aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--Documentation/arming_state_machine.odgbin0 -> 12021 bytes
-rw-r--r--Documentation/arming_state_machine.pdfbin0 -> 9039 bytes
-rw-r--r--Documentation/flight_mode_state_machine.odgbin0 -> 18105 bytes
-rw-r--r--Documentation/flight_mode_state_machine.pdfbin0 -> 23031 bytes
-rw-r--r--Documentation/rc_mode_switch.odgbin0 -> 14631 bytes
-rw-r--r--Documentation/rc_mode_switch.pdfbin0 -> 15841 bytes
-rw-r--r--ROMFS/Makefile4
-rwxr-xr-xROMFS/scripts/rcS10
-rw-r--r--apps/ChangeLog.txt57
-rw-r--r--apps/Kconfig4
-rw-r--r--apps/Make.defs15
-rw-r--r--apps/Makefile43
-rw-r--r--apps/README.txt146
-rw-r--r--apps/builtin/Kconfig17
-rw-r--r--apps/builtin/Make.defs (renamed from apps/namedapp/Make.defs)6
-rw-r--r--apps/builtin/Makefile (renamed from apps/namedapp/Makefile)64
-rw-r--r--apps/builtin/builtin.c80
-rw-r--r--apps/builtin/builtin_list.c (renamed from apps/namedapp/namedapp.c)31
-rw-r--r--apps/builtin/exec_builtin.c467
-rw-r--r--apps/builtin/registry/Makefile61
-rw-r--r--apps/drivers/bma180/bma180.cpp15
-rw-r--r--apps/examples/Kconfig2
-rw-r--r--apps/examples/Make.defs8
-rw-r--r--apps/examples/Makefile28
-rw-r--r--apps/examples/README.txt104
-rw-r--r--apps/examples/adc/Makefile9
-rw-r--r--apps/examples/buttons/Makefile9
-rw-r--r--apps/examples/can/Makefile9
-rw-r--r--apps/examples/cdcacm/Makefile11
-rw-r--r--apps/examples/hello/Makefile11
-rw-r--r--apps/examples/helloxx/Makefile9
-rw-r--r--apps/examples/nsh/nsh_main.c38
-rw-r--r--apps/examples/ostest/Makefile17
-rw-r--r--apps/examples/ostest/ostest.h46
-rw-r--r--apps/examples/ostest/ostest_main.c14
-rw-r--r--apps/examples/ostest/sighand.c63
-rw-r--r--apps/examples/ostest/vfork.c103
-rw-r--r--apps/examples/ostest/waitpid.c269
-rw-r--r--apps/examples/posix_spawn/Kconfig29
-rw-r--r--apps/examples/posix_spawn/Makefile130
-rw-r--r--apps/examples/posix_spawn/filesystem/Makefile88
-rw-r--r--apps/examples/posix_spawn/filesystem/hello/hello.c78
-rwxr-xr-xapps/examples/posix_spawn/filesystem/mksymtab.sh51
-rw-r--r--apps/examples/posix_spawn/filesystem/redirect/redirect.c63
-rw-r--r--apps/examples/posix_spawn/filesystem/testdata.txt2
-rw-r--r--apps/examples/posix_spawn/spawn_main.c460
-rw-r--r--apps/examples/pwm/Makefile9
-rw-r--r--apps/examples/qencoder/Makefile9
-rw-r--r--apps/examples/watchdog/Makefile9
-rw-r--r--apps/hott_telemetry/Makefile45
-rw-r--r--apps/hott_telemetry/hott_telemetry_main.c312
-rw-r--r--apps/hott_telemetry/messages.c87
-rw-r--r--apps/hott_telemetry/messages.h123
-rw-r--r--apps/include/builtin.h111
-rw-r--r--apps/interpreters/Makefile2
-rw-r--r--apps/interpreters/ficl/Makefile1
-rw-r--r--apps/mavlink/mavlink_receiver.c10
-rw-r--r--apps/namedapp/Kconfig15
-rw-r--r--apps/namedapp/namedapp_list.h42
-rw-r--r--apps/namedapp/namedapp_proto.h42
-rw-r--r--apps/nshlib/Kconfig19
-rw-r--r--apps/nshlib/Makefile7
-rw-r--r--apps/nshlib/README.txt2
-rw-r--r--apps/nshlib/nsh.h8
-rw-r--r--apps/nshlib/nsh_builtin.c (renamed from apps/nshlib/nsh_apps.c)94
-rw-r--r--apps/nshlib/nsh_codeccmd.c538
-rw-r--r--apps/nshlib/nsh_fileapps.c314
-rw-r--r--apps/nshlib/nsh_mntcmds.c77
-rw-r--r--apps/nshlib/nsh_netcmds.c6
-rw-r--r--apps/nshlib/nsh_parse.c138
-rw-r--r--apps/px4/tests/test_hott_telemetry.c239
-rw-r--r--apps/px4/tests/tests.h1
-rw-r--r--apps/px4/tests/tests_main.c1
-rw-r--r--apps/sensors/sensors.cpp101
-rw-r--r--apps/system/Makefile2
-rw-r--r--apps/system/free/Makefile10
-rw-r--r--apps/system/i2c/Makefile12
-rw-r--r--apps/system/install/Makefile10
-rw-r--r--apps/system/readline/Makefile1
-rw-r--r--apps/systemcmds/param/param.c78
-rw-r--r--apps/systemcmds/perf/perf.c10
-rw-r--r--apps/systemlib/Makefile3
-rw-r--r--apps/systemlib/airspeed.c8
-rw-r--r--apps/systemlib/airspeed.h11
-rw-r--r--apps/systemlib/conversions.c6
-rw-r--r--apps/systemlib/conversions.h5
-rw-r--r--apps/systemlib/perf_counter.c45
-rw-r--r--apps/systemlib/perf_counter.h13
-rw-r--r--nuttx/ChangeLog222
-rw-r--r--nuttx/Makefile.unix6
-rw-r--r--nuttx/Makefile.win19
-rw-r--r--nuttx/README.txt284
-rw-r--r--nuttx/TODO319
-rw-r--r--nuttx/arch/Kconfig148
-rw-r--r--nuttx/arch/README.txt12
-rw-r--r--nuttx/arch/arm/Kconfig30
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq.h146
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq_cmnvector.h6
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h6
-rw-r--r--nuttx/arch/arm/include/stm32/chip.h48
-rw-r--r--nuttx/arch/arm/include/types.h6
-rw-r--r--nuttx/arch/arm/src/armv7-m/Kconfig8
-rw-r--r--nuttx/arch/arm/src/armv7-m/Toolchain.defs19
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_assert.c7
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_doirq.c8
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_exception.S11
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_hardfault.c24
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_initialstate.c12
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c18
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_sigdeliver.c10
-rw-r--r--nuttx/arch/arm/src/armv7-m/vfork.S142
-rw-r--r--nuttx/arch/arm/src/common/up_internal.h4
-rw-r--r--nuttx/arch/arm/src/common/up_vfork.c233
-rw-r--r--nuttx/arch/arm/src/common/up_vfork.h88
-rw-r--r--nuttx/arch/arm/src/stm32/Kconfig19
-rw-r--r--nuttx/arch/arm/src/stm32/Make.defs9
-rw-r--r--nuttx/arch/arm/src/stm32/chip.h2
-rw-r--r--nuttx/arch/arm/src/stm32/stm32.h6
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_flash.c37
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_irq.c48
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_serial.c135
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_uart.h7
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_vectors.S17
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c56
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c11
-rw-r--r--nuttx/binfmt/Kconfig14
-rw-r--r--nuttx/binfmt/Makefile7
-rw-r--r--nuttx/binfmt/binfmt_exec.c79
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c20
-rw-r--r--nuttx/binfmt/binfmt_loadmodule.c45
-rw-r--r--nuttx/binfmt/binfmt_schedunload.c333
-rw-r--r--nuttx/binfmt/builtin.c198
-rw-r--r--nuttx/binfmt/elf.c2
-rw-r--r--nuttx/binfmt/libbuiltin/Kconfig4
-rw-r--r--nuttx/binfmt/libbuiltin/Make.defs52
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_getname.c96
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_isavail.c (renamed from apps/namedapp/exec_namedapp.c)122
-rw-r--r--nuttx/binfmt/libelf/Kconfig40
-rw-r--r--nuttx/binfmt/libelf/gnu-elf.ld129
-rw-r--r--nuttx/binfmt/libelf/libelf_ctors.c215
-rw-r--r--nuttx/binfmt/libelf/libelf_dtors.c215
-rw-r--r--nuttx/binfmt/libelf/libelf_init.c202
-rw-r--r--nuttx/binfmt/libelf/libelf_iobuffer.c136
-rw-r--r--nuttx/binfmt/libelf/libelf_sections.c284
-rw-r--r--nuttx/binfmt/libelf/libelf_symbols.c329
-rw-r--r--nuttx/binfmt/libelf/libelf_uninit.c126
-rw-r--r--nuttx/binfmt/libelf/libelf_verify.c120
-rw-r--r--nuttx/configs/README.txt130
-rw-r--r--nuttx/configs/px4fmu/nsh/appconfig1
-rwxr-xr-xnuttx/configs/px4fmu/nsh/defconfig10
-rw-r--r--nuttx/drivers/Kconfig3
-rw-r--r--nuttx/drivers/input/Kconfig19
-rw-r--r--nuttx/drivers/lcd/Make.defs4
-rw-r--r--nuttx/drivers/lcd/README.txt78
-rw-r--r--nuttx/drivers/lcd/ug-2864ambag01.c8
-rw-r--r--nuttx/drivers/lcd/ug-2864hsweg01.c1218
-rw-r--r--nuttx/drivers/mmcsd/Kconfig6
-rw-r--r--nuttx/drivers/mtd/Make.defs3
-rw-r--r--nuttx/drivers/usbdev/composite.c4
-rw-r--r--nuttx/drivers/usbdev/pl2303.c20
-rw-r--r--nuttx/drivers/usbhost/Kconfig64
-rw-r--r--nuttx/drivers/usbhost/usbhost_hidkbd.c405
-rw-r--r--nuttx/fs/Kconfig3
-rw-r--r--nuttx/fs/Makefile15
-rw-r--r--nuttx/fs/binfs/Kconfig19
-rw-r--r--nuttx/fs/binfs/Make.defs48
-rw-r--r--nuttx/fs/binfs/fs_binfs.c (renamed from apps/namedapp/binfs.c)346
-rw-r--r--nuttx/fs/fat/Make.defs9
-rw-r--r--nuttx/fs/fat/fs_fat32.c171
-rw-r--r--nuttx/fs/fat/fs_fat32.h1
-rw-r--r--nuttx/fs/fat/fs_fat32util.c10
-rw-r--r--nuttx/fs/fs_files.c18
-rw-r--r--nuttx/fs/fs_mount.c15
-rw-r--r--nuttx/fs/mmap/Make.defs9
-rw-r--r--nuttx/fs/nfs/Make.defs9
-rw-r--r--nuttx/fs/nfs/nfs_node.h3
-rw-r--r--nuttx/fs/nfs/nfs_util.c9
-rw-r--r--nuttx/fs/nfs/nfs_vfsops.c163
-rw-r--r--nuttx/fs/nfs/rpc_clnt.c28
-rw-r--r--nuttx/fs/nxffs/Make.defs9
-rw-r--r--nuttx/fs/nxffs/nxffs.h41
-rw-r--r--nuttx/fs/nxffs/nxffs_initialize.c4
-rw-r--r--nuttx/fs/nxffs/nxffs_open.c65
-rw-r--r--nuttx/fs/romfs/Make.defs9
-rw-r--r--nuttx/fs/romfs/fs_romfs.c258
-rw-r--r--nuttx/fs/romfs/fs_romfs.h1
-rw-r--r--nuttx/fs/romfs/fs_romfsutil.c12
-rw-r--r--nuttx/graphics/Kconfig6
-rw-r--r--nuttx/graphics/Makefile3
-rw-r--r--nuttx/graphics/nxfonts/Make.defs6
-rw-r--r--nuttx/graphics/nxfonts/Makefile.sources7
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_bitmaps.c2
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_getfont.c12
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_mono5x8.h815
-rw-r--r--nuttx/include/nuttx/arch.h2
-rw-r--r--nuttx/include/nuttx/binfmt/binfmt.h55
-rw-r--r--nuttx/include/nuttx/binfmt/builtin.h (renamed from apps/include/apps.h)109
-rw-r--r--nuttx/include/nuttx/clock.h2
-rw-r--r--nuttx/include/nuttx/fs/binfs.h83
-rw-r--r--nuttx/include/nuttx/fs/dirent.h6
-rw-r--r--nuttx/include/nuttx/fs/fs.h3
-rw-r--r--nuttx/include/nuttx/fs/ioctl.h5
-rw-r--r--nuttx/include/nuttx/input/kbd_codec.h347
-rw-r--r--nuttx/include/nuttx/lcd/hd4478ou.h118
-rw-r--r--nuttx/include/nuttx/lcd/ug-2864ambag01.h1
-rw-r--r--nuttx/include/nuttx/lcd/ug-2864hsweg01.h246
-rw-r--r--nuttx/include/nuttx/lcd/ug-9664hswag01.h1
-rw-r--r--nuttx/include/nuttx/net/mii.h168
-rw-r--r--nuttx/include/nuttx/nx/nxfonts.h11
-rw-r--r--nuttx/include/nuttx/progmem.h4
-rw-r--r--nuttx/include/nuttx/sched.h103
-rw-r--r--nuttx/include/nuttx/serial/tioctl.h23
-rw-r--r--nuttx/include/nuttx/spawn.h121
-rw-r--r--nuttx/include/nuttx/usb/hid.h2
-rw-r--r--nuttx/include/nuttx/wqueue.h2
-rw-r--r--nuttx/include/pthread.h152
-rw-r--r--nuttx/include/sched.h65
-rw-r--r--nuttx/include/semaphore.h10
-rw-r--r--nuttx/include/signal.h87
-rw-r--r--nuttx/include/spawn.h198
-rw-r--r--nuttx/include/stdbool.h4
-rw-r--r--nuttx/include/sys/types.h8
-rw-r--r--nuttx/include/sys/wait.h10
-rw-r--r--nuttx/include/unistd.h16
-rw-r--r--nuttx/libc/Kconfig89
-rw-r--r--nuttx/libc/Makefile1
-rw-r--r--nuttx/libc/lib_internal.h1
-rw-r--r--nuttx/libc/math/Kconfig2
-rw-r--r--nuttx/libc/misc/Make.defs6
-rw-r--r--nuttx/libc/misc/lib_filesem.c16
-rw-r--r--nuttx/libc/misc/lib_kbddecode.c267
-rw-r--r--nuttx/libc/misc/lib_kbdencode.c151
-rw-r--r--nuttx/libc/misc/lib_streamsem.c2
-rw-r--r--nuttx/libc/spawn/Make.defs63
-rw-r--r--nuttx/libc/spawn/lib_psa_dump.c127
-rw-r--r--nuttx/libc/spawn/lib_psa_getflags.c72
-rw-r--r--nuttx/libc/spawn/lib_psa_getschedparam.c74
-rw-r--r--nuttx/libc/spawn/lib_psa_getschedpolicy.c73
-rw-r--r--nuttx/libc/spawn/lib_psa_getsigmask.c78
-rw-r--r--nuttx/libc/spawn/lib_psa_init.c93
-rw-r--r--nuttx/libc/spawn/lib_psa_setflags.c71
-rw-r--r--nuttx/libc/spawn/lib_psa_setschedparam.c74
-rw-r--r--nuttx/libc/spawn/lib_psa_setschedpolicy.c72
-rw-r--r--nuttx/libc/spawn/lib_psa_setsigmask.c79
-rw-r--r--nuttx/libc/spawn/lib_psfa_addaction.c91
-rw-r--r--nuttx/libc/spawn/lib_psfa_addclose.c100
-rw-r--r--nuttx/libc/spawn/lib_psfa_adddup2.c104
-rw-r--r--nuttx/libc/spawn/lib_psfa_addopen.c119
-rw-r--r--nuttx/libc/spawn/lib_psfa_destroy.c96
-rw-r--r--nuttx/libc/spawn/lib_psfa_dump.c129
-rw-r--r--nuttx/libc/spawn/lib_psfa_init.c70
-rw-r--r--nuttx/libc/stdio/Make.defs2
-rw-r--r--nuttx/libc/stdio/lib_libfread.c3
-rw-r--r--nuttx/libc/stdio/lib_rawprintf.c15
-rw-r--r--nuttx/libc/stdio/lib_vdprintf.c81
-rw-r--r--nuttx/libc/string/lib_strndup.c11
-rw-r--r--nuttx/libc/unistd/Make.defs4
-rw-r--r--nuttx/libc/unistd/lib_execl.c146
-rw-r--r--nuttx/libc/unistd/lib_execsymtab.c147
-rw-r--r--nuttx/libc/unistd/lib_execv.c151
-rw-r--r--nuttx/net/Kconfig35
-rw-r--r--nuttx/net/net_internal.h62
-rw-r--r--nuttx/net/net_monitor.c93
-rw-r--r--nuttx/net/net_poll.c38
-rw-r--r--nuttx/net/recvfrom.c42
-rw-r--r--nuttx/net/send.c104
-rw-r--r--nuttx/sched/Kconfig188
-rw-r--r--nuttx/sched/Makefile174
-rw-r--r--nuttx/sched/clock_time2ticks.c42
-rw-r--r--nuttx/sched/mq_initialize.c4
-rw-r--r--nuttx/sched/os_bringup.c22
-rw-r--r--nuttx/sched/os_internal.h22
-rw-r--r--nuttx/sched/os_start.c13
-rw-r--r--nuttx/sched/pthread_create.c11
-rw-r--r--nuttx/sched/sched_addprioritized.c2
-rw-r--r--nuttx/sched/sched_addreadytorun.c8
-rw-r--r--nuttx/sched/sched_setuptaskfiles.c3
-rw-r--r--nuttx/sched/sched_unlock.c1
-rw-r--r--nuttx/sched/sched_wait.c90
-rw-r--r--nuttx/sched/sched_waitid.c331
-rw-r--r--nuttx/sched/sched_waitpid.c252
-rw-r--r--nuttx/sched/sig_action.c157
-rw-r--r--nuttx/sched/sig_kill.c7
-rw-r--r--nuttx/sched/sig_mqnotempty.c7
-rw-r--r--nuttx/sched/sig_queue.c13
-rw-r--r--nuttx/sched/sig_timedwait.c29
-rw-r--r--nuttx/sched/task_childstatus.c396
-rw-r--r--nuttx/sched/task_create.c18
-rw-r--r--nuttx/sched/task_deletecurrent.c20
-rw-r--r--nuttx/sched/task_exithook.c114
-rw-r--r--nuttx/sched/task_init.c3
-rw-r--r--nuttx/sched/task_posixspawn.c674
-rw-r--r--nuttx/sched/task_reparent.c163
-rw-r--r--nuttx/sched/task_setup.c101
-rw-r--r--nuttx/sched/task_vfork.c333
-rw-r--r--nuttx/sched/timer_settime.c4
-rw-r--r--nuttx/syscall/syscall.csv2
-rw-r--r--nuttx/tools/Makefile.export12
-rw-r--r--nuttx/tools/Makefile.host53
-rw-r--r--nuttx/tools/README.txt61
-rw-r--r--nuttx/tools/bdf-converter.c1
-rw-r--r--nuttx/tools/cfgdefine.c323
-rw-r--r--nuttx/tools/cfgdefine.h (renamed from apps/namedapp/namedapp.h)40
-rw-r--r--nuttx/tools/cfgparser.c162
-rw-r--r--nuttx/tools/cfgparser.h15
-rw-r--r--nuttx/tools/cmpconfig.c161
-rw-r--r--nuttx/tools/configure.bat127
-rw-r--r--nuttx/tools/configure.c890
-rwxr-xr-xnuttx/tools/configure.sh21
-rwxr-xr-xnuttx/tools/kconfig.bat131
-rw-r--r--nuttx/tools/mkconfig.c12
-rw-r--r--nuttx/tools/mksyscall.c6
-rw-r--r--nuttx/tools/mkversion.c4
314 files changed, 22039 insertions, 2506 deletions
diff --git a/.gitignore b/.gitignore
index ef0ed3c4c..8e9075ba4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,16 @@
.built
*.context
+*.bdat
+*.pdat
.depend
+.updated
.config
+.config-e
.version
.project
.cproject
-apps/namedapp/namedapp_list.h
-apps/namedapp/namedapp_proto.h
+apps/builtin/builtin_list.h
+apps/builtin/builtin_proto.h
Make.dep
*.pyc
*.o
@@ -43,6 +47,7 @@ nsh_romfsimg.h
cscope.out
.configX-e
nuttx-export.zip
+.~lock.*
dot.gdbinit
mavlink/include/mavlink/v0.9/
.*.swp
diff --git a/Documentation/arming_state_machine.odg b/Documentation/arming_state_machine.odg
new file mode 100644
index 000000000..cfadbab7c
--- /dev/null
+++ b/Documentation/arming_state_machine.odg
Binary files differ
diff --git a/Documentation/arming_state_machine.pdf b/Documentation/arming_state_machine.pdf
new file mode 100644
index 000000000..2c3e8be23
--- /dev/null
+++ b/Documentation/arming_state_machine.pdf
Binary files differ
diff --git a/Documentation/flight_mode_state_machine.odg b/Documentation/flight_mode_state_machine.odg
new file mode 100644
index 000000000..b630ecb40
--- /dev/null
+++ b/Documentation/flight_mode_state_machine.odg
Binary files differ
diff --git a/Documentation/flight_mode_state_machine.pdf b/Documentation/flight_mode_state_machine.pdf
new file mode 100644
index 000000000..cd234ada7
--- /dev/null
+++ b/Documentation/flight_mode_state_machine.pdf
Binary files differ
diff --git a/Documentation/rc_mode_switch.odg b/Documentation/rc_mode_switch.odg
new file mode 100644
index 000000000..e35a83372
--- /dev/null
+++ b/Documentation/rc_mode_switch.odg
Binary files differ
diff --git a/Documentation/rc_mode_switch.pdf b/Documentation/rc_mode_switch.pdf
new file mode 100644
index 000000000..823b1d868
--- /dev/null
+++ b/Documentation/rc_mode_switch.pdf
Binary files differ
diff --git a/ROMFS/Makefile b/ROMFS/Makefile
index ec4221b93..3b024de06 100644
--- a/ROMFS/Makefile
+++ b/ROMFS/Makefile
@@ -35,6 +35,10 @@ ROMFS_FSSPEC := $(SRCROOT)/scripts/rcS~init.d/rcS \
$(SRCROOT)/mixers/FMU_octo_+.mix~mixers/FMU_octo_+.mix \
$(SRCROOT)/logging/logconv.m~logging/logconv.m
+# the EXTERNAL_SCRIPTS variable is used to add out of tree scripts
+# to ROMFS.
+ROMFS_FSSPEC += $(EXTERNAL_SCRIPTS)
+
#
# Add the PX4IO firmware to the spec if someone has dropped it into the
# source directory, or otherwise specified its location.
diff --git a/ROMFS/scripts/rcS b/ROMFS/scripts/rcS
index 69d791da5..660bf61e9 100755
--- a/ROMFS/scripts/rcS
+++ b/ROMFS/scripts/rcS
@@ -69,6 +69,16 @@ else
fi
fi
+# if this is an APM build then there will be a rc.APM script
+# from an EXTERNAL_SCRIPTS build option
+if [ -f /etc/init.d/rc.APM ]
+then
+ echo Running rc.APM
+ # if APM startup is successful then nsh will exit
+ sh /etc/init.d/rc.APM
+fi
+
+
#
# If we are still in flight mode, work out what airframe
# configuration we have and start up accordingly.
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 0695747f8..bcc0ac172 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -435,3 +435,60 @@
logic to find the absolute path to the program using the PATH variable.
6.25 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * Makefiles: Removed dependency of distclean on clean in most top-level
+ files. It makes sense for 'leaf' Makefiles to have this dependency,
+ but it does not make sense for upper-level Makefiles.
+ * apps/namedapp/: Renamed to builtins in preparation for another change.
+ * .context: Removed the .context kludge. This caused lots of problems
+ when changing configurations because there is no easy way to get the
+ system to rebuild the context. Now, the context will be rebuilt
+ whenever there is a change in either .config or the Makefile.
+ * apps/builtin/registry: Updated new built-in registration logic to handle
+ cases where (1) old apps/.config is used, and (2) applications ared
+ removed, not just added.
+ * apps/examples/nettest/Makefile: Fix an error that crept in during
+ some of the recent, massive build system changes.
+ * apps/builtin/Makefile: Need to have auto-generated header files
+ in place early in the dependency generation phase to avoid warnings.
+ It is not important if they are only stubbed out header files at
+ this build phase.
+ * apps/examples/hidbkd: Now supports decoding of encoded special keys
+ if CONFIG_EXAMPLES_HIDKBD_ENCODED is defined.
+ * apps/examples/hidbkd: Add support for decoding key release events
+ as well. However, the USB HID keyboard drier has not yet been
+ updated to detect key release events. That is kind of tricky in
+ the USB HID keyboard report data.
+ * apps/examples/wlan: Remove non-functional example.
+ * apps/examples/ostest/vfork.c: Added a test of vfork().
+ * apps/exampes/posix_spawn: Added a test of poxis_spawn().
+ * apps/examples/ostest: Extend signal handler test to catch
+ death-of-child signals (SIGCHLD).
+ * apps/examples/ostest/waitpid.c: Add a test for waitpid(), waitid(),
+ and wait().
+ * builtin/binfs.c: Add hooks for dup() method (not implemented).
+ * builtin/exec_builtin.c, nshlib/nsh_parse.c, and nshlib/nsh_builtin.c:
+ NSH now supports re-direction of I/O to files (but still not from).
+ * builtin/binfs.c: Greatly simplified (it is going to need to be
+ very lightweight). Now supports open, close, and a new ioctl to recover
+ the builtin filename. The latter will be needed to support a binfs
+ binfmt.
+ * builtin/binfs.c: Move apps/builtin/binfs.c to fs/binfs/fs_binfs.c
+ CONFIG_APPS_BINDIR rename CONFIG_FS_BINFS
+ * apps/include/builtin.h: Some of the content of
+ apps/include/apps.h moved to include/nuttx/binfmt/builtin.h.
+ apps/include/apps.h renamed builtin.h
+ * apps/builtin/exec_builtins.c: Move utility builtin
+ utility functions from apps/builtin/exec_builtins.c to
+ binfmt/libbuiltin/libbuiltin_utils.c
+ * apps/nshlib/nsh_mountcmds.c: The block driver/source
+ argument is now optional. Many files systems do not need
+ a source and it is really stupid to have to enter a bogus
+ source parameter.
+ * apps/nshlib/nsh_fileapp.c: Add the ability to execute a file
+ from a file system using posix_spawn().
+ * apps/builtin/: Extensions from Mike Smith.
+ * apps/examples/ftpd/Makefile: Name ftpd_start is not the name of
+ the entrypoint. Should be ftpd_main (from Yan T.)
+ * apps/netutils/telnetd/telnetd_driver: Was stuck in a loop if
+ recv[from]() ever returned a value <= 0.
diff --git a/apps/Kconfig b/apps/Kconfig
index ea9bd2d31..68c36f5a5 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -3,8 +3,8 @@
# see misc/tools/kconfig-language.txt.
#
-menu "Named Applications"
-source "$APPSDIR/namedapp/Kconfig"
+menu "Built-In Applications"
+source "$APPSDIR/builtin/Kconfig"
endmenu
menu "Examples"
diff --git a/apps/Make.defs b/apps/Make.defs
index 53ac7f8be..f7e6aa08d 100644
--- a/apps/Make.defs
+++ b/apps/Make.defs
@@ -34,8 +34,17 @@
#
############################################################################
+BUILTIN_REGISTRY = $(APPDIR)$(DELIM)builtin$(DELIM)registry
+
+ifeq ($(CONFIG_NUTTX_NEWCONFIG),y)
+DEPCONFIG = $(TOPDIR)$(DELIM).config
+else
+DEPCONFIG = $(TOPDIR)$(DELIM).config $(APPDIR)$(DELIM).config
+endif
+
define REGISTER
- @echo "Register: $1"
- @echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/namedapp/namedapp_list.h"
- @echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/namedapp/namedapp_proto.h"
+ $(Q) echo "Register: $1"
+ $(Q) echo "{ \"$1\", $2, $3, $4 }," > "$(BUILTIN_REGISTRY)$(DELIM)$4.bdat"
+ $(Q) echo "int $4(int argc, char *argv[]);" > "$(BUILTIN_REGISTRY)$(DELIM)$4.pdat"
+ $(Q) touch "$(BUILTIN_REGISTRY)$(DELIM).updated"
endef
diff --git a/apps/Makefile b/apps/Makefile
index f0de58e25..d3078d069 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -45,14 +45,14 @@ APPDIR = ${shell pwd}
# action. It is created by the configured appconfig file (a copy of which
# 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
+# only for cleaning. builtin must always be the first in the list. This
# list can be extended by the .config file as well.
CONFIGURED_APPS =
-#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))
+SUBDIRS = examples interpreters builtin nshlib system
+
+#SUBDIRS = examples graphics interpreters modbus builtin nshlib netutils system
# There are two different mechanisms for obtaining the list of configured
# directories:
@@ -73,20 +73,20 @@ SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS))
ifeq ($(CONFIG_NUTTX_NEWCONFIG),y)
-# namedapp/Make.defs must be included first
+# builtin/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 netutils/Make.defs
--include nshlib/Make.defs
--include system/Make.defs
+include builtin/Make.defs
+include examples/Make.defs
+include graphics/Make.defs
+include interpreters/Make.defs
+include modbus/Make.defs
+include netutils/Make.defs
+include nshlib/Make.defs
+include system/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
-# application directory. namedapp is always in the list of applications to be
+# application directory. builtin is always in the list of applications to be
# built.
INSTALLED_APPS =
@@ -98,10 +98,10 @@ else
# INSTALLED_APPS is the list of currently available application directories. It
# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent
-# application directory. namedapp is always in the list of applications to be
+# application directory. builtin is always in the list of applications to be
# built.
-INSTALLED_APPS = namedapp
+INSTALLED_APPS = builtin
endif
# Create the list of available applications (INSTALLED_APPS)
@@ -139,21 +139,16 @@ $(INSTALLED_APPS):
$(BIN): $(INSTALLED_APPS)
-.context:
+context:
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
$(Q) for %%G in ($(INSTALLED_APPS)) do ( \
- if exist %%G\.context del /f /q %%G\.context \
$(MAKE) -C %%G TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context \
)
else
$(Q) for dir in $(INSTALLED_APPS) ; do \
- rm -f $$dir/.context ; \
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context ; \
done
endif
- $(Q) touch $@
-
-context: .context
.depend: context Makefile $(SRCS)
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
@@ -184,13 +179,12 @@ endif
$(call DELFILE, $(BIN))
$(call CLEAN)
-distclean: # clean
+distclean:
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
$(Q) for %%G in ($(SUBDIRS)) do ( \
$(MAKE) -C %%G distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" \
)
$(call DELFILE, .config)
- $(call DELFILE, .context)
$(call DELFILE, .depend)
$(Q) ( if exist external ( \
echo ********************************************************" \
@@ -202,7 +196,6 @@ else
$(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \
done
$(call DELFILE, .config)
- $(call DELFILE, .context)
$(call DELFILE, .depend)
$(Q) ( if [ -e external ]; then \
echo "********************************************************"; \
diff --git a/apps/README.txt b/apps/README.txt
index 7a379254e..55accfcf6 100644
--- a/apps/README.txt
+++ b/apps/README.txt
@@ -6,26 +6,25 @@ Contents
General
Directory Location
- Named Applications
- Named Startup main() function
+ Built-In Applications
NuttShell (NSH) Built-In Commands
Synchronous Built-In Commands
Application Configuration File
- Example Named Application
+ Example Built-In Application
Building NuttX with Board-Specific Pieces Outside the Source Tree
General
-------
This folder provides various applications found in sub-directories. These
-applications are not inherently a part of NuttX but are provided you help
+applications are not inherently a part of NuttX but are provided to help
you develop your own applications. The apps/ directory is a "break away"
-part of the configuration that you may chose to use or not.
+part of the configuration that you may choose to use or not.
Directory Location
------------------
The default application directory used by the NuttX build should be named
apps/ (or apps-x.y/ where x.y is the NuttX version number). This apps/
-directoy should appear in the directory tree at the same level as the
+directory should appear in the directory tree at the same level as the
NuttX directory. Like:
.
@@ -47,14 +46,14 @@ ways to do that:
path to the application directory on the configuration command line
like: ./configure.sh -a <app-dir> <board-name>/<config-name>
-Named Applications
-------------------
+Built-In Applications
+---------------------
NuttX also supports applications that can be started using a name string.
In this case, application entry points with their requirements are gathered
together in two files:
- - namedapp/namedapp_proto.h Entry points, prototype function
- - namedapp/namedapp_list.h Application specific information and requirements
+ - builtin/builtin_proto.h Entry points, prototype function
+ - builtin/builtin_list.h Application specific information and requirements
The build occurs in several phases as different build targets are executed:
(1) context, (2) depend, and (3) default (all). Application information is
@@ -62,18 +61,18 @@ collected during the make context build phase.
To execute an application function:
- exec_namedapp() is defined in the nuttx/include/apps/apps.h
+ exec_builtin() is defined in the nuttx/include/apps/builtin.h
NuttShell (NSH) Built-In Commands
---------------------------------
-One use of named applications is to provide a way of invoking your custom
+One use of builtin applications is to provide a way of invoking your custom
application through the NuttShell (NSH) command line. NSH will support
a seamless method invoking the applications, when the following option is
enabled in the NuttX configuration file:
CONFIG_NSH_BUILTIN_APPS=y
-Applications registered in the apps/namedapp/namedapp_list.h file will then
+Applications registered in the apps/builtin/builtin_list.h file will then
be accessible from the NSH command line. If you type 'help' at the NSH
prompt, you will see a list of the registered commands.
@@ -96,11 +95,11 @@ after the NSH command.
Application Configuration File
------------------------------
-A special configuration file is used to configure which applications
-are to be included in the build. The source for this file is
-configs/<board>/<configuration>/appconfig. The existence of the appconfig
-file in the board configuration directory is sufficient to enable building
-of applications.
+The old-style NuttX configuration uses a special configuration file is
+used to configure which applications are to be included in the build.
+The source for this file is configs/<board>/<configuration>/appconfig.
+The existence of the appconfig file in the board configuration directory\
+is sufficient to enable building of applications.
The appconfig file is copied into the apps/ directory as .config when
NuttX is configured. .config is included in the toplevel apps/Makefile.
@@ -109,38 +108,101 @@ CONFIGURED_APPS list like:
CONFIGURED_APPS += examples/hello system/poweroff
-Named Start-Up main() function
-------------------------------
-A named application can even be used as the main, start-up entry point
-into your embedded software. When the user defines this option in
-the NuttX configuration file:
+The new NuttX configuration uses kconfig-frontends tools and only the
+NuttX .config file. The new configuration is indicated by the existence
+of the definition CONFIG_NUTTX_NEWCONFIG=y in the NuttX .config file.
+If CONFIG_NUTTX_NEWCONFIG is defined, then the Makefile will:
+
+- Assume that there is no apps/.config file and will instead
+- Include Make.defs files from each of the subdirectories.
+
+When an application is enabled using the kconfig-frontends tool, then
+a new definition is added to the NuttX .config file. For example, if
+you want to enable apps/examples/hello then the old apps/.config would
+have had:
+
+ CONFIGURED_APPS += examples/hello
+
+But in the new configuration there will be no apps/.config file and,
+instead, the NuttX .config will have:
+
+ CONFIG_EXAMPLES_HELLO=y
- CONFIG_BUILTIN_APP_START=<application name>
-
-that application shall be invoked immediately after system starts
-*instead* of the default "user_start" entry point.
-Note that <application name> must be provided as: "hello",
-will call:
+This will select the apps/examples/hello in the following way:
- int hello_main(int argc, char *argv[])
+- The top-level make will include examples/Make.defs
+- examples/Make.defs will set CONFIGURED_APPS += examples/hello
+ like this:
-Example Named Application
--------------------------
+ ifeq ($(CONFIG_EXAMPLES_HELLO),y)
+ CONFIGURED_APPS += examples/hello
+ endif
+
+Thus accomplishing the same thing with no apps/.config file.
+
+Example Built-In Application
+----------------------------
An example application skeleton can be found under the examples/hello
-sub-directory. This example shows how a named application can be added
+sub-directory. This example shows how a builtin application can be added
to the project. One must define:
- 1. create sub-directory as: appname
- 2. provide entry point: appname_main()
- 3. set the requirements in the file: Makefile, specially the lines:
+Old configuration method:
+
+ 1. Create sub-directory as: appname
+
+ 2. In this directory there should be:
+
+ - A Makefile, and
+ - The application source code.
+
+ 3. The application source code should provide the entry point:
+ appname_main()
+
+ 4. Set the requirements in the file: Makefile, specially the lines:
+
+ APPNAME = appname
+ PRIORITY = SCHED_PRIORITY_DEFAULT
+ STACKSIZE = 768
+ ASRCS = asm source file list as a.asm b.asm ...
+ CSRCS = C source file list as foo1.c foo2.c ..
+
+ Look at some of the other Makefiles for examples. Note the
+ special registration logic needed for the context: target
+
+ 5. Add the to the application to the CONFIGIURED_APPS in the
+ apps/.config file:
+
+ CONFIGURED_APPS += appname
+
+New Configuration Method:
+
+ 1. Create sub-directory as: appname
+
+ 2. In this directory there should be:
+
+ - A Make.defs file that would be included by the apps/Makefile
+ - A Kconfig file that would be used by the configuration tool (see
+ misc/tools/kconfig-language.txt). This Kconfig file should be
+ included by the apps/Kconfig file
+ - A Makefile, and
+ - The application source code.
+
+ 3. The application source code should provide the entry point:
+ appname_main()
+
+ 4. Set the requirements in the file: Makefile, specially the lines:
+
+ APPNAME = appname
+ PRIORITY = SCHED_PRIORITY_DEFAULT
+ STACKSIZE = 768
+ ASRCS = asm source file list as a.asm b.asm ...
+ CSRCS = C source file list as foo1.c foo2.c ..
- APPNAME = appname
- PRIORITY = SCHED_PRIORITY_DEFAULT
- STACKSIZE = 768
- ASRCS = asm source file list as a.asm b.asm ...
- CSRCS = C source file list as foo1.c foo2.c ..
+ 4b. The Make.defs file should include a line like:
- 4. add application in the apps/.config
+ ifeq ($(CONFIG_APPNAME),y)
+ CONFIGURED_APPS += appname
+ endif
Building NuttX with Board-Specific Pieces Outside the Source Tree
-----------------------------------------------------------------
diff --git a/apps/builtin/Kconfig b/apps/builtin/Kconfig
new file mode 100644
index 000000000..c3371d708
--- /dev/null
+++ b/apps/builtin/Kconfig
@@ -0,0 +1,17 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+if BUILTIN
+
+config BUILTIN_PROXY_STACKSIZE
+ int "Builtin Proxy Stack Size"
+ default 1024
+ ---help---
+ If exec_builtin uses I/O redirection options, then it will require
+ an intermediary/proxy task to muck with the file descriptors. This
+ configuration item specifies the stack size used for the proxy. Default:
+ 1024 bytes.
+
+endif
diff --git a/apps/namedapp/Make.defs b/apps/builtin/Make.defs
index 399fefee8..ab6292cc3 100644
--- a/apps/namedapp/Make.defs
+++ b/apps/builtin/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/namedapps/Make.defs
+# apps/builtin/Make.defs
# Adds selected applications to apps/ build
#
# Copyright (C) 2012 Gregory Nutt. All rights reserved.
@@ -34,7 +34,7 @@
#
############################################################################
-ifeq ($(CONFIG_NAMEDAPP),y)
-CONFIGURED_APPS += namedapp
+ifeq ($(CONFIG_BUILTIN),y)
+CONFIGURED_APPS += builtin
endif
diff --git a/apps/namedapp/Makefile b/apps/builtin/Makefile
index a88c73567..f89532871 100644
--- a/apps/namedapp/Makefile
+++ b/apps/builtin/Makefile
@@ -1,5 +1,5 @@
############################################################################
-# apps/nshlib/Makefile
+# apps/builtin/Makefile
#
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
@@ -33,20 +33,13 @@
#
############################################################################
--include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs
-# NSH Library
-
# Source and object files
ASRCS =
-CSRCS = namedapp.c exec_namedapp.c
-
-ifeq ($(CONFIG_APPS_BINDIR),y)
-CSRCS += binfs.c
-endif
+CSRCS = builtin.c builtin_list.c exec_builtin.c
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
@@ -70,7 +63,7 @@ VPATH =
# Build Targets
all: .built
-.PHONY: .context context depend clean distclean
+.PHONY: context depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
@@ -78,33 +71,60 @@ $(AOBJS): %$(OBJEXT): %.S
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
-.built: $(OBJS)
+registry$(DELIM).updated:
+ $(V) $(MAKE) -C registry .updated TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
+
+builtin_list.h: registry$(DELIM).updated
+ $(call DELFILE, builtin_list.h)
+ $(Q) touch builtin_list.h
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ $(Q) for /f %%G in ('dir /b registry\*.bdat`) do ( type registry\%%G >> builtin_list.h )
+else
+ $(Q) ( \
+ filelist=`ls registry/*.bdat 2>/dev/null || echo ""`; \
+ for file in $$filelist; \
+ do cat $$file >> builtin_list.h; \
+ done; \
+ )
+endif
+
+builtin_proto.h: registry$(DELIM).updated
+ $(call DELFILE, builtin_proto.h)
+ $(Q) touch builtin_proto.h
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ $(Q) for /f %%G in ('dir /b registry\*.pdat`) do ( type registry\%%G >> builtin_proto.h )
+else
+ $(Q) ( \
+ filelist=`ls registry/*.pdat 2>/dev/null || echo ""`; \
+ for file in $$filelist; \
+ do cat $$file >> builtin_proto.h; \
+ done; \
+ )
+endif
+
+.built: builtin_list.h builtin_proto.h $(OBJS)
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built
-.context:
- @echo "/* List of application requirements, generated during make context. */" > namedapp_list.h
- @echo "/* List of application entry points, generated during make context. */" > namedapp_proto.h
- $(Q) touch $@
-
-context: .context
+context:
+ $(Q) $(MAKE) -C registry context TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
-.depend: Makefile $(SRCS)
+.depend: Makefile $(SRCS) builtin_list.h builtin_proto.h
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
clean:
+ $(Q) $(MAKE) -C registry clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
$(call DELFILE, .built)
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
+ $(Q) $(MAKE) -C registry distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
- $(call DELFILE, namedapp_list.h)
- $(call DELFILE, namedapp_proto.h)
+ $(call DELFILE, builtin_list.h)
+ $(call DELFILE, builtin_proto.h)
-include Make.dep
-
diff --git a/apps/builtin/builtin.c b/apps/builtin/builtin.c
new file mode 100644
index 000000000..d26f0a044
--- /dev/null
+++ b/apps/builtin/builtin.c
@@ -0,0 +1,80 @@
+/****************************************************************************
+ * apps/builtin/builtin.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Authors: Uros Platise <uros.platise@isotel.eu>
+ * Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern const struct builtin_s g_builtins[];
+extern const int g_builtin_count;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+FAR const struct builtin_s *builtin_for_index(int index)
+{
+ if (index < g_builtin_count)
+ {
+ return &g_builtins[index];
+ }
+ return NULL;
+}
diff --git a/apps/namedapp/namedapp.c b/apps/builtin/builtin_list.c
index d59ce6e3b..a5556bf54 100644
--- a/apps/namedapp/namedapp.c
+++ b/apps/builtin/builtin_list.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * apps/namedaps/namedapp.c
+ * apps/builtin/builtin_list.c
*
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
@@ -40,7 +40,8 @@
****************************************************************************/
#include <nuttx/config.h>
-#include <apps/apps.h>
+
+#include <nuttx/binfmt/builtin.h>
/****************************************************************************
* Private Types
@@ -54,27 +55,15 @@
* Public Data
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
-#include "namedapp_proto.h"
+#include "builtin_proto.h"
-const struct namedapp_s namedapps[] =
+const struct builtin_s g_builtins[] =
{
-# include "namedapp_list.h"
+# include "builtin_list.h"
{ NULL, 0, 0, 0 }
};
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
-
+const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);
/****************************************************************************
* Private Data
@@ -88,9 +77,3 @@ const struct namedapp_s namedapps[] =
* Public Functions
****************************************************************************/
-int number_namedapps(void)
-{
- return sizeof(namedapps)/sizeof(struct namedapp_s) - 1;
-}
-
-
diff --git a/apps/builtin/exec_builtin.c b/apps/builtin/exec_builtin.c
new file mode 100644
index 000000000..60e8b742d
--- /dev/null
+++ b/apps/builtin/exec_builtin.c
@@ -0,0 +1,467 @@
+/****************************************************************************
+ * apps/builtin/exec_builtin.c
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/wait.h>
+#include <sched.h>
+#include <string.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/builtin.h>
+#include <apps/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_BUILTIN_PROXY_STACKSIZE
+# define CONFIG_BUILTIN_PROXY_STACKSIZE 1024
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct builtin_parms_s
+{
+ /* Input values */
+
+ FAR const char *redirfile;
+ FAR const char **argv;
+ int oflags;
+ int index;
+
+ /* Returned values */
+
+ pid_t result;
+ int errcode;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_builtin_parmsem = SEM_INITIALIZER(1);
+#ifndef CONFIG_SCHED_WAITPID
+static sem_t g_builtin_execsem = SEM_INITIALIZER(0);
+#endif
+static struct builtin_parms_s g_builtin_parms;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bultin_semtake and builtin_semgive
+ *
+ * Description:
+ * Give and take semaphores
+ *
+ * Input Parameters:
+ *
+ * sem - The semaphore to act on.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void bultin_semtake(FAR sem_t *sem)
+{
+ int ret;
+
+ do
+ {
+ ret = sem_wait(sem);
+ ASSERT(ret == 0 || get_errno() == EINTR);
+ }
+ while (ret != 0);
+}
+
+#define builtin_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: builtin_taskcreate
+ *
+ * Description:
+ * Execute the builtin task
+ *
+ * Returned Value:
+ * On success, the task ID of the builtin task is returned; On failure, -1
+ * (ERROR) is returned and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+static int builtin_taskcreate(int index, FAR const char **argv)
+{
+ FAR const struct builtin_s *b;
+ int ret;
+
+ b = builtin_for_index(index);
+
+ if (b == NULL)
+ {
+ set_errno(ENOENT);
+ return ERROR;
+ }
+
+ /* Disable pre-emption. This means that although we start the builtin
+ * application here, it will not actually run until pre-emption is
+ * re-enabled below.
+ */
+
+ sched_lock();
+
+ /* Start the builtin application task */
+
+ ret = TASK_CREATE(b->name, b->priority, b->stacksize, b->main,
+ (argv) ? &argv[1] : (FAR const char **)NULL);
+
+ /* If robin robin scheduling is enabled, then set the scheduling policy
+ * of the new task to SCHED_RR before it has a chance to run.
+ */
+
+#if CONFIG_RR_INTERVAL > 0
+ if (ret > 0)
+ {
+ struct sched_param param;
+
+ /* Pre-emption is disabled so the task creation and the
+ * following operation will be atomic. The priority of the
+ * new task cannot yet have changed from its initial value.
+ */
+
+ param.sched_priority = b->priority;
+ (void)sched_setscheduler(ret, SCHED_RR, &param);
+ }
+#endif
+
+ /* Now let the builtin application run */
+
+ sched_unlock();
+
+ /* Return the task ID of the new task if the task was sucessfully
+ * started. Otherwise, ret will be ERROR (and the errno value will
+ * be set appropriately).
+ */
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: builtin_proxy
+ *
+ * Description:
+ * Perform output redirection, then execute the builtin task.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * Standard task return value.
+ *
+ ****************************************************************************/
+
+static int builtin_proxy(int argc, char *argv[])
+{
+ int fd;
+ int ret = ERROR;
+
+ /* Open the output file for redirection */
+
+ svdbg("Open'ing redirfile=%s oflags=%04x mode=0644\n",
+ g_builtin_parms.redirfile, g_builtin_parms.oflags);
+
+ fd = open(g_builtin_parms.redirfile, g_builtin_parms.oflags, 0644);
+ if (fd < 0)
+ {
+ /* Remember the errno value. ret is already set to ERROR */
+
+ g_builtin_parms.errcode = get_errno();
+ sdbg("ERROR: open of %s failed: %d\n",
+ g_builtin_parms.redirfile, g_builtin_parms.errcode);
+ }
+
+ /* Does the return file descriptor happen to match the required file
+ * desciptor number?
+ */
+
+ else if (fd != 1)
+ {
+ /* No.. dup2 to get the correct file number */
+
+ svdbg("Dup'ing %d->1\n", fd);
+
+ ret = dup2(fd, 1);
+ if (ret < 0)
+ {
+ g_builtin_parms.errcode = get_errno();
+ sdbg("ERROR: dup2 failed: %d\n", g_builtin_parms.errcode);
+ }
+
+ svdbg("Closing fd=%d\n", fd);
+ close(fd);
+ }
+
+ /* Was the setup successful? */
+
+ if (ret == OK)
+ {
+ /* Yes.. Start the task. On success, the task ID of the builtin task
+ * is returned; On failure, -1 (ERROR) is returned and the errno
+ * is set appropriately.
+ */
+
+ ret = builtin_taskcreate(g_builtin_parms.index, g_builtin_parms.argv);
+ if (ret < 0)
+ {
+ g_builtin_parms.errcode = get_errno();
+ sdbg("ERROR: builtin_taskcreate failed: %d\n",
+ g_builtin_parms.errcode);
+ }
+ }
+
+ /* NOTE: There is a logical error here if CONFIG_SCHED_HAVE_PARENT is
+ * defined: The new task is the child of this proxy task, not the
+ * original caller. As a consequence, operations like waitpid() will
+ * fail on the caller's thread.
+ */
+
+ /* Post the semaphore to inform the parent task that we have completed
+ * what we need to do.
+ */
+
+ g_builtin_parms.result = ret;
+#ifndef CONFIG_SCHED_WAITPID
+ builtin_semgive(&g_builtin_execsem);
+#endif
+ return 0;
+}
+
+/****************************************************************************
+ * Name: builtin_startproxy
+ *
+ * Description:
+ * Perform output redirection, then execute the builtin task.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * On success, the task ID of the builtin task is returned; On failure, -1
+ * (ERROR) is returned and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+static inline int builtin_startproxy(int index, FAR const char **argv,
+ FAR const char *redirfile, int oflags)
+{
+ struct sched_param param;
+ pid_t proxy;
+ int errcode;
+#ifdef CONFIG_SCHED_WAITPID
+ int status;
+#endif
+ int ret;
+
+ svdbg("index=%d argv=%p redirfile=%s oflags=%04x\n",
+ index, argv, redirfile, oflags);
+
+ /* We will have to go through an intermediary/proxy task in order to
+ * perform the I/O redirection. This would be a natural place to fork().
+ * However, true fork() behavior requires an MMU and most implementations
+ * of vfork() are not capable of these operations.
+ *
+ * Even without fork(), we can still do the job, but parameter passing is
+ * messier. Unfortunately, there is no (clean) way to pass binary values
+ * as a task parameter, so we will use a semaphore-protected global
+ * structure.
+ */
+
+ /* Get exclusive access to the global parameter structure */
+
+ bultin_semtake(&g_builtin_parmsem);
+
+ /* Populate the parameter structure */
+
+ g_builtin_parms.redirfile = redirfile;
+ g_builtin_parms.argv = argv;
+ g_builtin_parms.result = ERROR;
+ g_builtin_parms.oflags = oflags;
+ g_builtin_parms.index = index;
+
+ /* Get the priority of this (parent) task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ errcode = get_errno();
+ sdbg("ERROR: sched_getparam failed: %d\n", errcode);
+ goto errout_with_sem;
+ }
+
+ /* Disable pre-emption so that the proxy does not run until we waitpid
+ * is called. This is probably unnecessary since the builtin_proxy has
+ * the same priority as this thread; it should be schedule behind this
+ * task in the ready-to-run list.
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ sched_lock();
+#endif
+
+ /* Start the intermediary/proxy task at the same priority as the parent task. */
+
+ proxy = TASK_CREATE("builtin_proxy", param.sched_priority,
+ CONFIG_BUILTIN_PROXY_STACKSIZE, (main_t)builtin_proxy,
+ (FAR const char **)NULL);
+ if (proxy < 0)
+ {
+ errcode = get_errno();
+ sdbg("ERROR: Failed to start builtin_proxy: %d\n", errcode);
+ goto errout_with_lock;
+ }
+
+ /* Wait for the proxy to complete its job. We could use waitpid()
+ * for this.
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ ret = waitpid(proxy, &status, 0);
+ if (ret < 0)
+ {
+ sdbg("ERROR: waitpid() failed: %d\n", get_errno());
+ goto errout_with_lock;
+ }
+#else
+ bultin_semtake(&g_builtin_execsem);
+#endif
+
+ /* Get the result and relinquish our access to the parameter structure */
+
+ set_errno(g_builtin_parms.errcode);
+ builtin_semgive(&g_builtin_parmsem);
+ return g_builtin_parms.result;
+
+errout_with_lock:
+#ifdef CONFIG_SCHED_WAITPID
+ sched_unlock();
+#endif
+
+errout_with_sem:
+ set_errno(errcode);
+ builtin_semgive(&g_builtin_parmsem);
+ return ERROR;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_builtin
+ *
+ * Description:
+ * Executes builtin applications registered during 'make context' time.
+ * New application is run in a separate task context (and thread).
+ *
+ * Input Parameter:
+ * filename - Name of the linked-in binary to be started.
+ * argv - Argument list
+ * redirfile - If output if redirected, this parameter will be non-NULL
+ * and will provide the full path to the file.
+ * oflags - If output is redirected, this parameter will provide the
+ * open flags to use. This will support file replacement
+ * of appending to an existing file.
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * Returns the PID of the exec'ed module. On failure, it.returns
+ * -1 (ERROR) and sets errno appropriately.
+ *
+ ****************************************************************************/
+
+int exec_builtin(FAR const char *appname, FAR const char **argv,
+ FAR const char *redirfile, int oflags)
+{
+ int index;
+ int ret = ERROR;
+
+ /* Verify that an application with this name exists */
+
+ index = builtin_isavail(appname);
+ if (index >= 0)
+ {
+ /* Is output being redirected? */
+
+ if (redirfile)
+ {
+ ret = builtin_startproxy(index, argv, redirfile, oflags);
+ }
+ else
+ {
+ /* Start the builtin application task */
+
+ ret = builtin_taskcreate(index, argv);
+ }
+ }
+
+
+ /* Return the task ID of the new task if the task was sucessfully
+ * started. Otherwise, ret will be ERROR (and the errno value will
+ * be set appropriately).
+ */
+
+ return ret;
+}
diff --git a/apps/builtin/registry/Makefile b/apps/builtin/registry/Makefile
new file mode 100644
index 000000000..4ecd5da9f
--- /dev/null
+++ b/apps/builtin/registry/Makefile
@@ -0,0 +1,61 @@
+############################################################################
+# apps/builtin/registry/Makefile
+#
+# Copyright (C) 2012 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# NSH Library
+
+all:
+.PHONY: context depend clean distclean
+
+.updated: $(DEPCONFIG)
+ $(call DELFILE, *.bdat)
+ $(call DELFILE, *.pdat)
+ $(Q) touch .updated
+
+# This must run before any other context target
+
+context: .updated
+
+depend:
+
+clean:
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, *.bdat)
+ $(call DELFILE, *.pdat)
+ $(call DELFILE, .updated)
diff --git a/apps/drivers/bma180/bma180.cpp b/apps/drivers/bma180/bma180.cpp
index bc4d4b3bf..32eb5333e 100644
--- a/apps/drivers/bma180/bma180.cpp
+++ b/apps/drivers/bma180/bma180.cpp
@@ -714,14 +714,17 @@ BMA180::measure()
* perform only the axis assignment here.
* Two non-value bits are discarded directly
*/
- report->y_raw = (((int16_t)read_reg(ADDR_ACC_X_LSB + 1)) << 8) | (read_reg(ADDR_ACC_X_LSB)); // XXX PX4DEV raw_report.x;
- report->x_raw = (((int16_t)read_reg(ADDR_ACC_X_LSB + 3)) << 8) | (read_reg(ADDR_ACC_X_LSB + 2)); // XXX PX4DEV raw_report.y;
- report->z_raw = (((int16_t)read_reg(ADDR_ACC_X_LSB + 5)) << 8) | (read_reg(ADDR_ACC_X_LSB + 4)); // XXX PX4DEV raw_report.z;
+ report->y_raw = read_reg(ADDR_ACC_X_LSB + 0);
+ report->y_raw |= read_reg(ADDR_ACC_X_LSB + 1) << 8;
+ report->x_raw = read_reg(ADDR_ACC_X_LSB + 2);
+ report->x_raw |= read_reg(ADDR_ACC_X_LSB + 3) << 8;
+ report->z_raw = read_reg(ADDR_ACC_X_LSB + 4);
+ report->z_raw |= read_reg(ADDR_ACC_X_LSB + 5) << 8;
/* discard two non-value bits in the 16 bit measurement */
- report->x_raw = (report->x_raw >> 2);
- report->y_raw = (report->y_raw >> 2);
- report->z_raw = (report->z_raw >> 2);
+ report->x_raw = (report->x_raw / 4);
+ report->y_raw = (report->y_raw / 4);
+ report->z_raw = (report->z_raw / 4);
/* invert y axis, due to 14 bit data no overflow can occur in the negation */
report->y_raw = -report->y_raw;
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig
index ae5f0a61a..ec0a97dd4 100644
--- a/apps/examples/Kconfig
+++ b/apps/examples/Kconfig
@@ -39,6 +39,7 @@ source "$APPSDIR/examples/pashello/Kconfig"
source "$APPSDIR/examples/pipe/Kconfig"
source "$APPSDIR/examples/poll/Kconfig"
source "$APPSDIR/examples/pwm/Kconfig"
+source "$APPSDIR/examples/posix_spawn/Kconfig"
source "$APPSDIR/examples/qencoder/Kconfig"
source "$APPSDIR/examples/relays/Kconfig"
source "$APPSDIR/examples/rgmp/Kconfig"
@@ -58,5 +59,4 @@ source "$APPSDIR/examples/usbterm/Kconfig"
source "$APPSDIR/examples/watchdog/Kconfig"
source "$APPSDIR/examples/wget/Kconfig"
source "$APPSDIR/examples/wgetjson/Kconfig"
-source "$APPSDIR/examples/wlan/Kconfig"
source "$APPSDIR/examples/xmlrpc/Kconfig"
diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs
index 91f1331df..68d4d4340 100644
--- a/apps/examples/Make.defs
+++ b/apps/examples/Make.defs
@@ -182,6 +182,10 @@ ifeq ($(CONFIG_EXAMPLES_PWM),y)
CONFIGURED_APPS += examples/pwm
endif
+ifeq ($(CONFIG_EXAMPLES_POSIXSPAWN),y)
+CONFIGURED_APPS += examples/posix_spawn
+endif
+
ifeq ($(CONFIG_EXAMPLES_QENCODER),y)
CONFIGURED_APPS += examples/qencoder
endif
@@ -254,10 +258,6 @@ ifeq ($(CONFIG_EXAMPLES_WGETJSON),y)
CONFIGURED_APPS += examples/wgetjson
endif
-ifeq ($(CONFIG_EXAMPLES_WLAN),y)
-CONFIGURED_APPS += examples/wlan
-endif
-
ifeq ($(CONFIG_EXAMPLES_XMLRPC),y)
CONFIGURED_APPS += examples/xmlrpc
endif
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index bdbfd4de8..201be955b 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -37,12 +37,15 @@
# Sub-directories
-SUBDIRS = adc buttons can cdcacm composite cxxtest dhcpd discover elf ftpc
-SUBDIRS += ftpd hello helloxx hidkbd igmp json keypadtest lcdrw mm modbus mount
-SUBDIRS += nettest nsh null nx nxconsole nxffs nxflat nxhello nximage
-SUBDIRS += nxlines nxtext ostest pashello pipe poll pwm qencoder relays
-SUBDIRS += rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip
-SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson wlan
+SUBDIRS = adc can cdcacm nsh
+SUBDIRS += math_demo control_demo kalman_demo px4_deamon_app
+
+#SUBDIRS = adc buttons can cdcacm composite cxxtest dhcpd discover elf ftpc
+#SUBDIRS += ftpd hello helloxx hidkbd igmp json keypadtest lcdrw mm modbus mount
+#SUBDIRS += nettest nsh null nx nxconsole nxffs nxflat nxhello nximage
+#SUBDIRS += nxlines nxtext ostest pashello pipe poll pwm posix_spawn qencoder
+#SUBDIRS += relays rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip
+#SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@@ -57,13 +60,14 @@ SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson wlan
CNTXTDIRS = pwm
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
-CNTXTDIRS += adc can cdcacm composite cxxtest dhcpd discover ftpd json keypadtest
-CNTXTDIRS += modbus nettest nxlines relays qencoder telnetd watchdog wgetjson
-endif
-ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y)
-CNTXTDIRS += hello
+CNTXTDIRS += adc can cdcacm
+
+#CNTXTDIRS += adc can cdcacm composite cxxtest dhcpd discover ftpd hello json
+#CNTXTDIRS += keypadtestmodbus nettest nxlines relays qencoder telnetd watchdog
+#CNTXTDIRS += wgetjson
endif
+
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
CNTXTDIRS += helloxx
endif
@@ -120,7 +124,7 @@ depend: $(foreach SDIR, $(SUBDIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(SUBDIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(SUBDIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(SUBDIRS), $(SDIR)_distclean)
-include Make.dep
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index e40a63be9..5996cbb70 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -329,10 +329,10 @@ examples/elf
each program in the ROMFS file system is executed. Requires CONFIG_ELF.
Other configuration options:
- CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block.
- For example, the N in /dev/ramN. Used for registering the RAM block driver
- that will hold the ROMFS file system containing the ELF executables to be
- tested. Default: 0
+ CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block
+ driver. For example, the N in /dev/ramN. Used for registering the RAM
+ block driver that will hold the ROMFS file system containing the ELF
+ executables to be tested. Default: 0
CONFIG_EXAMPLES_ELF_DEVPATH - The path to the ROMFS block driver device. This
must match EXAMPLES_ELF_DEVMINOR. Used for registering the RAM block driver
@@ -348,7 +348,7 @@ examples/elf
Similarly for C++ flags which must be provided in CXXELFFLAGS.
- 2. Your top-level nuttx/Make.defs file must alos include an approproate definition,
+ 2. Your top-level nuttx/Make.defs file must also include an approproate definition,
LDELFFLAGS, to generate a relocatable ELF object. With GNU LD, this should
include '-r' and '-e main' (or _main on some platforms).
@@ -491,7 +491,7 @@ examples/hello
than examples/null with a single printf statement. Really useful only
for bringing up new NuttX architectures.
- * CONFIG_EXAMPLES_HELLO_BUILTIN
+ * CONFIG_NSH_BUILTIN_APPS
Build the "Hello, World" example as an NSH built-in application.
examples/helloxx
@@ -540,9 +540,21 @@ examples/hidkbd
This is a simple test to debug/verify the USB host HID keyboard class
driver.
- CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread.
- CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread.
-
+ CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread. Default:
+ 50
+ CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread. Default
+ 1024
+ CONFIG_EXAMPLES_HIDKBD_DEVNAME - Name of keyboard device to be used.
+ Default: "/dev/kbda"
+ CONFIG_EXAMPLES_HIDKBD_ENCODED - Decode special key press events in the
+ user buffer. In this case, the example coded will use the interfaces
+ defined in include/nuttx/input/kbd_codec.h to decode the returned
+ keyboard data. These special keys include such things as up/down
+ arrows, home and end keys, etc. If this not defined, only 7-bit print-
+ able and control ASCII characters will be provided to the user.
+ Requires CONFIG_HIDKBD_ENCODED && CONFIG_LIB_KBDCODEC
+
+endif
examples/igmp
^^^^^^^^^^^^^
@@ -1190,6 +1202,80 @@ examples/poll
CONFIGURED_APPS += uiplib
+examples/posix_spawn
+^^^^^^^^^^^^^^^^^^^^
+
+ This is a simple test of the posix_spawn() API. The example derives from
+ examples/elf. As a result, these tests are built using the relocatable
+ ELF format installed in a ROMFS file system. At run time, the test program
+ in the ROMFS file system is spawned using posix_spawn().
+
+ Requires:
+
+ CONFIG_BINFMT_DISABLE=n - Don't disable the binary loader
+ CONFIG_ELF=y - Enable ELF binary loader
+ CONFIG_LIBC_EXECFUNCS=y - Enable support for posix_spawn
+ CONFIG_EXECFUNCS_SYMTAB="exports" - The name of the symbol table
+ created by the test.
+ CONFIG_EXECFUNCS_NSYMBOLS=10 - Value does not matter, it will be
+ corrected at runtime.
+ CONFIG_POSIX_SPAWN_STACKSIZE=768 - This default setting.
+
+ Test-specific configuration options:
+
+ CONFIG_EXAMPLES_POSIXSPAWN_DEVMINOR - The minor device number of the ROMFS
+ block. driver. For example, the N in /dev/ramN. Used for registering the
+ RAM block driver that will hold the ROMFS file system containing the ELF
+ executables to be tested. Default: 0
+
+ CONFIG_EXAMPLES_POSIXSPAWN_DEVPATH - The path to the ROMFS block driver
+ device. This must match EXAMPLES_POSIXSPAWN_DEVMINOR. Used for
+ registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: "/dev/ram0"
+
+ NOTES:
+
+ 1. CFLAGS should be provided in CELFFLAGS. RAM and FLASH memory regions
+ may require long allcs. For ARM, this might be:
+
+ CELFFLAGS = $(CFLAGS) -mlong-calls
+
+ Similarly for C++ flags which must be provided in CXXELFFLAGS.
+
+ 2. Your top-level nuttx/Make.defs file must also include an approproate
+ definition, LDELFFLAGS, to generate a relocatable ELF object. With GNU
+ LD, this should include '-r' and '-e main' (or _main on some platforms).
+
+ LDELFFLAGS = -r -e main
+
+ If you use GCC to link, you make also need to include '-nostdlib' or
+ '-nostartfiles' and '-nodefaultlibs'.
+
+ 3. This example also requires genromfs. genromfs can be build as part of the
+ nuttx toolchain. Or can built from the genromfs sources that can be found
+ at misc/tools/genromfs-0.5.2.tar.gz. In any event, the PATH variable must
+ include the path to the genromfs executable.
+
+ 4. ELF size: The ELF files in this example are, be default, quite large
+ because they include a lot of "build garbage". You can greatly reduce the
+ size of the ELF binaries are using the 'objcopy --strip-unneeded' command to
+ remove un-necessary information from the ELF files.
+
+ 5. Simulator. You cannot use this example with the the NuttX simulator on
+ Cygwin. That is because the Cygwin GCC does not generate ELF file but
+ rather some Windows-native binary format.
+
+ If you really want to do this, you can create a NuttX x86 buildroot toolchain
+ and use that be build the ELF executables for the ROMFS file system.
+
+ 6. Linker scripts. You might also want to use a linker scripts to combine
+ sections better. An example linker script is at nuttx/binfmt/libelf/gnu-elf.ld.
+ That example might have to be tuned for your particular linker output to
+ position additional sections correctly. The GNU LD LDELFFLAGS then might
+ be:
+
+ LDELFFLAGS = -r -e main -T$(TOPDIR)/binfmt/libelf/gnu-elf.ld
+
examples/pwm
^^^^^^^^^^^^
diff --git a/apps/examples/adc/Makefile b/apps/examples/adc/Makefile
index 69862b383..3cbe843f6 100644
--- a/apps/examples/adc/Makefile
+++ b/apps/examples/adc/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/buttons/Makefile b/apps/examples/buttons/Makefile
index 77c1cd67d..a2e8679d4 100644
--- a/apps/examples/buttons/Makefile
+++ b/apps/examples/buttons/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/can/Makefile b/apps/examples/can/Makefile
index 8924797e3..548c6702c 100644
--- a/apps/examples/can/Makefile
+++ b/apps/examples/can/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/cdcacm/Makefile b/apps/examples/cdcacm/Makefile
index e8d03807d..2cf3a107f 100644
--- a/apps/examples/cdcacm/Makefile
+++ b/apps/examples/cdcacm/Makefile
@@ -87,12 +87,17 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME1)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME1),$(PRIORITY1),$(STACKSIZE1),$(APPNAME1)_main)
+
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME2)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME2),$(PRIORITY2),$(STACKSIZE2),$(APPNAME2)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME1)_main.bdat $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME2)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/hello/Makefile b/apps/examples/hello/Makefile
index 560b0da35..c3b9744d7 100644
--- a/apps/examples/hello/Makefile
+++ b/apps/examples/hello/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
-ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y)
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/helloxx/Makefile b/apps/examples/helloxx/Makefile
index 062da7d58..44d880658 100644
--- a/apps/examples/helloxx/Makefile
+++ b/apps/examples/helloxx/Makefile
@@ -100,13 +100,14 @@ $(CXXOBJS): %$(OBJEXT): %.cxx
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c
index 97792cb2a..d9bfc2018 100644
--- a/apps/examples/nsh/nsh_main.c
+++ b/apps/examples/nsh/nsh_main.c
@@ -46,6 +46,12 @@
#include <errno.h>
#include <nuttx/arch.h>
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+#include <nuttx/binfmt/builtin.h>
+#endif
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+#include <nuttx/binfmt/symtab.h>
+#endif
#include <apps/nsh.h>
@@ -75,6 +81,21 @@
* Public Data
****************************************************************************/
+/* If posix_spawn() is enabled as required for CONFIG_NSH_FILE_APPS, then
+ * a symbol table is needed by the internals of posix_spawn(). The symbol
+ * table is needed to support ELF and NXFLAT binaries to dynamically link to
+ * the base code. However, if only the BINFS file system is supported, then
+ * no Makefile is needed.
+ *
+ * This is a kludge to plug the missing file system in the case where BINFS
+ * is used. REVISIT: This will, of course, be in the way if you want to
+ * support ELF or NXFLAT binaries!
+ */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+const struct symtab_s CONFIG_EXECFUNCS_SYMTAB[1];
+#endif
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -98,6 +119,23 @@ int nsh_main(int argc, char *argv[])
up_cxxinitialize();
#endif
+ /* Make sure that we are using our symbol take */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+ exec_setsymtab(CONFIG_EXECFUNCS_SYMTAB, 0);
+#endif
+
+ /* Register the BINFS file system */
+
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+ ret = builtin_initialize();
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR: builtin_initialize failed: %d\n", ret);
+ exitval = 1;
+ }
+#endif
+
/* Initialize the NSH library */
nsh_initialize();
diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile
index 3e78c64e8..5a8ff7293 100644
--- a/apps/examples/ostest/Makefile
+++ b/apps/examples/ostest/Makefile
@@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_FPU),y)
CSRCS += fpu.c
endif
+ifeq ($(CONFIG_SCHED_WAITPID),y)
+CSRCS += waitpid.c
+endif
+
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += cancel.c cond.c mutex.c sem.c barrier.c
ifneq ($(CONFIG_RR_INTERVAL),0)
@@ -84,6 +88,10 @@ ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
CSRCS += posixtimer.c
endif
+ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CSRCS += vfork.c
+endif
+
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
@@ -127,13 +135,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_EXAMPLES_OSTEST_BUILTIN),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h
index a4af37f05..5217f0a0c 100644
--- a/apps/examples/ostest/ostest.h
+++ b/apps/examples/ostest/ostest.h
@@ -105,71 +105,83 @@
/* dev_null.c ***************************************************************/
-extern int dev_null(void);
+int dev_null(void);
/* fpu.c ********************************************************************/
-extern void fpu_test(void);
+void fpu_test(void);
+
+/* waitpid.c ****************************************************************/
+
+#ifdef CONFIG_SCHED_WAITPID
+int waitpid_test(void);
+#endif
/* mutex.c ******************************************************************/
-extern void mutex_test(void);
+void mutex_test(void);
/* rmutex.c ******************************************************************/
-extern void recursive_mutex_test(void);
+void recursive_mutex_test(void);
/* sem.c ********************************************************************/
-extern void sem_test(void);
+void sem_test(void);
/* cond.c *******************************************************************/
-extern void cond_test(void);
+void cond_test(void);
/* mqueue.c *****************************************************************/
-extern void mqueue_test(void);
+void mqueue_test(void);
/* timedmqueue.c ************************************************************/
-extern void timedmqueue_test(void);
+void timedmqueue_test(void);
/* cancel.c *****************************************************************/
-extern void cancel_test(void);
+void cancel_test(void);
/* timedwait.c **************************************************************/
-extern void timedwait_test(void);
+void timedwait_test(void);
/* sighand.c ****************************************************************/
-extern void sighand_test(void);
+void sighand_test(void);
/* posixtimers.c ************************************************************/
-extern void timer_test(void);
+void timer_test(void);
/* roundrobin.c *************************************************************/
-extern void rr_test(void);
+void rr_test(void);
/* barrier.c ****************************************************************/
-extern void barrier_test(void);
+void barrier_test(void);
/* prioinherit.c ************************************************************/
-extern void priority_inheritance(void);
+void priority_inheritance(void);
+
+/* vfork.c ******************************************************************/
+
+#ifdef CONFIG_ARCH_HAVE_VFORK
+int vfork_test(void);
+#endif
/* APIs exported (conditionally) by the OS specifically for testing of
* priority inheritance
*/
#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG)
-extern void sem_enumholders(FAR sem_t *sem);
-extern int sem_nfreeholders(void);
+void sem_enumholders(FAR sem_t *sem);
+int sem_nfreeholders(void);
#else
# define sem_enumholders(sem)
# define sem_nfreeholders()
diff --git a/apps/examples/ostest/ostest_main.c b/apps/examples/ostest/ostest_main.c
index 46726d515..aab1ff045 100644
--- a/apps/examples/ostest/ostest_main.c
+++ b/apps/examples/ostest/ostest_main.c
@@ -301,6 +301,14 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
+#ifdef CONFIG_SCHED_WAITPID
+ /* Check waitpid() and friends */
+
+ printf("\nuser_main: waitpid test\n");
+ waitpid_test();
+ check_test_memory_usage();
+#endif
+
#ifndef CONFIG_DISABLE_PTHREAD
/* Verify pthreads and pthread mutex */
@@ -409,6 +417,11 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */
+#ifdef CONFIG_ARCH_HAVE_VFORK
+ printf("\nuser_main: vfork() test\n");
+ vfork_test();
+#endif
+
/* Compare memory usage at time ostest_main started until
* user_main exits. These should not be identical, but should
* be similar enough that we can detect any serious OS memory
@@ -428,6 +441,7 @@ static int user_main(int argc, char *argv[])
show_memory_usage(&g_mmbefore, &g_mmafter);
#endif
}
+
printf("user_main: Exitting\n");
return 0;
}
diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c
index eabfe5646..32b182c21 100644
--- a/apps/examples/ostest/sighand.c
+++ b/apps/examples/ostest/sighand.c
@@ -54,12 +54,37 @@ static sem_t sem;
static bool sigreceived = false;
static bool threadexited = false;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static void death_of_child(int signo, siginfo_t *info, void *ucontext)
+{
+ /* Use of printf in a signal handler is NOT safe! It can cause deadlocks!
+ * Also, signals are not queued by NuttX. As a consequence, some
+ * notifications will get lost (or the info data can be overwrittedn)!
+ * Because POSIX does not require signals to be queued, I do not think
+ * that this is a bug (the overwriting is a bug, however).
+ */
+
+ if (info)
+ {
+ printf("death_of_child: PID %d received signal=%d code=%d pid=%d status=%d\n",
+ getpid(), signo, info->si_code, info->si_pid, info->si_status);
+ }
+ else
+ {
+ printf("death_of_child: PID %d received signal=%d (no info?)\n",
+ getpid(), signo);
+ }
+}
+#endif
+
static void wakeup_action(int signo, siginfo_t *info, void *ucontext)
{
sigset_t oldset;
sigset_t allsigs;
int status;
+ /* Use of printf in a signal handler is NOT safe! It can cause deadlocks! */
+
printf("wakeup_action: Received signal %d\n" , signo);
sigreceived = true;
@@ -186,6 +211,11 @@ static int waiter_main(int argc, char *argv[])
void sighand_test(void)
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ struct sigaction act;
+ struct sigaction oact;
+ sigset_t sigset;
+#endif
struct sched_param param;
union sigval sigvalue;
pid_t waiterpid;
@@ -195,6 +225,32 @@ void sighand_test(void)
printf("sighand_test: Initializing semaphore to 0\n" );
sem_init(&sem, 0, 0);
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ printf("sighand_test: Unmasking SIGCHLD\n");
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+ status = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (status != OK)
+ {
+ printf("sighand_test: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ printf("sighand_test: Registering SIGCHLD handler\n" );
+ act.sa_sigaction = death_of_child;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, SIGCHLD);
+
+ status = sigaction(SIGCHLD, &act, &oact);
+ if (status != OK)
+ {
+ printf("waiter_main: ERROR sigaction failed, status=%d\n" , status);
+ }
+#endif
+
/* Start waiter thread */
printf("sighand_test: Starting waiter task\n" );
@@ -262,6 +318,13 @@ void sighand_test(void)
printf("sighand_test: ERROR signal handler did not run\n" );
}
+ /* Detach the signal handler */
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ act.sa_sigaction = SIG_DFL;
+ status = sigaction(SIGCHLD, &act, &oact);
+#endif
+
printf("sighand_test: done\n" );
FFLUSH();
}
diff --git a/apps/examples/ostest/vfork.c b/apps/examples/ostest/vfork.c
new file mode 100644
index 000000000..4e1b8c892
--- /dev/null
+++ b/apps/examples/ostest/vfork.c
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * examples/ostest/vfork.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if defined(CONFIG_ARCH_HAVE_VFORK) && !defined(CONFIG_DISABLE_SIGNALS)
+static volatile bool g_vforkchild;
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int vfork_test(void)
+{
+#if defined(CONFIG_ARCH_HAVE_VFORK) && !defined(CONFIG_DISABLE_SIGNALS)
+ pid_t pid;
+
+ g_vforkchild = false;
+ pid = vfork();
+ if (pid == 0)
+ {
+ /* There is not very much that the child is permitted to do. Perhaps
+ * it can just set g_vforkchild.
+ */
+
+ g_vforkchild = true;
+ exit(0);
+ }
+ else if (pid < 0)
+ {
+ printf("vfork_test: vfork() failed: %d\n", errno);
+ return -1;
+ }
+ else
+ {
+ sleep(1);
+ if (g_vforkchild)
+ {
+ printf("vfork_test: Child %d ran successfully\n", pid);
+ }
+ else
+ {
+ printf("vfork_test: ERROR Child %d did not run\n", pid);
+ return -1;
+ }
+ }
+#endif
+
+ return 0;
+}
diff --git a/apps/examples/ostest/waitpid.c b/apps/examples/ostest/waitpid.c
new file mode 100644
index 000000000..e53b49213
--- /dev/null
+++ b/apps/examples/ostest/waitpid.c
@@ -0,0 +1,269 @@
+/****************************************************************************
+ * examples/ostest/waitpid.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/wait.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+#ifdef CONFIG_SCHED_WAITPID
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RETURN_STATUS 14
+#define NCHILDREN 3
+#define PRIORITY 100
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static int g_waitpids[NCHILDREN];
+
+/****************************************************************************
+ * Priviate Functions
+ ****************************************************************************/
+
+static int waitpid_main(int argc, char *argv[])
+{
+ pid_t me = getpid();
+
+ printf("waitpid_main: PID %d Started\n", me);
+ sleep(3);
+ printf("waitpid_main: PID %d exitting with result=%d\n", me, RETURN_STATUS);
+ return RETURN_STATUS;
+}
+
+static void waitpid_start_children(void)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < NCHILDREN; i++)
+ {
+ ret = TASK_CREATE("waitpid", PRIORITY, STACKSIZE, waitpid_main, NULL);
+ if (ret < 0)
+ {
+ printf("waitpid_start_child: ERROR Failed to start user_main\n");
+ }
+ else
+ {
+ printf("waitpid_start_child: Started waitpid_main at PID=%d\n", ret);
+ }
+
+ g_waitpids[i] = ret;
+ }
+}
+
+static void waitpid_last(void)
+{
+ int stat_loc;
+ int ret;
+
+ printf("waitpid_last: Waiting for PID=%d with waitpid()\n",
+ g_waitpids[NCHILDREN-1]);
+
+ ret = (int)waitpid(g_waitpids[NCHILDREN-1], &stat_loc, 0);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_last: ERROR: PID %d waitpid failed: %d\n",
+ g_waitpids[NCHILDREN-1], errcode);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_last: ERROR: PID %d return status is %d, expected %d\n",
+ g_waitpids[NCHILDREN-1], stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_last: PID %d waitpid succeeded with stat_loc=%d\n",
+ g_waitpids[NCHILDREN-1], stat_loc);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int waitpid_test(void)
+{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ siginfo_t info;
+#endif
+ int stat_loc;
+ int ret;
+
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest waitpid()\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for PID=%d with waitpid()\n", g_waitpids[0]);
+ ret = (int)waitpid(g_waitpids[0], &stat_loc, 0);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: PID %d waitpid failed: %d\n",
+ g_waitpids[0], errcode);
+ }
+ else if (ret != g_waitpids[0])
+ {
+ printf("waitpid_test: ERROR: PID %d wait returned PID %d\n",
+ g_waitpids[0], ret);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ g_waitpids[0], stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d waitpid succeeded with stat_loc=%d\n",
+ g_waitpids[0], stat_loc);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest waitid(P_PID)\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for PID=%d with waitid()\n", g_waitpids[0]);
+ ret = waitid(P_PID, (id_t)g_waitpids[0], &info, WEXITED);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: PID %d waitid failed: %d\n",
+ g_waitpids[0], errcode);
+ }
+ else if (info.si_pid != g_waitpids[0])
+ {
+ printf("waitpid_test: ERROR: PID %d waitid returned PID %d\n",
+ g_waitpids[0], info.si_pid);
+ }
+ else if (info.si_status != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ info.si_pid, info.si_status, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: waitid PID %d succeeded with si_status=%d\n",
+ info.si_pid, info.si_status);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+ /* Start the children and wait for any one to complete */
+
+ printf("\nTest waitid(P_ALL)\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for any child with waitid()\n");
+ ret = waitid(P_ALL, 0, &info, WEXITED);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: waitid failed: %d\n", errcode);
+ }
+ else if (info.si_status != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ info.si_pid, info.si_status, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d waitid succeeded with si_status=%d\n",
+ info.si_pid, info.si_status);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest wait()\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for any child with wait()\n");
+ ret = (int)wait(&stat_loc);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: wait failed: %d\n", errcode);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ ret, stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d wait succeeded with stat_loc=%d\n",
+ ret, stat_loc);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+#endif
+
+ return 0;
+}
+
+#endif /* CONFIG_SCHED_WAITPID */
diff --git a/apps/examples/posix_spawn/Kconfig b/apps/examples/posix_spawn/Kconfig
new file mode 100644
index 000000000..508065913
--- /dev/null
+++ b/apps/examples/posix_spawn/Kconfig
@@ -0,0 +1,29 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config EXAMPLES_POSIXSPAWN
+ bool "posix_spawn Unit Test"
+ default n
+ ---help---
+ Enable the posix_spawn() unit test
+
+if EXAMPLES_POSIXSPAWN
+config EXAMPLES_POSIXSPAWN_DEVMINOR
+ int "ROMFS Minor Device Number"
+ default 0
+ ---help---
+ The minor device number of the ROMFS block. For example, the N in /dev/ramN.
+ Used for registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: 0
+
+config EXAMPLES_POSIXSPAWN_DEVPATH
+ string "ROMFS Devie Path"
+ default "/dev/ram0"
+ ---help---
+ The path to the ROMFS block driver device. This must match EXAMPLES_POSIXSPAWN_DEVMINOR.
+ Used for registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: "/dev/ram0"
+
+endif
diff --git a/apps/examples/posix_spawn/Makefile b/apps/examples/posix_spawn/Makefile
new file mode 100644
index 000000000..0bfa36e55
--- /dev/null
+++ b/apps/examples/posix_spawn/Makefile
@@ -0,0 +1,130 @@
+############################################################################
+# apps/examples/posix_spawn/Makefile
+#
+# Copyright (C) 2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# ELF Example
+
+ASRCS =
+CSRCS = spawn_main.c symtab.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ BIN = ..\\..\\libapps$(LIBEXT)
+else
+ BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ROOTDEPPATH = --dep-path . --dep-path filesystem
+
+# Build targets
+
+VPATH = filesystem
+
+all: build
+.PHONY: build clean_filesystem clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+# This is a little messy. The build is broken into two pieces: (1) the
+# filesystem/ subdir build that auto-generates several files, and (2) the library
+# build. This is done because we need a fresh build context after auto-
+# generating the source files.
+
+build_lib: $(OBJS)
+ $(call ARCHIVE, $(BIN), $(OBJS))
+
+build:
+ @$(MAKE) -C filesystem TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV)
+ @$(MAKE) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" build_lib
+
+context:
+
+# We can't make dependencies in this directory because the required
+# header files may not yet exist.
+
+.depend:
+ @touch $@
+
+depend: .depend
+
+clean_filesystem:
+ @$(MAKE) -C filesystem TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) clean
+
+clean: clean_filesystem
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+# There are no dependencies in this directory. Some of more important
+# and more obvious dependencies are hard-coded here:
+
+spawn_main.o: spawn_main.c \
+ $(TOPDIR)/include/nuttx/config.h \
+ $(TOPDIR)/include/nuttx/compiler.h \
+ $(TOPDIR)/include/sys/mount.h \
+ $(TOPDIR)/include/stdio.h \
+ $(TOPDIR)/include/stdlib.h \
+ $(TOPDIR)/include/unistd.h \
+ $(TOPDIR)/include/string.h \
+ $(TOPDIR)/include/fcntl.h \
+ $(TOPDIR)/include/spawn.h \
+ $(TOPDIR)/include/debug.h \
+ $(TOPDIR)/include/errno.h \
+ $(TOPDIR)/include/nuttx/ramdisk.h \
+ $(TOPDIR)/include/nuttx/binfmt/elf.h \
+ $(TOPDIR)/include/nuttx/binfmt/symtab.h \
+ filesystem/romfs.h
+
+symtab.o: filesystem/symtab.c \
+ $(TOPDIR)/include/nuttx/compiler.h \
+ $(TOPDIR)/include/nuttx/binfmt/symtab.h
diff --git a/apps/examples/posix_spawn/filesystem/Makefile b/apps/examples/posix_spawn/filesystem/Makefile
new file mode 100644
index 000000000..26897426c
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/Makefile
@@ -0,0 +1,88 @@
+############################################################################
+# apps/examples/posix_spawn/filesystem/Makefile
+#
+# Copyright (C) 2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)$(DELIM)Make.defs
+
+SPAWN_DIR = $(APPDIR)$(DELIM)examples$(DELIM)posix_spawn
+FILESYSTEM_DIR = $(SPAWN_DIR)$(DELIM)filesystem
+ROMFS_DIR = $(FILESYSTEM_DIR)$(DELIM)romfs
+ROMFS_IMG = $(FILESYSTEM_DIR)$(DELIM)romfs.img
+ROMFS_HDR = $(FILESYSTEM_DIR)$(DELIM)romfs.h
+SYMTAB_SRC = $(FILESYSTEM_DIR)$(DELIM)symtab.c
+
+all: $(ROMFS_HDR) $(SYMTAB_SRC)
+.PHONY: all hello/hello redirect/redirect clean populate
+
+# Create the romfs directory
+
+$(ROMFS_DIR):
+ $(Q) mkdir $(ROMFS_DIR)
+
+# Build the hello test program
+
+hello/hello:
+ $(Q) $(MAKE) -C hello hello TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+
+# Build the redirection test program
+
+redirect/redirect:
+ $(Q) $(MAKE) -C redirect redirect TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+
+# Create the romfs.img file from the romfs directory
+
+$(ROMFS_IMG): hello/hello redirect/redirect testdata.txt $(ROMFS_DIR)
+ $(Q) $(MAKE) -C hello install TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) $(MAKE) -C redirect install TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) install --mode=0644 testdata.txt $(ROMFS_DIR)/testdata.txt
+ $(Q) genromfs -f $@ -d $(ROMFS_DIR) -V "POSIXSPAWN"
+
+# Create the romfs.h header file from the romfs.img file
+
+$(ROMFS_HDR) : $(ROMFS_IMG)
+ $(Q) (cd $(FILESYSTEM_DIR); xxd -i romfs.img | sed -e "s/^unsigned/static const unsigned/g" >$@)
+
+# Create the exported symbol table
+
+$(SYMTAB_SRC): $(ROMFS_DIR)/hello $(ROMFS_DIR)/redirect $(ROMFS_DIR)/testdata.txt
+ $(Q) $(FILESYSTEM_DIR)$(DELIM)mksymtab.sh $(ROMFS_DIR) >$@
+
+# Clean each subdirectory
+
+clean:
+ $(Q) $(MAKE) -C hello clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) $(MAKE) -C redirect clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) rm -f $(ROMFS_HDR) $(ROMFS_IMG) $(SYMTAB_SRC)
+ $(Q) rm -rf $(ROMFS_DIR)
diff --git a/apps/examples/posix_spawn/filesystem/hello/hello.c b/apps/examples/posix_spawn/filesystem/hello/hello.c
new file mode 100644
index 000000000..1b269d85f
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/hello/hello.c
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * examples/posix_spawn/filesystem/hello/hello.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ /* Mandatory "Hello, world!" */
+
+ puts("Getting ready to say \"Hello, world\"\n");
+ printf("Hello, world!\n");
+ puts("It has been said.\n");
+
+ /* Print arguments */
+
+ printf("argc\t= %d\n", argc);
+ printf("argv\t= 0x%p\n", argv);
+
+ for (i = 0; i < argc; i++)
+ {
+ printf("argv[%d]\t= ", i);
+ if (argv[i])
+ {
+ printf("(0x%p) \"%s\"\n", argv[i], argv[i]);
+ }
+ else
+ {
+ printf("NULL?\n");
+ }
+ }
+
+ printf("argv[%d]\t= 0x%p\n", argc, argv[argc]);
+ printf("Goodbye, world!\n");
+ return 0;
+}
diff --git a/apps/examples/posix_spawn/filesystem/mksymtab.sh b/apps/examples/posix_spawn/filesystem/mksymtab.sh
new file mode 100755
index 000000000..51408a89c
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/mksymtab.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+usage="Usage: $0 <test-dir-path>"
+
+# Check for the required ROMFS directory path
+
+dir=$1
+if [ -z "$dir" ]; then
+ echo "ERROR: Missing <test-dir-path>"
+ echo ""
+ echo $usage
+ exit 1
+fi
+
+if [ ! -d "$dir" ]; then
+ echo "ERROR: Directory $dir does not exist"
+ echo ""
+ echo $usage
+ exit 1
+fi
+
+# Extract all of the undefined symbols from the ELF files and create a
+# list of sorted, unique undefined variable names.
+
+varlist=`find ${dir} -executable -type f | xargs nm | fgrep ' U ' | sed -e "s/^[ ]*//g" | cut -d' ' -f2 | sort | uniq`
+
+# Now output the symbol table as a structure in a C source file. All
+# undefined symbols are declared as void* types. If the toolchain does
+# any kind of checking for function vs. data objects, then this could
+# faile
+
+echo "#include <nuttx/compiler.h>"
+echo "#include <nuttx/binfmt/symtab.h>"
+echo ""
+
+for var in $varlist; do
+ echo "extern void *${var};"
+done
+
+echo ""
+echo "const struct symtab_s exports[] = "
+echo "{"
+
+for var in $varlist; do
+ echo " {\"${var}\", &${var}},"
+done
+
+echo "};"
+echo ""
+echo "const int nexports = sizeof(exports) / sizeof(struct symtab_s);"
+
diff --git a/apps/examples/posix_spawn/filesystem/redirect/redirect.c b/apps/examples/posix_spawn/filesystem/redirect/redirect.c
new file mode 100644
index 000000000..61638df79
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/redirect/redirect.c
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * examples/posix_spawn/filesystem/redirect/redirect.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int ch;
+
+ printf("Entering the stdin redirection test\n");
+
+ /* stdin should have been redirected to testdata.txt. Read and print until
+ * we hit the end of file.
+ */
+
+ while ((ch = getchar()) != EOF)
+ {
+ putchar(ch);
+ }
+
+ printf("Exit-ing the stdin redirection test\n");
+ return 0;
+}
diff --git a/apps/examples/posix_spawn/filesystem/testdata.txt b/apps/examples/posix_spawn/filesystem/testdata.txt
new file mode 100644
index 000000000..bb581fbb5
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/testdata.txt
@@ -0,0 +1,2 @@
+Now is the time for all good men to come to the aid of their party.
+
diff --git a/apps/examples/posix_spawn/spawn_main.c b/apps/examples/posix_spawn/spawn_main.c
new file mode 100644
index 000000000..0ca5f9107
--- /dev/null
+++ b/apps/examples/posix_spawn/spawn_main.c
@@ -0,0 +1,460 @@
+/****************************************************************************
+ * examples/posix_spawn/spawn_main.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <sys/mount.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/ramdisk.h>
+#include <nuttx/binfmt/elf.h>
+#include <nuttx/binfmt/symtab.h>
+
+#include "filesystem/romfs.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Check configuration. This is not all of the configuration settings that
+ * are required -- only the more obvious.
+ */
+
+#if CONFIG_NFILE_DESCRIPTORS < 1
+# error "You must provide file descriptors via CONFIG_NFILE_DESCRIPTORS in your configuration file"
+#endif
+
+#ifdef CONFIG_BINFMT_DISABLE
+# error "The binary loader is disabled (CONFIG_BINFMT_DISABLE)!"
+#endif
+
+#ifndef CONFIG_ELF
+# error "You must select CONFIG_ELF in your configuration file"
+#endif
+
+#ifndef CONFIG_FS_ROMFS
+# error "You must select CONFIG_FS_ROMFS in your configuration file"
+#endif
+
+#ifdef CONFIG_DISABLE_MOUNTPOINT
+# error "You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file"
+#endif
+
+#ifdef CONFIG_BINFMT_DISABLE
+# error "You must not disable loadable modules via CONFIG_BINFMT_DISABLE in your configuration file"
+#endif
+
+/* Describe the ROMFS file system */
+
+#define SECTORSIZE 512
+#define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE)
+#define MOUNTPT "/mnt/romfs"
+
+#ifndef CONFIG_EXAMPLES_ELF_DEVMINOR
+# define CONFIG_EXAMPLES_ELF_DEVMINOR 0
+#endif
+
+#ifndef CONFIG_EXAMPLES_ELF_DEVPATH
+# define CONFIG_EXAMPLES_ELF_DEVPATH "/dev/ram0"
+#endif
+
+/* If CONFIG_DEBUG is enabled, use dbg instead of printf so that the
+ * output will be synchronous with the debug output.
+ */
+
+#ifdef CONFIG_CPP_HAVE_VARARGS
+# ifdef CONFIG_DEBUG
+# define message(format, arg...) dbg(format, ##arg)
+# define err(format, arg...) dbg(format, ##arg)
+# else
+# define message(format, arg...) printf(format, ##arg)
+# define err(format, arg...) fprintf(stderr, format, ##arg)
+# endif
+#else
+# ifdef CONFIG_DEBUG
+# define message dbg
+# define err dbg
+# else
+# define message printf
+# define err printf
+# endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static unsigned int g_mminitial; /* Initial memory usage */
+static unsigned int g_mmstep; /* Memory Usage at beginning of test step */
+
+static const char delimiter[] =
+ "****************************************************************************";
+static const char g_redirect[] = "redirect";
+static const char g_hello[] = "hello";
+static const char g_data[] = "testdata.txt";
+
+static char fullpath[128];
+
+static char * const g_argv[4] =
+ { "Argument 1", "Argument 2", "Argument 3", NULL };
+
+/****************************************************************************
+ * Symbols from Auto-Generated Code
+ ****************************************************************************/
+
+extern const struct symtab_s exports[];
+extern const int nexports;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mm_update
+ ****************************************************************************/
+
+static void mm_update(FAR unsigned int *previous, FAR const char *msg)
+{
+ struct mallinfo mmcurrent;
+
+ /* Get the current memory usage */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ /* Show the change from the previous time */
+
+ printf("\nMemory Usage %s:\n", msg);
+ printf(" Before: %8u After: %8u Change: %8d\n",
+ *previous, mmcurrent.uordblks, (int)mmcurrent.uordblks - (int)*previous);
+
+ /* Set up for the next test */
+
+ *previous = mmcurrent.uordblks;
+}
+
+/****************************************************************************
+ * Name: mm_initmonitor
+ ****************************************************************************/
+
+static void mm_initmonitor(void)
+{
+ struct mallinfo mmcurrent;
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ g_mminitial = mmcurrent.uordblks;
+ g_mmstep = mmcurrent.uordblks;
+
+ printf("Initial memory usage: %d\n", mmcurrent.uordblks);
+}
+
+/****************************************************************************
+ * Name: testheader
+ ****************************************************************************/
+
+static inline void testheader(FAR const char *progname)
+{
+ message("\n%s\n* Executing %s\n%s\n\n", delimiter, progname, delimiter);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spawn_main
+ ****************************************************************************/
+
+int spawn_main(int argc, char *argv[])
+{
+ posix_spawn_file_actions_t file_actions;
+ posix_spawnattr_t attr;
+ FAR const char *filepath;
+ pid_t pid;
+ int ret;
+
+ /* Initialize the memory monitor */
+
+ mm_initmonitor();
+
+ /* Initialize the ELF binary loader */
+
+ message("Initializing the ELF binary loader\n");
+ ret = elf_initialize();
+ if (ret < 0)
+ {
+ err("ERROR: Initialization of the ELF loader failed: %d\n", ret);
+ exit(1);
+ }
+
+ mm_update(&g_mmstep, "after elf_initialize");
+
+ /* Create a ROM disk for the ROMFS filesystem */
+
+ message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR);
+ ret = romdisk_register(CONFIG_EXAMPLES_ELF_DEVMINOR, (FAR uint8_t *)romfs_img,
+ NSECTORS(romfs_img_len), SECTORSIZE);
+ if (ret < 0)
+ {
+ err("ERROR: romdisk_register failed: %d\n", ret);
+ elf_uninitialize();
+ exit(1);
+ }
+
+ mm_update(&g_mmstep, "after romdisk_register");
+
+ /* Mount the file system */
+
+ message("Mounting ROMFS filesystem at target=%s with source=%s\n",
+ MOUNTPT, CONFIG_EXAMPLES_ELF_DEVPATH);
+
+ ret = mount(CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, "romfs", MS_RDONLY, NULL);
+ if (ret < 0)
+ {
+ err("ERROR: mount(%s,%s,romfs) failed: %s\n",
+ CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, errno);
+ elf_uninitialize();
+ }
+
+ mm_update(&g_mmstep, "after mount");
+
+ /* Does the system support the PATH variable? Has the PATH variable
+ * already been set? If YES and NO, then set the PATH variable to
+ * the ROMFS mountpoint.
+ */
+
+#if defined(CONFIG_BINFMT_EXEPATH) && !defined(CONFIG_PATH_INITIAL)
+ (void)setenv("PATH", MOUNTPT, 1);
+#endif
+
+ /* Make sure that we are using our symbol take */
+
+ exec_setsymtab(exports, nexports);
+
+ /*************************************************************************
+ * Case 1: Simple program with arguments
+ *************************************************************************/
+
+ /* Output a seperated so that we can clearly discriminate the output of
+ * this program from the others.
+ */
+
+ testheader(g_hello);
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_init failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr init");
+
+ /* If the binary loader does not support the PATH variable, then
+ * create the full path to the executable program. Otherwise,
+ * use the relative path so that the binary loader will have to
+ * search the PATH variable to find the executable.
+ */
+
+#ifdef CONFIG_BINFMT_EXEPATH
+ filepath = g_hello;
+#else
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_hello);
+ filepath = fullpath;
+#endif
+
+ /* Execute the program */
+
+ mm_update(&g_mmstep, "before posix_spawn");
+
+ ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, (FAR char * const*)&g_argv);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn failed: %d\n", ret);
+ }
+
+ sleep(4);
+ mm_update(&g_mmstep, "after posix_spawn");
+
+ /* Free attibutes and file actions */
+
+ ret = posix_spawn_file_actions_destroy(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_destroy(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr destruction");
+
+ /*************************************************************************
+ * Case 2: Simple program with redirection of stdin to a file input
+ *************************************************************************/
+
+ /* Output a seperated so that we can clearly discriminate the output of
+ * this program from the others.
+ */
+
+ testheader(g_redirect);
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_init failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr init");
+
+ /* Set up to close stdin (0) and open testdata.txt as the program input */
+
+ ret = posix_spawn_file_actions_addclose(&file_actions, 0);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_addclose failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_data);
+ ret = posix_spawn_file_actions_addopen(&file_actions, 0, fullpath, O_RDONLY, 0644);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_addopen failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ mm_update(&g_mmstep, "after adding file_actions");
+
+ /* If the binary loader does not support the PATH variable, then
+ * create the full path to the executable program. Otherwise,
+ * use the relative path so that the binary loader will have to
+ * search the PATH variable to find the executable.
+ */
+
+#ifdef CONFIG_BINFMT_EXEPATH
+ filepath = g_redirect;
+#else
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_redirect);
+ filepath = fullpath;
+#endif
+
+ /* Execute the program */
+
+ mm_update(&g_mmstep, "before posix_spawn");
+
+ ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, NULL);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn failed: %d\n", ret);
+ }
+
+ sleep(2);
+ mm_update(&g_mmstep, "after posix_spawn");
+
+ /* Free attibutes and file actions */
+
+ ret = posix_spawn_file_actions_destroy(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_destroy(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr destruction");
+
+ /* Clean-up */
+
+ elf_uninitialize();
+
+ mm_update(&g_mmstep, "End-of-Test");
+ return 0;
+}
diff --git a/apps/examples/pwm/Makefile b/apps/examples/pwm/Makefile
index 3a6f2520a..ece901a99 100644
--- a/apps/examples/pwm/Makefile
+++ b/apps/examples/pwm/Makefile
@@ -83,11 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/qencoder/Makefile b/apps/examples/qencoder/Makefile
index 7d2427c6b..9668796e6 100644
--- a/apps/examples/qencoder/Makefile
+++ b/apps/examples/qencoder/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/watchdog/Makefile b/apps/examples/watchdog/Makefile
index 9890959fb..076272fe3 100644
--- a/apps/examples/watchdog/Makefile
+++ b/apps/examples/watchdog/Makefile
@@ -83,11 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile
new file mode 100644
index 000000000..8d5faa3b7
--- /dev/null
+++ b/apps/hott_telemetry/Makefile
@@ -0,0 +1,45 @@
+############################################################################
+#
+# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Graupner HoTT Telemetry application.
+#
+
+# The following line is required for accessing UARTs directly.
+INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
+
+APPNAME = hott_telemetry
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+include $(APPDIR)/mk/app.mk
diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c
new file mode 100644
index 000000000..31c9247aa
--- /dev/null
+++ b/apps/hott_telemetry/hott_telemetry_main.c
@@ -0,0 +1,312 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Author: @author Simon Wilks <sjwilks@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file hott_telemetry_main.c
+ *
+ * Graupner HoTT Telemetry implementation.
+ *
+ * The HoTT receiver polls each device at a regular interval at which point
+ * a data packet can be returned if necessary.
+ *
+ * TODO: Add support for at least the vario and GPS sensor data.
+ *
+ */
+
+#include <fcntl.h>
+#include <nuttx/config.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <systemlib/systemlib.h>
+
+#include "messages.h"
+
+/* The following are equired for UART direct manipulation. */
+#include <arch/board/board.h>
+#include "up_arch.h"
+#include "chip.h"
+#include "stm32_internal.h"
+
+static int thread_should_exit = false; /**< Deamon exit flag */
+static int thread_running = false; /**< Deamon status flag */
+static int deamon_task; /**< Handle of deamon task / thread */
+static char *daemon_name = "hott_telemetry";
+static char *commandline_usage = "usage: hott_telemetry start|status|stop [-d <device>]";
+
+
+/* A little console messaging experiment - console helper macro */
+#define FATAL_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg); exit(1);
+#define ERROR_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg);
+#define INFO_MSG(_msg) printf("[%s] %s\n", daemon_name, _msg);
+/**
+ * Deamon management function.
+ */
+__EXPORT int hott_telemetry_main(int argc, char *argv[]);
+
+/**
+ * Mainloop of deamon.
+ */
+int hott_telemetry_thread_main(int argc, char *argv[]);
+
+static int read_data(int uart, int *id);
+static int send_data(int uart, uint8_t *buffer, int size);
+
+static int open_uart(const char *device, struct termios *uart_config_original)
+{
+ /* baud rate */
+ int speed = B19200;
+ int uart;
+
+ /* open uart */
+ uart = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart < 0) {
+ char msg[80];
+ sprintf(msg, "Error opening port: %s\n", device);
+ FATAL_MSG(msg);
+ }
+
+ /* Try to set baud rate */
+ struct termios uart_config;
+ int termios_state;
+
+ /* Back up the original uart configuration to restore it after exit */
+ char msg[80];
+
+ if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) {
+ sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", device, termios_state);
+ close(uart);
+ FATAL_MSG(msg);
+ }
+
+ /* Fill the struct for the new configuration */
+ tcgetattr(uart, &uart_config);
+
+ /* Clear ONLCR flag (which appends a CR for every LF) */
+ uart_config.c_oflag &= ~ONLCR;
+
+ /* Set baud rate */
+ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) {
+ sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n",
+ device, termios_state);
+ close(uart);
+ FATAL_MSG(msg);
+ }
+
+ if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) {
+ sprintf(msg, "Error setting baudrate / termios config for %s (tcsetattr)\n", device);
+ close(uart);
+ FATAL_MSG(msg);
+ }
+
+ /* Activate single wire mode */
+ ioctl(uart, TIOCSSINGLEWIRE, SER_SINGLEWIRE_ENABLED);
+
+ return uart;
+}
+
+int read_data(int uart, int *id)
+{
+ const int timeout = 1000;
+ struct pollfd fds[] = { { .fd = uart, .events = POLLIN } };
+
+ char mode;
+
+ if (poll(fds, 1, timeout) > 0) {
+ /* Get the mode: binary or text */
+ read(uart, &mode, 1);
+ /* Read the device ID being polled */
+ read(uart, id, 1);
+
+ /* if we have a binary mode request */
+ if (mode != BINARY_MODE_REQUEST_ID) {
+ return ERROR;
+ }
+
+ } else {
+ ERROR_MSG("UART timeout on TX/RX port");
+ return ERROR;
+ }
+
+ return OK;
+}
+
+int send_data(int uart, uint8_t *buffer, int size)
+{
+ usleep(POST_READ_DELAY_IN_USECS);
+
+ uint16_t checksum = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (i == size - 1) {
+ /* Set the checksum: the first uint8_t is taken as the checksum. */
+ buffer[i] = checksum & 0xff;
+
+ } else {
+ checksum += buffer[i];
+ }
+
+ write(uart, &buffer[i], 1);
+
+ /* Sleep before sending the next byte. */
+ usleep(POST_WRITE_DELAY_IN_USECS);
+ }
+
+ /* A hack the reads out what was written so the next read from the receiver doesn't get it. */
+ /* TODO: Fix this!! */
+ uint8_t dummy[size];
+ read(uart, &dummy, size);
+
+ return OK;
+}
+
+int hott_telemetry_thread_main(int argc, char *argv[])
+{
+ INFO_MSG("starting");
+
+ thread_running = true;
+
+ char *device = "/dev/ttyS1"; /**< Default telemetry port: USART2 */
+
+ /* read commandline arguments */
+ for (int i = 0; i < argc && argv[i]; i++) {
+ if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set
+ if (argc > i + 1) {
+ device = argv[i + 1];
+
+ } else {
+ thread_running = false;
+ ERROR_MSG("missing parameter to -d");
+ ERROR_MSG(commandline_usage);
+ exit(1);
+ }
+ }
+ }
+
+ /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */
+ struct termios uart_config_original;
+ int uart = open_uart(device, &uart_config_original);
+
+ if (uart < 0) {
+ ERROR_MSG("Failed opening HoTT UART, exiting.");
+ thread_running = false;
+ exit(ERROR);
+ }
+
+ messages_init();
+
+ uint8_t buffer[MESSAGE_BUFFER_SIZE];
+ int size = 0;
+ int id = 0;
+
+ while (!thread_should_exit) {
+ if (read_data(uart, &id) == OK) {
+ switch (id) {
+ case ELECTRIC_AIR_MODULE:
+ build_eam_response(buffer, &size);
+ break;
+
+ default:
+ continue; // Not a module we support.
+ }
+
+ send_data(uart, buffer, size);
+ }
+ }
+
+ INFO_MSG("exiting");
+
+ close(uart);
+
+ thread_running = false;
+
+ return 0;
+}
+
+/**
+ * Process command line arguments and tart the daemon.
+ */
+int hott_telemetry_main(int argc, char *argv[])
+{
+ if (argc < 1) {
+ ERROR_MSG("missing command");
+ ERROR_MSG(commandline_usage);
+ exit(1);
+ }
+
+ if (!strcmp(argv[1], "start")) {
+
+ if (thread_running) {
+ INFO_MSG("deamon already running");
+ exit(0);
+ }
+
+ thread_should_exit = false;
+ deamon_task = task_spawn("hott_telemetry",
+ SCHED_DEFAULT,
+ SCHED_PRIORITY_MAX - 40,
+ 2048,
+ hott_telemetry_thread_main,
+ (argv) ? (const char **)&argv[2] : (const char **)NULL);
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "stop")) {
+ thread_should_exit = true;
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "status")) {
+ if (thread_running) {
+ INFO_MSG("daemon is running");
+
+ } else {
+ INFO_MSG("daemon not started");
+ }
+
+ exit(0);
+ }
+
+ ERROR_MSG("unrecognized command");
+ ERROR_MSG(commandline_usage);
+ exit(1);
+}
+
+
+
diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c
new file mode 100644
index 000000000..8bfb99773
--- /dev/null
+++ b/apps/hott_telemetry/messages.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Author: @author Simon Wilks <sjwilks@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file messages.c
+ *
+ */
+
+#include "messages.h"
+
+#include <string.h>
+#include <systemlib/systemlib.h>
+#include <unistd.h>
+#include <uORB/topics/battery_status.h>
+#include <uORB/topics/sensor_combined.h>
+
+static int battery_sub = -1;
+static int sensor_sub = -1;
+
+void messages_init(void)
+{
+ battery_sub = orb_subscribe(ORB_ID(battery_status));
+ sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
+}
+
+void build_eam_response(uint8_t *buffer, int *size)
+{
+ /* get a local copy of the current sensor values */
+ struct sensor_combined_s raw;
+ memset(&raw, 0, sizeof(raw));
+ orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw);
+
+ /* get a local copy of the battery data */
+ struct battery_status_s battery;
+ memset(&battery, 0, sizeof(battery));
+ orb_copy(ORB_ID(battery_status), battery_sub, &battery);
+
+ struct eam_module_msg msg;
+ *size = sizeof(msg);
+ memset(&msg, 0, *size);
+
+ msg.start = START_BYTE;
+ msg.eam_sensor_id = ELECTRIC_AIR_MODULE;
+ msg.sensor_id = EAM_SENSOR_ID;
+ msg.temperature1 = (uint8_t)(raw.baro_temp_celcius + 20);
+ msg.temperature2 = TEMP_ZERO_CELSIUS;
+ msg.main_voltage_L = (uint8_t)(battery.voltage_v * 10);
+
+ uint16_t alt = (uint16_t)(raw.baro_alt_meter + 500);
+ msg.altitude_L = (uint8_t)alt & 0xff;
+ msg.altitude_H = (uint8_t)(alt >> 8) & 0xff;
+
+ msg.stop = STOP_BYTE;
+
+ memcpy(buffer, &msg, *size);
+} \ No newline at end of file
diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h
new file mode 100644
index 000000000..44001e04f
--- /dev/null
+++ b/apps/hott_telemetry/messages.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Author: @author Simon Wilks <sjwilks@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file messages.h
+ *
+ * Graupner HoTT Telemetry message generation.
+ *
+ */
+#ifndef MESSAGES_H_
+#define MESSAGES_H
+
+#include <stdlib.h>
+
+/* The buffer size used to store messages. This must be at least as big as the number of
+ * fields in the largest message struct.
+ */
+#define MESSAGE_BUFFER_SIZE 50
+
+/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request.
+ * Note that the value specified here is lower than 5000 (5ms) as time is lost constucting
+ * the message after the read which takes some milliseconds.
+ */
+#define POST_READ_DELAY_IN_USECS 4000
+/* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower
+ * values can be used in practise though.
+ */
+#define POST_WRITE_DELAY_IN_USECS 2000
+
+// Protocol constants.
+#define BINARY_MODE_REQUEST_ID 0x80 // Binary mode request.
+#define START_BYTE 0x7c
+#define STOP_BYTE 0x7d
+#define TEMP_ZERO_CELSIUS 0x14
+
+/* Electric Air Module (EAM) constants. */
+#define ELECTRIC_AIR_MODULE 0x8e
+#define EAM_SENSOR_ID 0xe0
+
+/* The Electric Air Module message. */
+struct eam_module_msg {
+ uint8_t start; /**< Start byte */
+ uint8_t eam_sensor_id; /**< EAM sensor ID */
+ uint8_t warning;
+ uint8_t sensor_id; /**< Sensor ID, why different? */
+ uint8_t alarm_inverse1;
+ uint8_t alarm_inverse2;
+ uint8_t cell1_L; /**< Lipo cell voltages. Not supported. */
+ uint8_t cell2_L;
+ uint8_t cell3_L;
+ uint8_t cell4_L;
+ uint8_t cell5_L;
+ uint8_t cell6_L;
+ uint8_t cell7_L;
+ uint8_t cell1_H;
+ uint8_t cell2_H;
+ uint8_t cell3_H;
+ uint8_t cell4_H;
+ uint8_t cell5_H;
+ uint8_t cell6_H;
+ uint8_t cell7_H;
+ uint8_t batt1_voltage_L; /**< Battery 1 voltage, lower 8-bits in steps of 0.02V */
+ uint8_t batt1_voltage_H;
+ uint8_t batt2_voltage_L; /**< Battery 2 voltage, lower 8-bits in steps of 0.02V */
+ uint8_t batt2_voltage_H;
+ uint8_t temperature1; /**< Temperature sensor 1. 20 = 0 degrees */
+ uint8_t temperature2;
+ uint8_t altitude_L; /**< Attitude (meters) lower 8-bits. 500 = 0 meters */
+ uint8_t altitude_H;
+ uint8_t current_L; /**< Current (mAh) lower 8-bits in steps of 0.1V */
+ uint8_t current_H;
+ uint8_t main_voltage_L; /**< Main power voltage lower 8-bits in steps of 0.1V */
+ uint8_t main_voltage_H;
+ uint8_t battery_capacity_L; /**< Used battery capacity in steps of 10mAh */
+ uint8_t battery_capacity_H;
+ uint8_t climbrate_L; /**< Climb rate in 0.01m/s. 0m/s = 30000 */
+ uint8_t climbrate_H;
+ uint8_t climbrate_3s; /**< Climb rate in m/3sec. 0m/3sec = 120 */
+ uint8_t rpm_L; /**< RPM Lower 8-bits In steps of 10 U/min */
+ uint8_t rpm_H;
+ uint8_t electric_min; /**< Flight time in minutes. */
+ uint8_t electric_sec; /**< Flight time in seconds. */
+ uint8_t speed_L; /**< Airspeed in km/h in steps of 1 km/h */
+ uint8_t speed_H;
+ uint8_t stop; /**< Stop byte */
+ uint8_t checksum; /**< Lower 8-bits of all bytes summed. */
+};
+
+void messages_init(void);
+void build_eam_response(uint8_t *buffer, int *size);
+
+#endif /* MESSAGES_H_ */
diff --git a/apps/include/builtin.h b/apps/include/builtin.h
new file mode 100644
index 000000000..24cf204fa
--- /dev/null
+++ b/apps/include/builtin.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * apps/include/builtin.h
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __APPS_INCLUDE_BUILTIN_H
+#define __APPS_INCLUDE_BUILTIN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_builtin
+ *
+ * Description:
+ * Executes builtin applications registered during 'make context' time.
+ * New application is run in a separate task context (and thread).
+ *
+ * Input Parameter:
+ * filename - Name of the linked-in binary to be started.
+ * argv - Argument list
+ * redirfile - If output if redirected, this parameter will be non-NULL
+ * and will provide the full path to the file.
+ * oflags - If output is redirected, this parameter will provide the
+ * open flags to use. This will support file replacement
+ * of appending to an existing file.
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * Returns the PID of the exec'ed module. On failure, it.returns
+ * -1 (ERROR) and sets errno appropriately.
+ *
+ ****************************************************************************/
+
+EXTERN int exec_builtin(FAR const char *appname, FAR const char **argv,
+ FAR const char *redirfile, int oflags);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __APPS_INCLUDE_BUILTIN_H */
diff --git a/apps/interpreters/Makefile b/apps/interpreters/Makefile
index 867d45f99..f78528714 100644
--- a/apps/interpreters/Makefile
+++ b/apps/interpreters/Makefile
@@ -73,4 +73,4 @@ depend: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
diff --git a/apps/interpreters/ficl/Makefile b/apps/interpreters/ficl/Makefile
index 990630fb8..3b2dc7ab9 100644
--- a/apps/interpreters/ficl/Makefile
+++ b/apps/interpreters/ficl/Makefile
@@ -108,7 +108,6 @@ context:
depend: .depend
clean:
- $(call DELFILE, .context)
$(call DELFILE, .built)
$(call CLEAN)
diff --git a/apps/mavlink/mavlink_receiver.c b/apps/mavlink/mavlink_receiver.c
index 9491ce7e3..86732d07c 100644
--- a/apps/mavlink/mavlink_receiver.c
+++ b/apps/mavlink/mavlink_receiver.c
@@ -587,12 +587,12 @@ receive_thread(void *arg)
struct pollfd fds[] = { { .fd = uart_fd, .events = POLLIN } };
if (poll(fds, 1, timeout) > 0) {
- /* non-blocking read */
- size_t nread = read(uart_fd, buf, sizeof(buf));
- ASSERT(nread > 0)
+ /* non-blocking read. read may return negative values */
+ ssize_t nread = read(uart_fd, buf, sizeof(buf));
- for (size_t i = 0; i < nread; i++) {
- if (mavlink_parse_char(chan, buf[i], &msg, &status)) { //parse the char
+ /* if read failed, this loop won't execute */
+ for (ssize_t i = 0; i < nread; i++) {
+ if (mavlink_parse_char(chan, buf[i], &msg, &status)) {
/* handle generic messages and commands */
handle_message(&msg);
diff --git a/apps/namedapp/Kconfig b/apps/namedapp/Kconfig
deleted file mode 100644
index 8d8f03421..000000000
--- a/apps/namedapp/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see misc/tools/kconfig-language.txt.
-#
-
-config NAMEDAPP
- bool "Support named applications"
- default n
- ---help---
- Enable support for named applications. This features assigns a string
- name to an application. This feature is also the underlying requirement
- to support built-in applications in the NuttShell (NSH).
-
-if NAMEDAPP
-endif
diff --git a/apps/namedapp/namedapp_list.h b/apps/namedapp/namedapp_list.h
new file mode 100644
index 000000000..72d1fa52d
--- /dev/null
+++ b/apps/namedapp/namedapp_list.h
@@ -0,0 +1,42 @@
+/* List of application requirements, generated during make context. */
+{ "math_demo", SCHED_PRIORITY_DEFAULT, 8192, math_demo_main },
+{ "control_demo", SCHED_PRIORITY_DEFAULT, 2048, control_demo_main },
+{ "kalman_demo", SCHED_PRIORITY_MAX - 30, 2048, kalman_demo_main },
+{ "reboot", SCHED_PRIORITY_DEFAULT, 2048, reboot_main },
+{ "perf", SCHED_PRIORITY_DEFAULT, 2048, perf_main },
+{ "top", SCHED_PRIORITY_DEFAULT - 10, 3000, top_main },
+{ "boardinfo", SCHED_PRIORITY_DEFAULT, 2048, boardinfo_main },
+{ "mixer", SCHED_PRIORITY_DEFAULT, 4096, mixer_main },
+{ "eeprom", SCHED_PRIORITY_DEFAULT, 4096, eeprom_main },
+{ "param", SCHED_PRIORITY_DEFAULT, 4096, param_main },
+{ "bl_update", SCHED_PRIORITY_DEFAULT, 4096, bl_update_main },
+{ "preflight_check", SCHED_PRIORITY_DEFAULT, 2048, preflight_check_main },
+{ "delay_test", SCHED_PRIORITY_DEFAULT, 2048, delay_test_main },
+{ "uorb", SCHED_PRIORITY_DEFAULT, 4096, uorb_main },
+{ "mavlink", SCHED_PRIORITY_DEFAULT, 2048, mavlink_main },
+{ "mavlink_onboard", SCHED_PRIORITY_DEFAULT, 2048, mavlink_onboard_main },
+{ "gps", SCHED_PRIORITY_DEFAULT, 2048, gps_main },
+{ "commander", SCHED_PRIORITY_MAX - 30, 2048, commander_main },
+{ "sdlog", SCHED_PRIORITY_MAX - 30, 2048, sdlog_main },
+{ "sensors", SCHED_PRIORITY_MAX-5, 4096, sensors_main },
+{ "ardrone_interface", SCHED_PRIORITY_MAX - 15, 2048, ardrone_interface_main },
+{ "multirotor_att_control", SCHED_PRIORITY_MAX - 15, 2048, multirotor_att_control_main },
+{ "multirotor_pos_control", SCHED_PRIORITY_MAX - 25, 2048, multirotor_pos_control_main },
+{ "fixedwing_att_control", SCHED_PRIORITY_MAX - 30, 2048, fixedwing_att_control_main },
+{ "fixedwing_pos_control", SCHED_PRIORITY_MAX - 30, 2048, fixedwing_pos_control_main },
+{ "position_estimator", SCHED_PRIORITY_DEFAULT, 4096, position_estimator_main },
+{ "attitude_estimator_ekf", SCHED_PRIORITY_DEFAULT, 2048, attitude_estimator_ekf_main },
+{ "ms5611", SCHED_PRIORITY_DEFAULT, 2048, ms5611_main },
+{ "hmc5883", SCHED_PRIORITY_DEFAULT, 4096, hmc5883_main },
+{ "mpu6000", SCHED_PRIORITY_DEFAULT, 4096, mpu6000_main },
+{ "bma180", SCHED_PRIORITY_DEFAULT, 2048, bma180_main },
+{ "l3gd20", SCHED_PRIORITY_DEFAULT, 2048, l3gd20_main },
+{ "px4io", SCHED_PRIORITY_DEFAULT, 2048, px4io_main },
+{ "blinkm", SCHED_PRIORITY_DEFAULT, 2048, blinkm_main },
+{ "tone_alarm", SCHED_PRIORITY_DEFAULT, 2048, tone_alarm_main },
+{ "adc", SCHED_PRIORITY_DEFAULT, 2048, adc_main },
+{ "fmu", SCHED_PRIORITY_DEFAULT, 2048, fmu_main },
+{ "hil", SCHED_PRIORITY_DEFAULT, 2048, hil_main },
+{ "tests", SCHED_PRIORITY_DEFAULT, 12000, tests_main },
+{ "sercon", SCHED_PRIORITY_DEFAULT, 2048, sercon_main },
+{ "serdis", SCHED_PRIORITY_DEFAULT, 2048, serdis_main },
diff --git a/apps/namedapp/namedapp_proto.h b/apps/namedapp/namedapp_proto.h
new file mode 100644
index 000000000..09f5b4156
--- /dev/null
+++ b/apps/namedapp/namedapp_proto.h
@@ -0,0 +1,42 @@
+/* List of application entry points, generated during make context. */
+EXTERN int math_demo_main(int argc, char *argv[]);
+EXTERN int control_demo_main(int argc, char *argv[]);
+EXTERN int kalman_demo_main(int argc, char *argv[]);
+EXTERN int reboot_main(int argc, char *argv[]);
+EXTERN int perf_main(int argc, char *argv[]);
+EXTERN int top_main(int argc, char *argv[]);
+EXTERN int boardinfo_main(int argc, char *argv[]);
+EXTERN int mixer_main(int argc, char *argv[]);
+EXTERN int eeprom_main(int argc, char *argv[]);
+EXTERN int param_main(int argc, char *argv[]);
+EXTERN int bl_update_main(int argc, char *argv[]);
+EXTERN int preflight_check_main(int argc, char *argv[]);
+EXTERN int delay_test_main(int argc, char *argv[]);
+EXTERN int uorb_main(int argc, char *argv[]);
+EXTERN int mavlink_main(int argc, char *argv[]);
+EXTERN int mavlink_onboard_main(int argc, char *argv[]);
+EXTERN int gps_main(int argc, char *argv[]);
+EXTERN int commander_main(int argc, char *argv[]);
+EXTERN int sdlog_main(int argc, char *argv[]);
+EXTERN int sensors_main(int argc, char *argv[]);
+EXTERN int ardrone_interface_main(int argc, char *argv[]);
+EXTERN int multirotor_att_control_main(int argc, char *argv[]);
+EXTERN int multirotor_pos_control_main(int argc, char *argv[]);
+EXTERN int fixedwing_att_control_main(int argc, char *argv[]);
+EXTERN int fixedwing_pos_control_main(int argc, char *argv[]);
+EXTERN int position_estimator_main(int argc, char *argv[]);
+EXTERN int attitude_estimator_ekf_main(int argc, char *argv[]);
+EXTERN int ms5611_main(int argc, char *argv[]);
+EXTERN int hmc5883_main(int argc, char *argv[]);
+EXTERN int mpu6000_main(int argc, char *argv[]);
+EXTERN int bma180_main(int argc, char *argv[]);
+EXTERN int l3gd20_main(int argc, char *argv[]);
+EXTERN int px4io_main(int argc, char *argv[]);
+EXTERN int blinkm_main(int argc, char *argv[]);
+EXTERN int tone_alarm_main(int argc, char *argv[]);
+EXTERN int adc_main(int argc, char *argv[]);
+EXTERN int fmu_main(int argc, char *argv[]);
+EXTERN int hil_main(int argc, char *argv[]);
+EXTERN int tests_main(int argc, char *argv[]);
+EXTERN int sercon_main(int argc, char *argv[]);
+EXTERN int serdis_main(int argc, char *argv[]);
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
index 17b107b8f..f6a5aa045 100644
--- a/apps/nshlib/Kconfig
+++ b/apps/nshlib/Kconfig
@@ -14,13 +14,22 @@ config NSH_LIBRARY
if NSH_LIBRARY
config NSH_BUILTIN_APPS
bool "Enable built-in applications"
- default y
- depends on NAMEDAPP
+ default n
+ depends on BUILTIN
---help---
- Support external registered, "named" applications that can be
+ Support external registered, "built-in" applications that can be
executed from the NSH command line (see apps/README.txt for
- more information). This options requires support for named applications
- (NAMEDAPP).
+ more information). This options requires support for builtin
+ applications (BUILTIN).
+
+config NSH_FILE_APPS
+ bool "Enable execution of program files"
+ default n
+ depends on LIBC_EXECFUNCS
+ ---help---
+ Support execution of program files residing within a file
+ system. This options requires support for the posix_spawn()
+ interface (LIBC_EXECFUNCS).
menu "Disable Individual commands"
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
index 73325e899..948f43d52 100644
--- a/apps/nshlib/Makefile
+++ b/apps/nshlib/Makefile
@@ -44,7 +44,11 @@ CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_fscmds.c nsh_ddcmd.c \
nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c nsh_dbgcmds.c
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
-CSRCS += nsh_apps.c
+CSRCS += nsh_builtin.c
+endif
+
+ifeq ($(CONFIG_NSH_FILE_APPS),y)
+CSRCS += nsh_fileapps.c
endif
ifeq ($(CONFIG_NSH_ROMFSETC),y)
@@ -130,7 +134,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt
index bc626e699..006839628 100644
--- a/apps/nshlib/README.txt
+++ b/apps/nshlib/README.txt
@@ -945,7 +945,7 @@ NSH-Specific Configuration Settings
the configs/<board-name>/defconfig file:
* CONFIG_NSH_BUILTIN_APPS
- Support external registered, "named" applications that can be
+ Support external registered, "builtin" applications that can be
executed from the NSH command line (see apps/README.txt for
more information).
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index a046a384f..64099a8df 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -491,7 +491,13 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline);
/* Application interface */
#ifdef CONFIG_NSH_BUILTIN_APPS
-int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, FAR char **argv);
+int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags);
+#endif
+
+#ifdef CONFIG_NSH_FILE_APPS
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags);
#endif
/* Working directory support */
diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_builtin.c
index 7dbaf9ba8..0d5a0231c 100644
--- a/apps/nshlib/nsh_apps.c
+++ b/apps/nshlib/nsh_builtin.c
@@ -1,10 +1,16 @@
/****************************************************************************
- * apps/nshlib/nsh_apps.c
+ * apps/nshlib/nsh_builtin.c
+ *
+ * Originally by:
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -48,7 +54,8 @@
#include <errno.h>
#include <string.h>
-#include <apps/apps.h>
+#include <nuttx/binfmt/builtin.h>
+#include <apps/builtin.h>
#include "nsh.h"
#include "nsh_console.h"
@@ -84,13 +91,13 @@
****************************************************************************/
/****************************************************************************
- * Name: nsh_execapp
+ * Name: nsh_builtin
*
* Description:
* Attempt to execute the application task whose name is 'cmd'
*
* Returned Value:
- * <0 If exec_namedapp() fails, then the negated errno value
+ * <0 If exec_builtin() fails, then the negated errno value
* is returned.
* -1 (ERROR) if the application task corresponding to 'cmd' could not
* be started (possibly because it doesn not exist).
@@ -104,13 +111,13 @@
*
****************************************************************************/
-int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
- FAR char **argv)
+int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags)
{
int ret = OK;
- /* Lock the scheduler to prevent the application from running until the
- * waitpid() has been called.
+ /* Lock the scheduler in an attempt to prevent the application from
+ * running until waitpid() has been called.
*/
sched_lock();
@@ -119,19 +126,23 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
* applications.
*/
- ret = exec_namedapp(cmd, (FAR const char **)argv);
+ ret = exec_builtin(cmd, (FAR const char **)argv, redirfile, oflags);
if (ret >= 0)
{
- /* The application was successfully started (but still blocked because
- * the scheduler is locked). If the application was not backgrounded,
- * then we need to wait here for the application to exit. These really
- * only works works with the following options:
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. But in the case where I/O was redirected, a
+ * proxy task ran and broke our lock. As result, the application may
+ * have aso ran if its priority was higher than than the priority of
+ * this thread.
+ *
+ * If the application did not run to completion and if the application
+ * was not backgrounded, then we need to wait here for the application
+ * to exit. This only works works with the following options:
*
* - CONFIG_NSH_DISABLEBG - Do not run commands in background
* - CONFIG_SCHED_WAITPID - Required to run external commands in
* foreground
- *
- * These concepts do not apply cleanly to the external applications.
*/
#ifdef CONFIG_SCHED_WAITPID
@@ -147,15 +158,46 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
int rc = 0;
- /* Wait for the application to exit. Since we have locked the
- * scheduler above, we know that the application has not yet
- * started and there is no possibility that it has already exited.
- * The scheduler will be unlocked while waitpid is waiting and the
- * application will be able to run.
+ /* Wait for the application to exit. We did lock the scheduler
+ * above, but that does not guarantee that the application did not
+ * already run to completion in the case where I/O was redirected.
+ * Here the scheduler will be unlocked while waitpid is waiting
+ * and if the application has not yet run, it will now be able to
+ * do so.
+ *
+ * Also, if CONFIG_SCHED_HAVE_PARENT is defined waitpid() might fail
+ * even if task is still active: If the I/O was re-directed by a
+ * proxy task, then the ask is a child of the proxy, and not this
+ * task. waitpid() fails with ECHILD in either case.
*/
ret = waitpid(ret, &rc, 0);
- if (ret >= 0)
+ if (ret < 0)
+ {
+ /* If the child thread does not exist, waitpid() will return
+ * the error ECHLD. Since we know that the task was successfully
+ * started, this must be one of the cases described above; we
+ * have to assume that the task already exit'ed. In this case,
+ * we have no idea if the application ran successfully or not
+ * (because NuttX does not retain exit status of child tasks).
+ * Let's assume that is did run successfully.
+ */
+
+ int errcode = errno;
+ if (errcode == ECHILD)
+ {
+ ret = OK;
+ }
+ else
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "waitpid",
+ NSH_ERRNO_OF(errcode));
+ }
+ }
+
+ /* Waitpid completed the wait successfully */
+
+ else
{
/* We can't return the exact status (nsh has nowhere to put it)
* so just pass back zero/nonzero in a fashion that doesn't look
@@ -191,7 +233,7 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
#if !defined(CONFIG_SCHED_WAITPID) || !defined(CONFIG_NSH_DISABLEBG)
{
struct sched_param param;
- sched_getparam(0, &param);
+ sched_getparam(ret, &param);
nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
/* Backgrounded commands always 'succeed' as long as we can start
@@ -205,13 +247,13 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
sched_unlock();
- /* If exec_namedapp() or waitpid() failed, then return the negated errno
- * value.
+ /* If exec_builtin() or waitpid() failed, then return -1 (ERROR) with the
+ * errno value set appropriately.
*/
if (ret < 0)
{
- return -errno;
+ return ERROR;
}
return ret;
diff --git a/apps/nshlib/nsh_codeccmd.c b/apps/nshlib/nsh_codeccmd.c
new file mode 100644
index 000000000..779fc5ecd
--- /dev/null
+++ b/apps/nshlib/nsh_codeccmd.c
@@ -0,0 +1,538 @@
+/****************************************************************************
+ * apps/nshlib/nsh_codeccmd.c
+ *
+ * This file is part of NuttX, contributed by Darcy Gong
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Darcy Gong 2012-10-30
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#ifdef CONFIG_NETUTILS_CODECS
+
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <errno.h>
+#include <debug.h>
+
+#if defined(CONFIG_NSH_DISABLE_URLENCODE) && defined(CONFIG_NSH_DISABLE_URLDECODE)
+# undef CONFIG_CODECS_URLCODE
+#endif
+
+#ifdef CONFIG_CODECS_URLCODE
+#include <apps/netutils/urldecode.h>
+#endif
+
+#if defined(CONFIG_NSH_DISABLE_BASE64ENC) && defined(CONFIG_NSH_DISABLE_BASE64ENC)
+# undef CONFIG_CODECS_BASE64
+#endif
+
+#ifdef CONFIG_CODECS_BASE64
+#include <apps/netutils/base64.h>
+#endif
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+#include <apps/netutils/md5.h>
+#endif
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_CODECS_BUFSIZE
+# define CONFIG_NSH_CODECS_BUFSIZE 128
+#endif
+
+#define CODEC_MODE_URLENCODE 1
+#define CODEC_MODE_URLDECODE 2
+#define CODEC_MODE_BASE64ENC 3
+#define CODEC_MODE_BASE64DEC 4
+#define CODEC_MODE_HASH_MD5 5
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef void (*codec_callback_t)(FAR char *src_buff, int src_buff_len,
+ FAR char *dst_buff, FAR int *dst_buff_len,
+ int mode);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: urlencode_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLENCODE)
+static void urlencode_cb(FAR char *src_buff, int src_buff_len,
+ FAR char *dst_buff, FAR int *dst_buff_len, int mode)
+{
+ urlencode(src_buff,src_buff_len,dst_buff,dst_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: urldecode_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+static void urldecode_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ urldecode(src_buff,src_buff_len,dst_buff,dst_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: b64enc_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+static void b64enc_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ if (mode == 0)
+ {
+ //dst_buff =
+ base64_encode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+ else
+ {
+ //dst_buff =
+ base64w_encode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: b64dec_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64DEC)
+static void b64dec_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ if (mode == 0)
+ {
+ //dst_buff =
+ base64_decode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+ else
+ {
+ //dst_buff =
+ base64w_decode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff,(size_t *)dst_buff_len);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: md5_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+static void md5_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ MD5Update((MD5_CTX *)dst_buff, (unsigned char *)src_buff, src_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: calc_codec_buffsize
+ ****************************************************************************/
+
+static int calc_codec_buffsize(int src_buffsize, uint8_t mode)
+{
+ switch (mode)
+ {
+ case CODEC_MODE_URLENCODE:
+ return src_buffsize*3+1;
+ case CODEC_MODE_URLDECODE:
+ return src_buffsize+1;
+ case CODEC_MODE_BASE64ENC:
+ return ((src_buffsize + 2)/ 3 * 4)+1;
+ case CODEC_MODE_BASE64DEC:
+ return (src_buffsize / 4 * 3 + 2)+1;
+ case CODEC_MODE_HASH_MD5:
+ return 32+1;
+ default:
+ return src_buffsize+1;
+ }
+}
+
+/****************************************************************************
+ * Name: cmd_codecs_proc
+ ****************************************************************************/
+
+static int cmd_codecs_proc(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+ uint8_t mode, codec_callback_t func)
+{
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ static const unsigned char hex_chars[] = "0123456789abcdef";
+ MD5_CTX ctx;
+ unsigned char mac[16];
+ char *pSrc;
+ char *pDest;
+#endif
+
+ char *localfile = NULL;
+ char *src_buffer = NULL;
+ char *buffer = NULL;
+ char *fullpath = NULL;
+ const char *fmt;
+ char *s_data;
+ bool badarg = false;
+ bool is_file = false;
+ bool is_websafe=false;
+ int option;
+ int fd = -1;
+ int buff_len = 0;
+ int src_buff_len = 0;
+ int i = 0;
+ int ret = OK;
+
+ /* Get the command options */
+
+ while ((option = getopt(argc, argv, ":fw")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'f':
+ is_file = true;
+ break;
+
+#ifdef CONFIG_CODECS_BASE64
+ case 'w':
+ is_websafe = true;
+
+ if (!(mode == CODEC_MODE_BASE64ENC || mode == CODEC_MODE_BASE64DEC))
+ {
+ badarg = true;
+ }
+ break;
+#endif
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ badarg = true;
+ break;
+ }
+ }
+
+ /* If a bad argument was encountered, then return without processing the command */
+
+ if (badarg)
+ {
+ return ERROR;
+ }
+
+ /* There should be exactly on parameter left on the command-line */
+
+ if (optind == argc-1)
+ {
+ s_data = argv[optind];
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ MD5Init(&ctx);
+ }
+#endif
+
+ if (is_file)
+ {
+ /* Get the local file name */
+
+ localfile = s_data;
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, localfile);
+
+ /* Open the local file for writing */
+
+ fd = open(fullpath, O_RDONLY|O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ ret = ERROR;
+ goto exit;
+ }
+
+ src_buffer = malloc(CONFIG_NSH_CODECS_BUFSIZE+2);
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+ if (mode == CODEC_MODE_BASE64ENC)
+ {
+ src_buff_len = CONFIG_NSH_CODECS_BUFSIZE / 3 * 3;
+ }
+ else
+#endif
+ {
+ src_buff_len = CONFIG_NSH_CODECS_BUFSIZE;
+ }
+
+ buff_len = calc_codec_buffsize(src_buff_len+2, mode);
+ buffer = malloc(buff_len);
+ while(true)
+ {
+ memset(src_buffer, 0, src_buff_len+2);
+ ret=read(fd, src_buffer, src_buff_len);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
+ ret = ERROR;
+ goto exit;
+ }
+ else if(ret==0)
+ {
+ break;
+ }
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+ if (mode == CODEC_MODE_URLDECODE)
+ {
+ if (src_buffer[src_buff_len-1]=='%')
+ {
+ ret += read(fd,&src_buffer[src_buff_len],2);
+ }
+ else if (src_buffer[src_buff_len-2]=='%')
+ {
+ ret += read(fd,&src_buffer[src_buff_len],1);
+ }
+ }
+#endif
+ memset(buffer, 0, buff_len);
+ if (func)
+ {
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ func(src_buffer, ret, (char *)&ctx, &buff_len,0);
+ }
+ else
+#endif
+ {
+ func(src_buffer, ret, buffer, &buff_len,(is_websafe)?1:0);
+ nsh_output(vtbl, "%s", buffer);
+ }
+ }
+
+ buff_len = calc_codec_buffsize(src_buff_len+2, mode);
+ }
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ MD5Final(mac, &ctx);
+ pSrc = (char *)&mac;
+ pDest = buffer;
+ for(i=0;i<16;i++,pSrc++)
+ {
+ *pDest++ = hex_chars[(*pSrc) >> 4];
+ *pDest++ = hex_chars[(*pSrc) & 0x0f];
+ }
+
+ *pDest='\0';
+ nsh_output(vtbl, "%s\n", buffer);
+ }
+#endif
+ ret = OK;
+ goto exit;
+ }
+ else
+ {
+ src_buffer = s_data;
+ src_buff_len = strlen(s_data);
+ buff_len = calc_codec_buffsize(src_buff_len, mode);
+ buffer = malloc(buff_len);
+ buffer[0]=0;
+ if (!buffer)
+ {
+ fmt = g_fmtcmdoutofmemory;
+ goto errout;
+ }
+
+ memset(buffer, 0, buff_len);
+ if (func)
+ {
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ func(src_buffer, src_buff_len, (char *)&ctx, &buff_len, 0);
+ MD5Final(mac, &ctx);
+ pSrc = (char *)&mac;
+ pDest = buffer;
+ for(i=0;i<16;i++,pSrc++)
+ {
+ *pDest++ = hex_chars[(*pSrc) >> 4];
+ *pDest++ = hex_chars[(*pSrc) & 0x0f];
+ }
+
+ *pDest='\0';
+ }
+ else
+#endif
+ {
+ func(src_buffer, src_buff_len, buffer, &buff_len,(is_websafe)?1:0);
+ }
+ }
+
+ nsh_output(vtbl, "%s\n",buffer);
+ src_buffer = NULL;
+ goto exit;
+ }
+
+exit:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+
+ if (fullpath)
+ {
+ free(fullpath);
+ }
+
+ if (src_buffer)
+ {
+ free(src_buffer);
+ }
+
+ if (buffer)
+ {
+ free(buffer);
+ }
+
+ return ret;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ ret = ERROR;
+ goto exit;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_urlencode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLENCODE)
+int cmd_urlencode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLENCODE, urlencode_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_urldecode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+int cmd_urldecode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLDECODE, urldecode_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_base64encode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+int cmd_base64encode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64ENC, b64enc_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_base64decode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64DEC)
+int cmd_base64decode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64DEC, b64dec_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_md5
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+int cmd_md5(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl,argc,argv,CODEC_MODE_HASH_MD5,md5_cb);
+}
+#endif
+
+#endif /* CONFIG_NETUTILS_CODECS */
diff --git a/apps/nshlib/nsh_fileapps.c b/apps/nshlib/nsh_fileapps.c
new file mode 100644
index 000000000..9ff230f1a
--- /dev/null
+++ b/apps/nshlib/nsh_fileapps.c
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * apps/nshlib/nsh_fileapps.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_SCHED_WAITPID
+# include <sys/wait.h>
+#endif
+
+#include <stdbool.h>
+#include <spawn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#ifdef CONFIG_NSH_FILE_APPS
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_fileapp
+ *
+ * Description:
+ * Attempt to execute the application task whose name is 'cmd'
+ *
+ * Returned Value:
+ * <0 If exec_builtin() fails, then the negated errno value
+ * is returned.
+ * -1 (ERROR) if the application task corresponding to 'cmd' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'cmd' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ ****************************************************************************/
+
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags)
+{
+ posix_spawn_file_actions_t file_actions;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int ret;
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_init returns a positive errno value on
+ * failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawn_file_actions_init",
+ NSH_ERRNO_OF(ret));
+ goto errout;
+ }
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ /* posix_spawnattr_init returns a positive errno value on failure. */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawnattr_init",
+ NSH_ERRNO);
+ goto errout_with_actions;
+ }
+
+ /* Handle re-direction of output */
+
+ if (redirfile)
+ {
+ ret = posix_spawn_file_actions_addopen(&file_actions, 1, redirfile,
+ oflags, 0644);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_addopen returns a positive errno
+ * value on failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd,
+ "posix_spawn_file_actions_addopen",
+ NSH_ERRNO);
+ goto errout_with_attrs;
+ }
+ }
+
+ /* Lock the scheduler in an attempt to prevent the application from
+ * running until waitpid() has been called.
+ */
+
+ sched_lock();
+
+ /* Execute the program. posix_spawnp returns a positive errno value on
+ * failure.
+ */
+
+ ret = posix_spawnp(&pid, cmd, &file_actions, &attr, &argv[1], NULL);
+ if (ret == OK)
+ {
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. But in the case where I/O was redirected, a
+ * proxy task ran and broke our lock. As result, the application may
+ * have aso ran if its priority was higher than than the priority of
+ * this thread.
+ *
+ * If the application did not run to completion and if the application
+ * was not backgrounded, then we need to wait here for the application
+ * to exit. This only works works with the following options:
+ *
+ * - CONFIG_NSH_DISABLEBG - Do not run commands in background
+ * - CONFIG_SCHED_WAITPID - Required to run external commands in
+ * foreground
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+
+ /* CONFIG_SCHED_WAITPID is selected, so we may run the command in
+ * foreground unless we were specifically requested to run the command
+ * in background (and running commands in background is enabled).
+ */
+
+# ifndef CONFIG_NSH_DISABLEBG
+ if (vtbl->np.np_bg == false)
+# endif /* CONFIG_NSH_DISABLEBG */
+ {
+ int rc = 0;
+
+ /* Wait for the application to exit. We did lock the scheduler
+ * above, but that does not guarantee that the application did not
+ * already run to completion in the case where I/O was redirected.
+ * Here the scheduler will be unlocked while waitpid is waiting
+ * and if the application has not yet run, it will now be able to
+ * do so.
+ */
+
+ ret = waitpid(pid, &rc, 0);
+ if (ret < 0)
+ {
+ /* If the child thread does not exist, waitpid() will return
+ * the error ECHLD. Since we know that the task was successfully
+ * started, this must be one of the cases described above; we
+ * have to assume that the task already exit'ed. In this case,
+ * we have no idea if the application ran successfully or not
+ * (because NuttX does not retain exit status of child tasks).
+ * Let's assume that is did run successfully.
+ */
+
+ int errcode = errno;
+ if (errcode == ECHILD)
+ {
+ ret = OK;
+ }
+ else
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "waitpid",
+ NSH_ERRNO_OF(errcode));
+ }
+ }
+
+ /* Waitpid completed the wait successfully */
+
+ else
+ {
+ /* We can't return the exact status (nsh has nowhere to put it)
+ * so just pass back zero/nonzero in a fashion that doesn't look
+ * like an error.
+ */
+
+ ret = (rc == 0) ? OK : 1;
+
+ /* TODO: Set the environment variable '?' to a string corresponding
+ * to WEXITSTATUS(rc) so that $? will expand to the exit status of
+ * the most recently executed task.
+ */
+ }
+ }
+# ifndef CONFIG_NSH_DISABLEBG
+ else
+# endif /* CONFIG_NSH_DISABLEBG */
+#endif /* CONFIG_SCHED_WAITPID */
+
+ /* We get here if either:
+ *
+ * - CONFIG_SCHED_WAITPID is not selected meaning that all commands
+ * have to be run in background, or
+ * - CONFIG_SCHED_WAITPID and CONFIG_NSH_DISABLEBG are both selected, but the
+ * user requested to run the command in background.
+ *
+ * NOTE that the case of a) CONFIG_SCHED_WAITPID is not selected and
+ * b) CONFIG_NSH_DISABLEBG selected cannot be supported. In that event, all
+ * commands will have to run in background. The waitpid() API must be
+ * available to support running the command in foreground.
+ */
+
+#if !defined(CONFIG_SCHED_WAITPID) || !defined(CONFIG_NSH_DISABLEBG)
+ {
+ struct sched_param param;
+ sched_getparam(ret, &param);
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
+
+ /* Backgrounded commands always 'succeed' as long as we can start
+ * them.
+ */
+
+ ret = OK;
+ }
+#endif /* !CONFIG_SCHED_WAITPID || !CONFIG_NSH_DISABLEBG */
+ }
+
+ sched_unlock();
+
+ /* Free attibutes and file actions. Ignoring return values in the case
+ * of an error.
+ */
+
+errout_with_actions:
+ (void)posix_spawn_file_actions_destroy(&file_actions);
+
+errout_with_attrs:
+ (void)posix_spawnattr_destroy(&attr);
+
+errout:
+ /* Most posix_spawn interfaces return a positive errno value on failure
+ * and do not set the errno variable.
+ */
+
+ if (ret > 0)
+ {
+ /* Set the errno value and return -1 */
+
+ set_errno(ret);
+ ret = ERROR;
+ }
+ else if (ret < 0)
+ {
+ /* Return -1 on failure. errno should have been set. */
+
+ ret = ERROR;
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NSH_FILE_APPS */
diff --git a/apps/nshlib/nsh_mntcmds.c b/apps/nshlib/nsh_mntcmds.c
index 690d027ca..f8e3a142a 100644
--- a/apps/nshlib/nsh_mntcmds.c
+++ b/apps/nshlib/nsh_mntcmds.c
@@ -45,10 +45,13 @@
#include <stdint.h>
#include <stdbool.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
+#include <nuttx/fs/nfs.h>
+
#include "nsh.h"
#include "nsh_console.h"
@@ -128,9 +131,9 @@ static int mount_handler(FAR const char *mountpoint,
break;
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
case BINFS_MAGIC:
- fstype = "bindir";
+ fstype = "binfs";
break;
#endif
@@ -195,9 +198,11 @@ int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- FAR char *source;
- FAR char *target;
- FAR char *filesystem = NULL;
+ FAR const char *source;
+ FAR char *fullsource;
+ FAR const char *target;
+ FAR char *fulltarget;
+ FAR const char *filesystem = NULL;
bool badarg = false;
int option;
int ret;
@@ -245,19 +250,32 @@ int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
return ERROR;
}
- /* There are two required arguments after the options: the source and target
- * paths.
+ /* There may be one or two required arguments after the options: the source
+ * and target paths. Some file systems do not require the source parameter
+ * so if there is only one parameter left, it must be the target.
*/
- if (optind + 2 < argc)
+ if (optind >= argc)
{
- nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
return ERROR;
}
- else if (optind + 2 > argc)
+
+ source = NULL;
+ target = argv[optind];
+ optind++;
+
+ if (optind < argc)
{
- nsh_output(vtbl, g_fmtargrequired, argv[0]);
- return ERROR;
+ source = target;
+ target = argv[optind];
+ optind++;
+
+ if (optind < argc)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ return ERROR;
+ }
}
/* While the above parsing for the -t argument looks nice, the -t argument
@@ -274,29 +292,44 @@ int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* working directory.
*/
- source = nsh_getfullpath(vtbl, argv[optind]);
- if (!source)
+ fullsource = NULL;
+ fulltarget = NULL;
+
+ if (source)
{
- return ERROR;
+ fullsource = nsh_getfullpath(vtbl, source);
+ if (!fullsource)
+ {
+ return ERROR;
+ }
}
- target = nsh_getfullpath(vtbl, argv[optind+1]);
- if (!target)
+ fulltarget = nsh_getfullpath(vtbl, target);
+ if (!fulltarget)
{
- nsh_freefullpath(source);
- return ERROR;
+ ret = ERROR;
+ goto errout;
}
/* Perform the mount */
- ret = mount(source, target, filesystem, 0, NULL);
+ ret = mount(fullsource, fulltarget, filesystem, 0, NULL);
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
}
- nsh_freefullpath(source);
- nsh_freefullpath(target);
+errout:
+ if (fullsource)
+ {
+ nsh_freefullpath(fullsource);
+ }
+
+ if (fulltarget)
+ {
+ nsh_freefullpath(fulltarget);
+ }
+
return ret;
}
#endif
diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c
index 371d30460..473045c40 100644
--- a/apps/nshlib/nsh_netcmds.c
+++ b/apps/nshlib/nsh_netcmds.c
@@ -53,12 +53,13 @@
#include <errno.h>
#include <debug.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+
#include <nuttx/net/net.h>
#include <nuttx/clock.h>
-#include <net/ethernet.h>
#include <nuttx/net/uip/uip.h>
#include <nuttx/net/uip/uip-arch.h>
-#include <netinet/ether.h>
#ifdef CONFIG_NET_STATISTICS
# include <nuttx/net/uip/uip.h>
@@ -67,6 +68,7 @@
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
# include <apps/netutils/uiplib.h>
+# include <apps/netutils/resolv.h>
#endif
#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index 27068acff..f679d9b32 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh_parse.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -59,8 +59,9 @@
#endif
#ifdef CONFIG_NSH_BUILTIN_APPS
-# include <apps/apps.h>
+# include <nuttx/binfmt/builtin.h>
#endif
+
#include <apps/nsh.h>
#include "nsh.h"
@@ -72,7 +73,7 @@
/* Argument list size
*
- * argv[0]: The command name.
+ * argv[0]: The command name.
* argv[1]: The beginning of argument (up to CONFIG_NSH_MAXARGUMENTS)
* argv[argc-3]: Possibly '>' or '>>'
* argv[argc-2]: Possibly <file>
@@ -226,7 +227,7 @@ static const struct cmdmap_s g_cmdmap[] =
{ "help", cmd_help, 1, 3, "[-v] [<cmd>]" },
# endif
#endif
-
+
#if CONFIG_NFILE_DESCRIPTORS > 0
#ifndef CONFIG_NSH_DISABLE_HEXDUMP
{ "hexdump", cmd_hexdump, 2, 2, "<file or device>" },
@@ -301,7 +302,7 @@ static const struct cmdmap_s g_cmdmap[] =
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
# ifndef CONFIG_NSH_DISABLE_MOUNT
- { "mount", cmd_mount, 1, 5, "[-t <fstype> <block-device> <mount-point>]" },
+ { "mount", cmd_mount, 1, 5, "[-t <fstype> [<block-device>] <mount-point>]" },
# endif
#endif
@@ -605,7 +606,7 @@ static inline void help_builtins(FAR struct nsh_vtbl_s *vtbl)
/* List the set of available built-in commands */
nsh_output(vtbl, "\nBuiltin Apps:\n");
- for (i = 0; (name = namedapp_getname(i)) != NULL; i++)
+ for (i = 0; (name = builtin_getname(i)) != NULL; i++)
{
nsh_output(vtbl, " %s\n", name);
}
@@ -723,15 +724,11 @@ static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* Name: nsh_execute
*
* Description:
- * Exectue the command in argv[0]
+ * Execute the command in argv[0]
*
* Returned Value:
- * <0 If exec_namedapp() fails, then the negated errno value
- * is returned.
* -1 (ERRROR) if the command was unsuccessful
* 0 (OK) if the command was successful
- * 1 if an application task was spawned successfully, but
- * returned failure exit status.
*
****************************************************************************/
@@ -751,21 +748,6 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[])
*/
cmd = argv[0];
-
- /* Try to find a command in the application library. */
-
-#ifdef CONFIG_NSH_BUILTIN_APPS
- ret = nsh_execapp(vtbl, cmd, argv);
-
- /* If the built-in application was successfully started, return OK
- * or 1 (if the application returned a non-zero exit status).
- */
-
- if (ret >= 0)
- {
- return ret;
- }
-#endif
/* See if the command is one that we understand */
@@ -1352,7 +1334,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
/* Parse all of the arguments following the command name. The form
* of argv is:
*
- * argv[0]: The command name.
+ * argv[0]: The command name.
* argv[1]: The beginning of argument (up to CONFIG_NSH_MAXARGUMENTS)
* argv[argc-3]: Possibly '>' or '>>'
* argv[argc-2]: Possibly <file>
@@ -1410,6 +1392,81 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
}
}
+ /* Check if the maximum number of arguments was exceeded */
+
+ if (argc > CONFIG_NSH_MAXARGUMENTS)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
+ }
+
+ /* Does this command correspond to an application filename?
+ * nsh_fileapp() returns:
+ *
+ * -1 (ERROR) if the application task corresponding to 'argv[0]' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'argv[0]' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ * Note the priority if not effected by nice-ness.
+ */
+
+#ifdef CONFIG_NSH_FILE_APPS
+ ret = nsh_fileapp(vtbl, argv[0], argv, redirfile, oflags);
+ if (ret >= 0)
+ {
+ /* nsh_fileapp() returned 0 or 1. This means that the builtin
+ * command was successfully started (although it may not have ran
+ * successfully). So certainly it is not an NSH command.
+ */
+
+ return nsh_saveresult(vtbl, ret != OK);
+ }
+
+ /* No, not a built in command (or, at least, we were unable to start a
+ * builtin command of that name). Treat it like an NSH command.
+ */
+
+#endif
+
+ /* Does this command correspond to a builtin command?
+ * nsh_builtin() returns:
+ *
+ * -1 (ERROR) if the application task corresponding to 'argv[0]' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'argv[0]' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ * Note the priority if not effected by nice-ness.
+ */
+
+#if defined(CONFIG_NSH_BUILTIN_APPS) && (!defined(CONFIG_NSH_FILE_APPS) || !defined(CONFIG_FS_BINFS))
+ ret = nsh_builtin(vtbl, argv[0], argv, redirfile, oflags);
+ if (ret >= 0)
+ {
+ /* nsh_builtin() returned 0 or 1. This means that the builtin
+ * command was successfully started (although it may not have ran
+ * successfully). So certainly it is not an NSH command.
+ */
+
+ return nsh_saveresult(vtbl, ret != OK);
+ }
+
+ /* No, not a built in command (or, at least, we were unable to start a
+ * builtin command of that name). Treat it like an NSH command.
+ */
+
+#endif
+
/* Redirected output? */
if (vtbl->np.np_redirect)
@@ -1431,23 +1488,13 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
}
}
- /* Check if the maximum number of arguments was exceeded */
-
- if (argc > CONFIG_NSH_MAXARGUMENTS)
- {
- nsh_output(vtbl, g_fmttoomanyargs, cmd);
- }
-
/* Handle the case where the command is executed in background.
- * However is app is to be started as namedapp new process will
- * be created anyway, so skip this step. */
+ * However is app is to be started as builtin new process will
+ * be created anyway, so skip this step.
+ */
#ifndef CONFIG_NSH_DISABLEBG
- if (vtbl->np.np_bg
-#ifdef CONFIG_NSH_BUILTIN_APPS
- && namedapp_isavail(argv[0]) < 0
-#endif
- )
+ if (vtbl->np.np_bg)
{
struct sched_param param;
struct nsh_vtbl_s *bkgvtbl;
@@ -1514,6 +1561,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
priority = min_priority;
}
}
+
param.sched_priority = priority;
}
@@ -1553,8 +1601,6 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
*
* -1 (ERRROR) if the command was unsuccessful
* 0 (OK) if the command was successful
- * 1 if an application task was spawned successfully, but
- * returned failure exit status.
*/
ret = nsh_execute(vtbl, argc, argv);
@@ -1568,11 +1614,11 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
nsh_undirect(vtbl, save);
}
- /* Treat both errors and non-zero return codes as "errors" so that
- * it is possible to test for non-zero returns in nsh scripts.
+ /* Mark errors so that it is possible to test for non-zero return values
+ * in nsh scripts.
*/
- if (ret != OK)
+ if (ret < 0)
{
goto errout;
}
diff --git a/apps/px4/tests/test_hott_telemetry.c b/apps/px4/tests/test_hott_telemetry.c
new file mode 100644
index 000000000..74aa0e614
--- /dev/null
+++ b/apps/px4/tests/test_hott_telemetry.c
@@ -0,0 +1,239 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Author: @author Simon Wilks <sjwilks@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file test_hott_telemetry.c
+ *
+ * Tests the Graupner HoTT telemetry support.
+ *
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <drivers/drv_gpio.h>
+#include <nuttx/config.h>
+#include <sys/types.h>
+
+#include <debug.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "tests.h"
+
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+static int open_uart(const char *device)
+{
+ /* baud rate */
+ int speed = B19200;
+
+ /* open uart */
+ int uart = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart < 0) {
+ errx(1, "FAIL: Error opening port");
+ return ERROR;
+ }
+
+ /* Try to set baud rate */
+ struct termios uart_config;
+
+ /* Fill the struct for the new configuration */
+ tcgetattr(uart, &uart_config);
+
+ /* Clear ONLCR flag (which appends a CR for every LF) */
+ uart_config.c_oflag &= ~ONLCR;
+
+ /* Set baud rate */
+ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) {
+ errx(1, "FAIL: Error setting baudrate / termios config for cfsetispeed, cfsetospeed");
+ return ERROR;
+ }
+
+ if (tcsetattr(uart, TCSANOW, &uart_config) < 0) {
+ errx(1, "FAIL: Error setting baudrate / termios config for tcsetattr");
+ return ERROR;
+ }
+
+ return uart;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: test_hott_telemetry
+ ****************************************************************************/
+
+int test_hott_telemetry(int argc, char *argv[])
+{
+ warnx("HoTT Telemetry Test Requirements:");
+ warnx("- Radio on and Electric Air. Mod on (telemetry -> sensor select).");
+ warnx("- Receiver telemetry port must be in telemetry mode.");
+ warnx("- Connect telemetry wire to /dev/ttyS1 (USART2).");
+ warnx("Testing...");
+
+ const char device[] = "/dev/ttyS1";
+ int fd = open_uart(device);
+
+ if (fd < 0) {
+ close(fd);
+ return ERROR;
+ }
+
+ /* Activate single wire mode */
+ ioctl(fd, TIOCSSINGLEWIRE, SER_SINGLEWIRE_ENABLED);
+
+ char send = 'a';
+ write(fd, &send, 1);
+
+ /* Since TX and RX are now connected we should be able to read in what we wrote */
+ const int timeout = 1000;
+ struct pollfd fds[] = { { .fd = fd, .events = POLLIN } };
+
+ if (poll(fds, 1, timeout) == 0) {
+ errx(1, "FAIL: Could not read sent data.");
+ }
+
+ char receive;
+ read(fd, &receive, 1);
+ warnx("PASS: Single wire enabled. Sent %x and received %x", send, receive);
+
+
+ /* Attempt to read HoTT poll messages from the HoTT receiver */
+ int received_count = 0;
+ int valid_count = 0;
+ const int max_polls = 5;
+ uint8_t byte;
+
+ for (; received_count < 5; received_count++) {
+ if (poll(fds, 1, timeout) == 0) {
+ errx(1, "FAIL: Could not read sent data. Is your HoTT receiver plugged in on %s?", device);
+ break;
+
+ } else {
+ read(fd, &byte, 1);
+
+ if (byte == 0x80) {
+ valid_count++;
+ }
+
+ /* Read the device ID being polled */
+ read(fd, &byte, 1);
+ }
+ }
+
+ if (received_count > 0 && valid_count > 0) {
+ if (received_count == max_polls && valid_count == max_polls) {
+ warnx("PASS: Received %d out of %d valid byte pairs from the HoTT receiver device.", received_count, max_polls);
+
+ } else {
+ warnx("WARN: Received %d out of %d byte pairs of which %d were valid from the HoTT receiver device.", received_count, max_polls, valid_count);
+ }
+
+ } else {
+ /* Let's work out what went wrong */
+ if (received_count == 0) {
+ errx(1, "FAIL: Could not read any polls from HoTT receiver device.");
+ }
+
+ if (valid_count == 0) {
+ errx(1, "FAIL: Received unexpected values from the HoTT receiver device.");
+ }
+ }
+
+
+ /* Attempt to send a HoTT response messages */
+ uint8_t response[] = {0x7c, 0x8e, 0x00, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, \
+ 0x19, 0x00, 0x00, 0x00, 0x30, 0x75, 0x78, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x7d, 0x12
+ };
+
+ usleep(5000);
+
+ for (unsigned int i = 0; i < sizeof(response); i++) {
+ write(fd, &response[i], 1);
+ usleep(1000);
+ }
+
+ warnx("PASS: Response sent to the HoTT receiver device. Voltage should now show 2.5V.");
+
+
+ /* Disable single wire */
+ ioctl(fd, TIOCSSINGLEWIRE, ~SER_SINGLEWIRE_ENABLED);
+
+ write(fd, &send, 1);
+
+ /* We should timeout as there will be nothing to read (TX and RX no longer connected) */
+ if (poll(fds, 1, timeout) == 0) {
+ errx(1, "FAIL: timeout expected.");
+ }
+
+ warnx("PASS: Single wire disabled.");
+
+ close(fd);
+ exit(0);
+}
diff --git a/apps/px4/tests/tests.h b/apps/px4/tests/tests.h
index 46450d10b..cc3f5493a 100644
--- a/apps/px4/tests/tests.h
+++ b/apps/px4/tests/tests.h
@@ -93,6 +93,7 @@ extern int test_uart_send(int argc, char *argv[]);
extern int test_sleep(int argc, char *argv[]);
extern int test_time(int argc, char *argv[]);
extern int test_uart_console(int argc, char *argv[]);
+extern int test_hott_telemetry(int argc, char *argv[]);
extern int test_jig_voltages(int argc, char *argv[]);
extern int test_param(int argc, char *argv[]);
extern int test_bson(int argc, char *argv[]);
diff --git a/apps/px4/tests/tests_main.c b/apps/px4/tests/tests_main.c
index 5bedd257b..ad6828f20 100644
--- a/apps/px4/tests/tests_main.c
+++ b/apps/px4/tests/tests_main.c
@@ -100,6 +100,7 @@ const struct {
{"uart_baudchange", test_uart_baudchange, OPT_NOJIGTEST | OPT_NOALLTEST},
{"uart_send", test_uart_send, OPT_NOJIGTEST | OPT_NOALLTEST},
{"uart_console", test_uart_console, OPT_NOJIGTEST | OPT_NOALLTEST},
+ {"hott_telemetry", test_hott_telemetry, OPT_NOJIGTEST | OPT_NOALLTEST},
{"tone", test_tone, 0},
{"sleep", test_sleep, OPT_NOJIGTEST},
{"time", test_time, OPT_NOJIGTEST},
diff --git a/apps/sensors/sensors.cpp b/apps/sensors/sensors.cpp
index 2697cf3d9..d8d200ea9 100644
--- a/apps/sensors/sensors.cpp
+++ b/apps/sensors/sensors.cpp
@@ -67,6 +67,7 @@
#include <systemlib/perf_counter.h>
#include <systemlib/ppm_decode.h>
+#include <systemlib/airspeed.h>
#include <uORB/uORB.h>
#include <uORB/topics/sensor_combined.h>
@@ -75,6 +76,7 @@
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/battery_status.h>
+#include <uORB/topics/differential_pressure.h>
#define GYRO_HEALTH_COUNTER_LIMIT_ERROR 20 /* 40 ms downtime at 500 Hz update rate */
#define ACC_HEALTH_COUNTER_LIMIT_ERROR 20 /* 40 ms downtime at 500 Hz update rate */
@@ -88,9 +90,10 @@
#define BARO_HEALTH_COUNTER_LIMIT_OK 5
#define ADC_HEALTH_COUNTER_LIMIT_OK 5
-#define ADC_BATTERY_VOLTAGE_CHANNEL 10
+#define ADC_BATTERY_VOLTAGE_CHANNEL 10
+#define ADC_AIRSPEED_VOLTAGE_CHANNEL 11
-#define BAT_VOL_INITIAL 12.f
+#define BAT_VOL_INITIAL 0.f
#define BAT_VOL_LOWPASS_1 0.99f
#define BAT_VOL_LOWPASS_2 0.01f
#define VOLTAGE_BATTERY_IGNORE_THRESHOLD_VOLTS 3.5f
@@ -161,11 +164,14 @@ private:
orb_advert_t _manual_control_pub; /**< manual control signal topic */
orb_advert_t _rc_pub; /**< raw r/c control topic */
orb_advert_t _battery_pub; /**< battery status */
+ orb_advert_t _airspeed_pub; /**< airspeed */
perf_counter_t _loop_perf; /**< loop performance counter */
struct rc_channels_s _rc; /**< r/c channel data */
struct battery_status_s _battery_status; /**< battery status */
+ struct baro_report _barometer; /**< barometer data */
+ struct differential_pressure_s _differential_pressure;
struct {
float min[_rc_max_chan_count];
@@ -389,6 +395,7 @@ Sensors::Sensors() :
_manual_control_pub(-1),
_rc_pub(-1),
_battery_pub(-1),
+ _airspeed_pub(-1),
/* performance counters */
_loop_perf(perf_alloc(PC_ELAPSED, "sensor task update"))
@@ -861,13 +868,12 @@ Sensors::baro_poll(struct sensor_combined_s &raw)
orb_check(_baro_sub, &baro_updated);
if (baro_updated) {
- struct baro_report baro_report;
- orb_copy(ORB_ID(sensor_baro), _baro_sub, &baro_report);
+ orb_copy(ORB_ID(sensor_baro), _baro_sub, &_barometer);
- raw.baro_pres_mbar = baro_report.pressure; // Pressure in mbar
- raw.baro_alt_meter = baro_report.altitude; // Altitude in meters
- raw.baro_temp_celcius = baro_report.temperature; // Temperature in degrees celcius
+ raw.baro_pres_mbar = _barometer.pressure; // Pressure in mbar
+ raw.baro_alt_meter = _barometer.altitude; // Altitude in meters
+ raw.baro_temp_celcius = _barometer.temperature; // Temperature in degrees celcius
raw.baro_counter++;
}
@@ -988,29 +994,72 @@ Sensors::adc_poll(struct sensor_combined_s &raw)
for (unsigned i = 0; i < sizeof(buf_adc) / sizeof(buf_adc[0]); i++) {
- if (ret >= sizeof(buf_adc[0]) && ADC_BATTERY_VOLTAGE_CHANNEL == buf_adc[i].am_channel) {
- /* Voltage in volts */
- float voltage = (buf_adc[i].am_data * _parameters.battery_voltage_scaling);
+ if (ret >= (int)sizeof(buf_adc[0])) {
- if (voltage > VOLTAGE_BATTERY_IGNORE_THRESHOLD_VOLTS) {
+ if (ADC_BATTERY_VOLTAGE_CHANNEL == buf_adc[i].am_channel) {
+ /* Voltage in volts */
+ float voltage = (buf_adc[i].am_data * _parameters.battery_voltage_scaling);
- /* one-time initialization of low-pass value to avoid long init delays */
- if (_battery_status.voltage_v < 3.0f) {
- _battery_status.voltage_v = voltage;
- }
+ if (voltage > VOLTAGE_BATTERY_IGNORE_THRESHOLD_VOLTS) {
+
+ /* one-time initialization of low-pass value to avoid long init delays */
+ if (_battery_status.voltage_v < 3.0f) {
+ _battery_status.voltage_v = voltage;
+ }
+
+ _battery_status.timestamp = hrt_absolute_time();
+ _battery_status.voltage_v = (BAT_VOL_LOWPASS_1 * (_battery_status.voltage_v + BAT_VOL_LOWPASS_2 * voltage));;
+ /* current and discharge are unknown */
+ _battery_status.current_a = -1.0f;
+ _battery_status.discharged_mah = -1.0f;
+
+ /* announce the battery voltage if needed, just publish else */
+ if (_battery_pub > 0) {
+ orb_publish(ORB_ID(battery_status), _battery_pub, &_battery_status);
+
+ } else {
+ _battery_pub = orb_advertise(ORB_ID(battery_status), &_battery_status);
+ }
+ }
+
+ } else if (ADC_AIRSPEED_VOLTAGE_CHANNEL == buf_adc[i].am_channel) {
+
+ /* calculate airspeed, raw is the difference from */
+
+ float voltage = buf_adc[i].am_data / 4096.0f;
+
+ /**
+ * The voltage divider pulls the signal down, only act on
+ * a valid voltage from a connected sensor
+ */
+ if (voltage > 0.4f) {
+
+ float pres_raw = fabsf(voltage - (3.3f / 2.0f));
+ float pres_mbar = pres_raw * (3.3f / 5.0f) * 10.0f;
+
+ float airspeed_true = calc_true_airspeed(pres_mbar + _barometer.pressure,
+ _barometer.pressure, _barometer.temperature - 5.0f);
+ // XXX HACK - true temperature is much less than indicated temperature in baro,
+ // subtract 5 degrees in an attempt to account for the electrical upheating of the PCB
+
+ float airspeed_indicated = calc_indicated_airspeed(pres_mbar + _barometer.pressure,
+ _barometer.pressure, _barometer.temperature - 5.0f);
+ // XXX HACK
- _battery_status.timestamp = hrt_absolute_time();
- _battery_status.voltage_v = (BAT_VOL_LOWPASS_1 * (_battery_status.voltage_v + BAT_VOL_LOWPASS_2 * voltage));;
- /* current and discharge are unknown */
- _battery_status.current_a = -1.0f;
- _battery_status.discharged_mah = -1.0f;
+ _differential_pressure.timestamp = hrt_absolute_time();
+ _differential_pressure.static_pressure_mbar = _barometer.pressure;
+ _differential_pressure.differential_pressure_mbar = pres_mbar;
+ _differential_pressure.temperature_celcius = _barometer.temperature;
+ _differential_pressure.indicated_airspeed_m_s = airspeed_indicated;
+ _differential_pressure.true_airspeed_m_s = airspeed_true;
- /* announce the battery voltage if needed, just publish else */
- if (_battery_pub > 0) {
- orb_publish(ORB_ID(battery_status), _battery_pub, &_battery_status);
+ /* announce the airspeed if needed, just publish else */
+ if (_airspeed_pub > 0) {
+ orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &_differential_pressure);
- } else {
- _battery_pub = orb_advertise(ORB_ID(battery_status), &_battery_status);
+ } else {
+ _airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &_differential_pressure);
+ }
}
}
@@ -1114,7 +1163,7 @@ Sensors::ppm_poll()
}
/* reverse channel if required */
- if (i == _rc.function[THROTTLE]) {
+ if (i == (int)_rc.function[THROTTLE]) {
if ((int)_parameters.rev[i] == -1) {
_rc.chan[i].scaled = 1.0f + -1.0f * _rc.chan[i].scaled;
}
diff --git a/apps/system/Makefile b/apps/system/Makefile
index 9955a6b2c..057fbcf77 100644
--- a/apps/system/Makefile
+++ b/apps/system/Makefile
@@ -73,4 +73,4 @@ depend: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
diff --git a/apps/system/free/Makefile b/apps/system/free/Makefile
index dada00d99..58ca7956c 100644
--- a/apps/system/free/Makefile
+++ b/apps/system/free/Makefile
@@ -92,11 +92,14 @@ $(COBJS): %$(OBJEXT): %.c
# Register application
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
# Create dependencies
@@ -111,7 +114,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile
index 029d2b6fe..1ed7a2fae 100644
--- a/apps/system/i2c/Makefile
+++ b/apps/system/i2c/Makefile
@@ -68,7 +68,7 @@ STACKSIZE = 2048
# Build targets
all: .built
-.PHONY: .context context .depend depend clean distclean
+.PHONY: context .depend depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
@@ -80,11 +80,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
@@ -97,7 +100,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/install/Makefile b/apps/system/install/Makefile
index 6a02d859f..07d42887a 100644
--- a/apps/system/install/Makefile
+++ b/apps/system/install/Makefile
@@ -93,11 +93,14 @@ $(COBJS): %$(OBJEXT): %.c
# Register application
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
# Create dependencies
@@ -112,7 +115,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/readline/Makefile b/apps/system/readline/Makefile
index 3a48d324e..040fd2e28 100644
--- a/apps/system/readline/Makefile
+++ b/apps/system/readline/Makefile
@@ -100,7 +100,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/systemcmds/param/param.c b/apps/systemcmds/param/param.c
index 210841604..56f5317e3 100644
--- a/apps/systemcmds/param/param.c
+++ b/apps/systemcmds/param/param.c
@@ -61,6 +61,7 @@ static void do_load(const char* param_file_name);
static void do_import(const char* param_file_name);
static void do_show(const char* search_string);
static void do_show_print(void *arg, param_t param);
+static void do_set(const char* name, const char* val);
int
param_main(int argc, char *argv[])
@@ -100,15 +101,24 @@ param_main(int argc, char *argv[])
exit(0);
}
- if (!strcmp(argv[1], "show"))
+ if (!strcmp(argv[1], "show")) {
if (argc >= 3) {
do_show(argv[2]);
} else {
do_show(NULL);
}
+ }
+
+ if (!strcmp(argv[1], "set")) {
+ if (argc >= 4) {
+ do_set(argv[2], argv[3]);
+ } else {
+ errx(1, "not enough arguments.\nTry 'param set PARAM_NAME 3'");
+ }
+ }
}
- errx(1, "expected a command, try 'load', 'import', 'show', 'select' or 'save'");
+ errx(1, "expected a command, try 'load', 'import', 'show', 'set', 'select' or 'save'");
}
static void
@@ -185,9 +195,11 @@ do_show_print(void *arg, param_t param)
float f;
const char *search_string = (const char*)arg;
- /* print nothing if search string valid and not matching */
- if (arg != NULL && (strcmp(search_string, param_name(param) != 0)))
+ /* print nothing if search string is invalid and not matching */
+ if (!(arg == NULL || (!strcmp(search_string, param_name(param))))) {
+ /* param not found */
return;
+ }
printf("%c %s: ",
param_value_unsaved(param) ? '*' : (param_value_is_default(param) ? ' ' : '+'),
@@ -225,3 +237,61 @@ do_show_print(void *arg, param_t param)
printf("<error fetching parameter %d>\n", param);
}
+
+static void
+do_set(const char* name, const char* val)
+{
+ int32_t i;
+ float f;
+ param_t param = param_find(name);
+
+ /* set nothing if parameter cannot be found */
+ if (param == PARAM_INVALID) {
+ /* param not found */
+ errx(1, "Error: Parameter %s not found.", name);
+ }
+
+ printf("%c %s: ",
+ param_value_unsaved(param) ? '*' : (param_value_is_default(param) ? ' ' : '+'),
+ param_name(param));
+
+ /*
+ * Set parameter if type is known and conversion from string to value turns out fine
+ */
+
+ switch (param_type(param)) {
+ case PARAM_TYPE_INT32:
+ if (!param_get(param, &i)) {
+ printf("old: %d", i);
+
+ /* convert string */
+ char* end;
+ i = strtol(val,&end,10);
+ param_set(param, &i);
+ printf(" -> new: %d\n", i);
+
+ }
+
+ break;
+
+ case PARAM_TYPE_FLOAT:
+ if (!param_get(param, &f)) {
+ printf("float values are not yet supported.");
+ // printf("old: %4.4f", (double)f);
+
+ // /* convert string */
+ // char* end;
+ // f = strtof(val,&end);
+ // param_set(param, &f);
+ // printf(" -> new: %4.4f\n", f);
+
+ }
+
+ break;
+
+ default:
+ errx(1, "<unknown / unsupported type %d>\n", 0 + param_type(param));
+ }
+
+ exit(0);
+}
diff --git a/apps/systemcmds/perf/perf.c b/apps/systemcmds/perf/perf.c
index ced942fd6..64443d019 100644
--- a/apps/systemcmds/perf/perf.c
+++ b/apps/systemcmds/perf/perf.c
@@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <unistd.h>
#include <stdio.h>
+#include <string.h>
#include "systemlib/perf_counter.h"
@@ -63,6 +64,15 @@ __EXPORT int perf_main(int argc, char *argv[]);
int perf_main(int argc, char *argv[])
{
+ if (argc > 1) {
+ if (strcmp(argv[1], "reset") == 0) {
+ perf_reset_all();
+ return 0;
+ }
+ printf("Usage: perf <reset>\n");
+ return -1;
+ }
+
perf_print_all();
fflush(stdout);
return 0;
diff --git a/apps/systemlib/Makefile b/apps/systemlib/Makefile
index 942116faa..8240dbe43 100644
--- a/apps/systemlib/Makefile
+++ b/apps/systemlib/Makefile
@@ -43,7 +43,8 @@ CSRCS = err.c \
conversions.c \
cpuload.c \
getopt_long.c \
- up_cxxinitialize.c
+ up_cxxinitialize.c \
+ airspeed.c
# ppm_decode.c \
diff --git a/apps/systemlib/airspeed.c b/apps/systemlib/airspeed.c
index e213b66c2..5c68f8ea5 100644
--- a/apps/systemlib/airspeed.c
+++ b/apps/systemlib/airspeed.c
@@ -41,11 +41,13 @@
*/
#include "math.h"
+#include "conversions.h"
+#include "airspeed.h"
float calc_indicated_airspeed(float pressure_front, float pressure_ambient, float temperature)
{
- return sqrtf((2.0f*(pressure_front - pressure_ambient)) / air_density_sea_level);
+ return sqrtf((2.0f*(pressure_front - pressure_ambient)) / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
}
/**
@@ -60,7 +62,7 @@ float calc_indicated_airspeed(float pressure_front, float pressure_ambient, floa
*/
float calc_true_airspeed_from_indicated(float speed, float pressure_ambient, float temperature)
{
- return speed * sqrtf(air_density_sea_level / get_air_density(pressure_ambient, temperature));
+ return speed * sqrtf(CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C / get_air_density(pressure_ambient, temperature));
}
/**
@@ -76,4 +78,4 @@ float calc_true_airspeed_from_indicated(float speed, float pressure_ambient, flo
float calc_true_airspeed(float pressure_front, float pressure_ambient, float temperature)
{
return sqrtf((2.0f*(pressure_front - pressure_ambient)) / get_air_density(pressure_ambient, temperature));
-} \ No newline at end of file
+}
diff --git a/apps/systemlib/airspeed.h b/apps/systemlib/airspeed.h
index 62acfe2b0..b1beb79ae 100644
--- a/apps/systemlib/airspeed.h
+++ b/apps/systemlib/airspeed.h
@@ -33,13 +33,16 @@
****************************************************************************/
/**
- * @file airspeed.c
- * Airspeed estimation
+ * @file airspeed.h
+ * Airspeed estimation declarations
*
* @author Lorenz Meier <lm@inf.ethz.ch>
*
*/
+#ifndef AIRSPEED_H_
+#define AIRSPEED_H_
+
#include "math.h"
#include "conversions.h"
@@ -83,4 +86,6 @@ __EXPORT float calc_true_airspeed_from_indicated(float speed, float pressure_amb
*/
__EXPORT float calc_true_airspeed(float pressure_front, float pressure_ambient, float temperature);
-__END_DECLS \ No newline at end of file
+__END_DECLS
+
+#endif
diff --git a/apps/systemlib/conversions.c b/apps/systemlib/conversions.c
index fed97f101..2b8003e45 100644
--- a/apps/systemlib/conversions.c
+++ b/apps/systemlib/conversions.c
@@ -42,10 +42,6 @@
#include "conversions.h"
-#define air_gas_constant 8.31432f
-#define air_density_sea_level 1.225f
-#define absolute_null_kelvin 273.15f
-
int16_t
int16_t_from_bytes(uint8_t bytes[])
{
@@ -154,5 +150,5 @@ void quat2rot(const float Q[4], float R[9])
float get_air_density(float static_pressure, float temperature_celsius)
{
- return static_pressure / (air_gas_constant * (temperature_celsius + absolute_null_kelvin));
+ return static_pressure / (CONSTANTS_AIR_GAS_CONST * (temperature_celsius + CONSTANTS_ABSOLUTE_NULL_KELVIN));
}
diff --git a/apps/systemlib/conversions.h b/apps/systemlib/conversions.h
index 4db6de772..c2987709b 100644
--- a/apps/systemlib/conversions.h
+++ b/apps/systemlib/conversions.h
@@ -44,7 +44,10 @@
#include <float.h>
#include <stdint.h>
-#define CONSTANTS_ONE_G 9.80665f
+#define CONSTANTS_ONE_G 9.80665f
+#define CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C 1.225f
+#define CONSTANTS_AIR_GAS_CONST 8.31432f
+#define CONSTANTS_ABSOLUTE_NULL_KELVIN 273.15f
__BEGIN_DECLS
diff --git a/apps/systemlib/perf_counter.c b/apps/systemlib/perf_counter.c
index ff15ef479..879f4715a 100644
--- a/apps/systemlib/perf_counter.c
+++ b/apps/systemlib/perf_counter.c
@@ -219,6 +219,40 @@ perf_end(perf_counter_t handle)
}
void
+perf_reset(perf_counter_t handle)
+{
+ if (handle == NULL)
+ return;
+
+ switch (handle->type) {
+ case PC_COUNT:
+ ((struct perf_ctr_count *)handle)->event_count = 0;
+ break;
+
+ case PC_ELAPSED: {
+ struct perf_ctr_elapsed *pce = (struct perf_ctr_elapsed *)handle;
+ pce->event_count = 0;
+ pce->time_start = 0;
+ pce->time_total = 0;
+ pce->time_least = 0;
+ pce->time_most = 0;
+ break;
+ }
+
+ case PC_INTERVAL: {
+ struct perf_ctr_interval *pci = (struct perf_ctr_interval *)handle;
+ pci->event_count = 0;
+ pci->time_event = 0;
+ pci->time_first = 0;
+ pci->time_last = 0;
+ pci->time_least = 0;
+ pci->time_most = 0;
+ break;
+ }
+ }
+}
+
+void
perf_print_counter(perf_counter_t handle)
{
if (handle == NULL)
@@ -270,3 +304,14 @@ perf_print_all(void)
handle = (perf_counter_t)sq_next(&handle->link);
}
}
+
+void
+perf_reset_all(void)
+{
+ perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters);
+
+ while (handle != NULL) {
+ perf_reset(handle);
+ handle = (perf_counter_t)sq_next(&handle->link);
+ }
+}
diff --git a/apps/systemlib/perf_counter.h b/apps/systemlib/perf_counter.h
index 6e6c80d5b..5c2cb15b2 100644
--- a/apps/systemlib/perf_counter.h
+++ b/apps/systemlib/perf_counter.h
@@ -97,6 +97,14 @@ __EXPORT extern void perf_begin(perf_counter_t handle);
*/
__EXPORT extern void perf_end(perf_counter_t handle);
+/**
+ * Reset a performance event.
+ *
+ * This call resets performance counter to initial state
+ *
+ * @param handle The handle returned from perf_alloc.
+ */
+__EXPORT extern void perf_reset(perf_counter_t handle);
/**
* Print one performance counter.
@@ -110,6 +118,11 @@ __EXPORT extern void perf_print_counter(perf_counter_t handle);
*/
__EXPORT extern void perf_print_all(void);
+/**
+ * Reset all of the performance counters.
+ */
+__EXPORT extern void perf_reset_all(void);
+
__END_DECLS
#endif
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index ed1cf39dc..99f6d4a52 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -1452,7 +1452,7 @@
complex: 'uname -o 2>/dev/null || echo "Other"'
* drivers/usbhost/usbhost_enumerate.c: Add logic to get the VID and PID. This
is necessary in order to support vendor-specific USB devices.
- * examplex/wlan, configs/olimex-lpc1766stk/wlan, drivers/usbhost/usbhost_rtl8187.c,
+ * examples/wlan, configs/olimex-lpc1766stk/wlan, drivers/usbhost/usbhost_rtl8187.c,
Add infrastructure to support RTL18187 wireless USB.
* configs/nucleus2g: backed out USB host changes... wrong board.
* Renamed arc/hc/include/mc9s12ne64 and src/mc9s12ne64 to m9s12. That name is
@@ -1920,7 +1920,7 @@
CONFIG_FAT_LCNAMES is not selected, all filenames are strictly upper
case.
* configs/stm3210e-eval/nsh2: Console is back on UART1; Added
- examplex/nx as an NSH "built-in" command as a demonstration.
+ examples/nx as an NSH "built-in" command as a demonstration.
* fs/fat/fs_fat32dirent.c: Fix an important bug in the directory
allocation (fat_allocatedirentry()). I looks like it could be
initializing the wrong sectors! NOTE: This function was in
@@ -3801,3 +3801,221 @@
to find executables using a relative path.
6.25 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * graphics/: Adds 5x8 monospace font. This tiny font is useful for graph
+ labels and for small bitmapped display. Contributed by Petteri
+ Aimonen.
+ * configs/stm3220g-eval/nxwm: Converted to use the kconfig-frontends
+ configuration tool.
+ * configs/sim/nxwm: Converted to use the kconfig-frontends configuration
+ tool.
+ * include/pthread.h: In sys/prctl.h because it is needed by
+ pthread_[set|get]name_np()
+ * tools/kconfig.bat: Kludge to run kconfig-frontends from a DOS shell.
+ * sched/sig_timedwait.c: Should always move the time up to the next
+ largest number of system ticks. The logic was rounding. Noted by
+ Petteri Aimonen.
+ * arch/arm/src/up_head.S: Fix backward conditional compilation. NOTE
+ there is a issue of ARM9 systems with low vectors and large memories
+ that will have to be addressed in the future.
+ * libc/misc/lib_kbdencode.c and lib_kbddecode.c: Add logic to marshal
+ and serialized "out-of-band" keyboard commands intermixed with normal
+ ASCII data (not yet hooked into anything).
+ * drivers/usbhost/usbhost_hidkbd.c: If CONFIG_HIDKBD_ENCODED is
+ defined, this driver will now use libc/misc/lib_kbdencode.c to
+ encode special function keys.
+ * configs/olimex-lpc1766stk/hidkbd: This configuration has been
+ converted to use the kconfig-frontends configuration tool.
+ * drivers/lcd/ug-2864hsweg01.c and include/nuttx/lcd/ug-2864hsweg01.h:
+ Driver for UG-2864HSWEG01 OLED contributed by Darcy Gong.
+ * configs/stm32f4discovery/src/up_ug2864hsweg01.c: Support for the
+ UG-2864HSWEG01 OLED for the STM32F4Discovery board.
+ * drivers/usbhost/usbhost_hidkbd.c: Correct a logic error in how
+ tasks waiting for read data are awakened.
+ * libc/misc/lib_kbdencode.c and lib_kbddecode.c: Now handles keypress
+ events too. However, the USB HID keyboard drier has not yet been
+ updated to detect key release events. That is kind of tricky in
+ the USB HID keyboard report data.
+ * configs/mcu123-214x/nsh: Converted to use the kconfig-frontends
+ configuration tool.
+ * configs/zp214xpa: Add basic support for the The0.net ZP213x/4xPA
+ board (with the LPC2148 and the UG_2864AMBAG01).
+ * configs/sim/nxlines: Add an nxlines configuration for the
+ simulator.
+ * configs/zp214xpa/nxlines: Add an nxlines configuration for the
+ ZP213x/4xPA (with the LPC2148 and the UG_2864AMBAG01). Working
+ as of 2012-12-30.
+ * configs/olimex-lpc1766stk/wlan: Remove non-functional
+ configuration.
+ * configs/stm32f4discovery/src and nuttx/drivers/lcd/ug-2864hsweg01.c:
+ Updates and correctinos for the UG-2864HSWEG01 from Darcy Gong.
+ * configs/lm326965-ek: All configurations converted to use the
+ kconfig-frontends configuration tool.
+ * configs/Kconfig: NSH_MMCSDSPIPORTNO should depend on MMCSD_SPI,
+ not just SPI (from Jose Pablo Carballo).
+ * arch/arm/src/arm/Kconfig and armv7m/Kconfig: Add an option for
+ buildroot toolchains: They may be EABI or OABI.
+ * include/nuttx/progmem and arch/arm/src/stm32/stm32_flash.c:
+ Fix a counting bug plus change interface to use either relative
+ or absolut FLASH addressing (from Freddie Chopin).
+ * libc/misc/Make.defs: Fix error in conditional for KBD CODEC.
+ * libc/Kconfig and configs/*/defconfig (several): The default
+ setting should be CONFIG_LIB_KBDCODEC=n
+ * tools/configure.c: configure.c can be used to build a work-alike
+ program as a replacement for configure.sh. This work-alike
+ program would be used in environments that do not support Bash
+ scripting (such as the Windows native environment).
+ * tools/configure.bat: configure.bat is a small Windows batch
+ file that can be used as a replacement for configure.sh in a
+ Windows native environment. configure.bat is actually just a
+ thin layer that execuates configure.exe if it is available. If
+ configure.exe is not available, then configure.bat will attempt
+ to build it first.
+ * arch/arm/src/lpc17xx/lpc17_syscon.h: Correct some typos in bit
+ definitions (from Rommel Marcelo).
+ * libc/string/lib_strndup.c: strndup() should use strnlen(), not
+ strlen(), to determine the size of the string.
+ * sched/os_bringup.c: Remove support for CONFIG_BUILTIN_APP_START.
+ This is not really a useful feature and creates a violation of the
+ OS layered architecture.
+ * include/unistd.h, arch/arch/src/*: Implement a simple vfork().
+ On initial checkin, this API is available only for ARM platforms.
+ * binfmt/binfmt_exec.c: exec() now sets the priority of the new task
+ to the same priority as the current task (instead of the arbirtrary
+ value of 50).
+ * libc/unisted/lib_execv.c and lib_execl.c: New, somewhat flawed,
+ implementations of execv() and execl().
+ * tools/cfgdefine.c: Strips quotes from CONFIG_EXECFUNCS_SYMTAB
+ value.
+ * arch/arm/include/lm3s/chip.h: Move chip definitions into
+ public include area for compatibility with other architectures.
+ * arch/arm/src/lm3s/chip: Move register definition header files
+ into a new chip/ sub-directory.
+ * arch/arm/src/lm3s/lm3s_internal.h: Broke up into several
+ smaller header files.
+ * arch/arm/src/lm: Rename the arch/arm/src/lm3s directory to
+ arch/arm/src/lm so that is can support other members of the
+ Stellaris family.
+ * libc/spawn: Add file action interfaces needed by posix_spawn().
+ * sched/clock_time2ticks.c: Another case where time was being
+ rounded down instead of up (from Mike Smith).
+ * libc/spawn: Implementation of posix_spawn() is complete but
+ untested and undocumented.
+ * drivers/usbdev/pl2303.c: Fix typols in the PL2303 driver
+ (from Max Holtzberg).
+ * configs/stm32f4discovery/posix_spawn: Added a configuration
+ that can be used for testing posix_spawn().
+ * arch/arm/src/stm32: Bring F1 support for general DMA and serial
+ DMA in paricular up to parity with F2/F4 (from Mike Smith).
+ * libc/stdio/lib_libfread.c: Correct some error handling when
+ lib_fread() was passed a bad stream. Needed to move the
+ releasing of a semaphore inside of some conditional logic
+ (cosmetic).
+ * include/nuttx/sched.h, sched/task_setup.c, and sched/task_exithook.c:
+ Add support for remembering the parent task and sending
+ SIGCHLD to the parent when the task exists.
+ * sched/task_exithook.c: Fixed a *critical* bug. Here is
+ the scenario: (1) sched_lock() is called increments the lockcount
+ on the current TCB (i.e., the one at the head of the ready to run
+ list), (2) sched_mergepending is called which may change the task
+ at the head of the readytorun list, then (2) sched_unlock() is called
+ which decrements the lockcount on the wrong TCB. The failure case
+ that I saw was that pre-emption got disabled in the IDLE thread,
+ locking up the whole system.
+ * sched/sched_waitpid.c: Use SIGCHLD instead of a semaphore. This
+ is a much more spec-compliant implemenation. However, there are
+ some issues with overruning signals because NuttX does not support
+ queueing of signals (POSIX does not require it). I think it may
+ need to.
+ * sched/sched_waitid.c and sched_wait.c: Add support for waitid()
+ and wait(). See issues with waitpid() above.
+ * include/nuttx/fs/fs.h and fs/fs_files.c: Add a dup() method to
+ the struct mountpt_operations. When dup'ing a file that resides
+ on a mounted volume, let the file system's dup() method do the
+ work.
+ * fs/romfs/fs_romfs.c: Implemented the dup() method for the ROMFS
+ file system.
+ * fs/fat/fs_fat32.c, fs/nxffs/nxffs_initialize, and
+ fs/nfs/nfs_vfsops.c: Add hooks for dup() method (not yet
+ implemented).
+ * fs/romfs: Remove the rf_open flag. It looks good, but actually
+ does nothing.
+ * fs/fat: Remove the ff_open flag. Same story as for the ROMFS
+ rf_open flag.
+ * fs/fat/fs_fat32.c, fs/nxffs/nxffs_initialize, and
+ fs/nfs/nfs_vfsops.c: Completed implementation of the dup() methods.
+ There is still no good test available.
+ * sched/sig_timedwait.c: sigtimedwait() would return a bad signal
+ number if the signal was already pending when the function was
+ called.
+ * configs/ubw32/scripts: All common linker scripts moved to this
+ scripts sub-directory
+ * configs/ubw32/ostest: Configuration configured to use the
+ kconfig-frontends tools.
+ * arch/mips/src/mips32/up_vfork.c, up_vfork.h, and vfork.S:
+ Implement vfork() for MIPS32 (no floating point support)
+ * configs/ubw32/ostest: Enable the vfork() test.
+ * fs/binfs: Move apps/builtin/binfs.c to fs/binfs/fs_binfs.c
+ CONFIG_APPS_BINDIR rename CONFIG_FS_BINFS
+ * include/nuttx/binfmt/builtin.h: Some of the content of
+ apps/include/apps.h moved to include/nuttx/binfmt/builtin.h
+ * binfmt/libbuiltin/libbuiltin_utils.c: Move utility builtin
+ utility functions from apps/builtin/exec_builtins.c to
+ binfmt/libbuiltin/libbuiltin_utils.c
+ * binfmt/builtin.c and binfmt/libbuiltin: Add a binary "loader"
+ that can be used to execute builtin programs from the BINFS
+ file system.
+ * configs/sim/nsh: Convert to use kconfig-frontends configuration
+ tool.
+ * binfmt/binfmt_schedunload.c: Add logic based on SIGCHLD to
+ automatically unload and clean-up after running a task that
+ was loaded into memory.
+ * binfmt/libbuiltin: Extensions from Mike Smith
+ * sched/task_reparent.c: Add internal interface to change the
+ parent task.
+ * sched/task_posixspawn(): Move libc/spawn/lib_ps.c to
+ sched/task_posixspawn() now it requires internal, reparenting
+ interfaces
+ * include/nuttx/spawn(): Move libc/spawn.h to include/nuttx/spawn.h
+ * arch/arm/include/lpc17xx/chip.h, irq178x.h: Integrate Marcelo
+ Rommel's LPC1788 definitions into the base LPC17xx.
+ * configs/olimex-lpc1766stk/nsh: Convert configuration to use
+ the kconfig-frontends tools.
+ * sched/task_reparent.c: Simplify reparenting interface.
+ * arch/arm/src/[many]: More LPC1788 definitions from Rommel
+ Marcelo incorporated.
+ * configs/open1788: Board configuration for the Wave Share
+ Open1788 board. Still fragmentary (contribnuted by Rommel
+ Marcelo, adapted to use kconfig-frontends.
+ * net/send(): Add logic to work around delayed ACKs by splitting
+ packets (contributed by Yan T.).
+ * net/recvfrom(): Fix a bug. When the host closes a connection
+ (gracefully). recv[from]() returned success and the closure
+ was never detected. Hmmm.. I don't know why the network monitor
+ did not catch this event. This is an important bug fix.
+ * net/recvfrom(): Fix a introduced with the last bugfix. If
+ the peer does an orderly closure of the socket, report 0 not
+ -ENOTCONN
+ * configs/lm3s6965-ek/README.txt and tools/: Add an OpenOCD
+ configuration for the LM3S (from Jose Pablo Carballo).
+ * nuttx/lcd/hd4478ou.h and configs/pcblogic-pic32mx/src/up_lcd1602:
+ Start of support of LCD1602 alphanumeric LCD. I need a few
+ more parts before I can finish integrating this one.
+ * arch/arm/src/*/chip.h and arch/arm/include/*/chip.h: Move all
+ priority ranges from the src to the include chip.h header file.
+ * arch/arm/include/armv7-m/irq.h: Add inline functions to enable
+ and disable interrupts via the BASEPRI register.
+ * arch/arm/Kconfig: Add new option CONFIG_ARM7VM_USEBASEI
+ * arch/arm/src/*/*_irq.c: Set the priority of the SVCALL exception
+ to the highest possible value.
+ * arch/armv7-m/up_hardfault.c: Fail if a hardfault occurs
+ while CONFIG_ARM7VM_USEBASEPRI=y.
+ * arch/arm/src/stm32/stm32_serial.c: Add support for USART
+ single wire more (Contributed by the PX4 team).
+ * sched/: Implement support for retaining child task status after
+ the child task exists. This is behavior required by POSIX.
+ But in NuttX is only enabled with CONFIG_SCHED_HAVE_PARENT and
+ CONFIG_SCHED_CHILD_STATUS
+ * Add support for keyboard encode to the keypad test (from
+ Denis Carikli).
+
diff --git a/nuttx/Makefile.unix b/nuttx/Makefile.unix
index d66c06bd8..47debcccf 100644
--- a/nuttx/Makefile.unix
+++ b/nuttx/Makefile.unix
@@ -642,13 +642,13 @@ pass2dep: context tools/mkdeps$(HOSTEXEEXT)
# misc/tools/README.txt for additional information.
config:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf Kconfig
oldconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf --oldconfig Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfig
menuconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} mconf Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfig
# export
#
diff --git a/nuttx/Makefile.win b/nuttx/Makefile.win
index 34da12ad0..5c4404f57 100644
--- a/nuttx/Makefile.win
+++ b/nuttx/Makefile.win
@@ -252,7 +252,7 @@ LINKLIBS = $(patsubst lib\\%,%,$(NUTTXLIBS))
BIN = nuttx$(EXEEXT)
all: $(BIN)
-.PHONY: context clean_context check_context export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
+.PHONY: context clean_context check_context configenv config oldconfig menuconfig export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
# Target used to copy include\nuttx\math.h. If CONFIG_ARCH_MATH_H is
# defined, then there is an architecture specific math.h header file
@@ -452,7 +452,7 @@ clean_context:
# check_context
#
# This target checks if NuttX has been configured. NuttX is configured using
-# the script tools\configure.sh. That script will install certain files in
+# the script tools\configure.bat. That script will install certain files in
# the top-level NuttX build directory. This target verifies that those
# configuration files have been installed and that NuttX is ready to be built.
@@ -647,14 +647,17 @@ pass2dep: context tools\mkdeps$(HOSTEXEEXT)
# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See
# misc\tools\README.txt for additional information.
-config:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf Kconfig
+configenv:
+ $(Q) set APPSDIR=${CONFIG_APPS_DIR}
-oldconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf --oldconfig Kconfig
+config: configenv
+ $(Q) kconfig-conf Kconfig
-menuconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} mconf Kconfig
+oldconfig: configenv
+ $(Q) kconfig-conf --oldconfig Kconfig
+
+menuconfig: configenv
+ $(Q) kconfig-mconf Kconfig
# export
#
diff --git a/nuttx/README.txt b/nuttx/README.txt
index b9210277e..2ff473fa0 100644
--- a/nuttx/README.txt
+++ b/nuttx/README.txt
@@ -10,6 +10,9 @@ README
o Configuring NuttX
- Instantiating "Canned" Configurations
- NuttX Configuration Tool
+ - Incompatibilities with Older Configurations
+ - Converting Older Configurations to use the Configuration Tool
+ - NuttX Configuration Tool under DOS
o Toolchains
- Cross-Development Toolchains
- NuttX Buildroot Toolchain
@@ -38,6 +41,10 @@ Installing Cygwin
tiny setup.exe program and it does the real, internet installation
for you.
+ NOTE: NuttX can also be installed and built on a native Windows
+ system, but with some loss of tool functionality (see the
+ discussion "Native Windows Build" below).
+
Some Cygwin installation tips:
1. Install at C:\cygwin
@@ -58,8 +65,9 @@ Installing Cygwin
After installing Cygwin, you will get lots of links for installed
tools and shells. I use the RXVT native shell. It is fast and reliable
and does not require you to run the Cygwin X server (which is neither
- fast nor reliable). The rest of these instructions assume that you
- are at a bash command line prompt in either Linux or in Cygwin shell.
+ fast nor reliable). Unless otherwise noted, the rest of these
+ instructions assume that you are at a bash command line prompt in
+ either Linux or in Cygwin shell.
Download and Unpack
-------------------
@@ -235,8 +243,8 @@ additional file to the directory the NuttX application package (APPSDIR)):
The appconfig file describes the applications that need to be
built in the appliction directory (APPSDIR). Not all configurations
have an appconfig file. This file is deprecated and will not be
- used with new defconfig files produced with the mconf configuration
- tool.
+ used with new defconfig files produced with the kconfig-mconf
+ configuration tool.
General information about configuring NuttX can be found in:
@@ -249,6 +257,13 @@ easier. It is used as follows:
cd ${TOPDIR}/tools
./configure.sh <board-name>/<config-dir>
+There is an alternative Windows batch file that can be used in the
+windows native enironment like:
+
+ cd ${TOPDIR}\tools
+ configure.bat <board-name>\<config-dir>
+
+See tools/README.txt for more information about these scripts.
NuttX Configuration Tool
------------------------
@@ -292,6 +307,162 @@ NuttX Configuration Tool
install 'mconf', make certain that your PATH variable includes
a path to that installation directory.
+ The basic configuration order is "bottom-up":
+
+ - Select the build environment,
+ - Select the processor,
+ - Select the board,
+ - Select the supported peripherals
+ - Configure the device drivers,
+ - Configure the application options on top of this.
+
+ This is pretty straight forward for creating new configurations
+ but may be less intuitive for modifying existing configurations.
+
+Incompatibilities with Older Configurations
+-------------------------------------------
+
+ ***** WARNING *****
+
+ The old legacy, manual configurations and the new kconfig-frontends
+ configurations are not 100% compatible. Old legacy configurations
+ can *not* be used with the kconfig-frontends tool: If you run
+ 'make menuconfig' with a legacy configuration the resulting
+ configuration will probably not be functional.
+
+ Q: How can I tell if a configuration is a new kconfig-frontends
+ configuration or an older, manual configuration?
+
+ A: a) New kcondfig-frontends configurations will have this setting
+ within the defconfig/.config file":
+
+ CONFIG_NUTTX_NEWCONFIG=y
+
+ b) Only old, manual configurations will have an appconfig file
+
+Converting Older Configurations to use the Configuration Tool
+-------------------------------------------------------------
+
+ Q: How can I convert a older, manual configuration into a new,
+ kconfig-frontends toolchain.
+
+ A: 1) Look at the appconfig file: Each application path there
+ will now have to have an enabling setting. For example,
+ if the old appconfig file had:
+
+ CONFIGURED_APPS = examples/ostest
+
+ Then the new configuration will need:
+
+ CONFIG_EXAMPLES_OSTEST=y
+
+ The appconfig file can then be deleted because it will not
+ be needed after the conversion.
+
+ 2) Build the cmpconfig utility at tools:
+
+ cd tools
+ make -f Makefile.host cmpconfig
+
+ 3) Perform these steps repeatedly until you are convinced that
+ the configurations are the same:
+
+ a) Repeat the following until you have account for all of the differences:
+
+ cp configs/<board>/<condfiguration>/defconfig .config
+ make menuconfig (Just exit and save the new .config file)
+ tools/cmpconfig configs/<board>/<condfiguration>/defconfig .config | grep file1
+
+ The final grep will show settings in the old defconfig file that
+ do not appear in the new .config file (or have a different value
+ in the new .config file). In the new configuration, you will
+ probably have to enable certain groups of features. Such
+ hierarachical enabling options were not part of the older
+ configuration.
+
+ b) Then make sure these all make sense:
+
+ tools/cmpconfig configs/<board>/<condfiguration>/defconfig .config | grep file2
+
+ The final grep will show settings in the new .config file that
+ do not appear in the older defconfig file (or have a different value
+ in the new .config file). Here you should see only the new
+ hierarachical enabling options (such as CONFIG_SPI or CONFIG_MMCSD)
+ plus some other internal configuration settings (like CONFIG_ARCH_HAVE_UART0).
+ You will have to convince yourself that these new settings all make sense.
+
+ 4) Finally, update the configuration:
+
+ cp .config configs/<board>/<condfiguration>/defconfig
+ rm configs/<board>/<condfiguration>/appconfig
+
+ NOTE: You should comment out the line containing the CONFIG_APPS_DIR
+ in the new defconfig file. Why? Because the application directory
+ may reside at a different location when the configuration is installed
+ at some later time.
+
+ # CONFIG_APPS_DIR="../apps"
+
+ 5) The updated configuration can then be instantiated in the normal
+ fashion:
+
+ cd tools
+ ./configure.sh <board>/<condfiguration>
+
+ (or configure.bat for the case of the Windows native build).
+
+ NOTE: If CONFIG_APPS_DIR is not defined in the defconfig file,
+ the configure.sh script will find and add the new, correct path to
+ the application directory (CONFIG_APPS_DIR) when it copies the
+ defconfig file to the .config file. This is the setting that was
+ commented out in step 4.
+
+NuttX Configuration Tool under DOS
+----------------------------------
+
+ Recent versions of NuttX support building NuttX from a native Windows
+ console window (see "Native Windows Build" below). But kconfig-frontends
+ is a Linux tool. There have been some successes building a Windows
+ native version of the kconfig-frontends tool, but that is not ready
+ for prime time.
+
+ At this point, there are only a few options for the Windows user:
+
+ 1. You can run the configuration tool using Cygwin. However, the
+ Cygwin Makefile.win will complain so to do this will, you have
+ to manually edit the .config file:
+
+ a. Delete the line: CONFIG_WINDOWS_NATIVE=y
+ b. Change the apps/ directory path, CONFIG_APPS_DIR to use Unix
+ style delimiters. For example, change "..\apps" to "../apps"
+
+ And of course, after you use the configuration tool you need to
+ restore CONFIG_WINDOWS_NATIVE=y and the correct CONFIG_APPS_DIR.
+
+ 2) You can, with some effort, run the the Cygwin kconfig-mconf tool
+ directly in the Windows console window. In this case, you do not
+ have to modify the .config file, but there are other complexities:
+
+ a. You need to temporarily set the Cgywin directories in the PATH
+ variable then run kconfig-mconf manually like:
+
+ kconfig-mconf Kconfig
+
+ There is a Windows bacht file at tools/kconfig.bat that automates
+ these steps:
+
+ tools/kconfig menuconfig
+
+ b. There is an issue with accessing DOS environment variables from
+ the Cygwin kconfig-mconf running in the Windows console. The
+ following change to the top-level Kconfig file seems to work
+ around these problems:
+
+ config APPSDIR
+ string
+ - option env="APPSDIR"
+ + default "../apps"
+
TOOLCHAINS
^^^^^^^^^^
@@ -509,82 +680,93 @@ Native Windows Build
- A few extensions from GNUWin32
In this build, you cannot use a Cygwin or MSYS shell. Rather the build must
- be performed in a Windows CMD shell. Here is a better shell than than the
- standard issue, CMD shell: ConEmu which can be downloaded from:
+ be performed in a Windows console window. Here is a better terminal than the
+ standard issue, CMD.exe terminal: ConEmu which can be downloaded from:
http://code.google.com/p/conemu-maximus5/
Build Tools. The build still relies on some Unix-like commands. I use
the GNUWin32 tools that can be downloaded from http://gnuwin32.sourceforge.net/.
- Host Compiler: I use the MingGW compiler which can be downloaded from
+ Host Compiler: I use the MingGW GCC compiler which can be downloaded from
http://www.mingw.org/. If you are using GNUWin32, then it is recommended
the you not install the optional MSYS components as there may be conflicts.
+ This capability should still be considered a work in progress because:
+
+ (1) It has not been verfied on all targets and tools, and
+ (2) it still lacks some of the creature-comforts of the more mature environments
+ (like 'make menuconfig' support. See the section "NuttX Configuration Tool
+ under DOS" above).
+
+ There is an alternative to the setenv.sh script available for the Windows
+ native environment: tools/configure.bat. See tools/README.txt for additional
+ information.
+
Installing GNUWin32
-------------------
-The Windows native build will depend upon a few Unix-like tools that can be
-provided either by MSYS or GNUWin32. The GNUWin32 are available from
-http://gnuwin32.sourceforge.net/. GNUWin32 provides ports of tools with a
-GPL or similar open source license to modern MS-Windows (Microsoft Windows
-2000 / XP / 2003 / Vista / 2008 / 7). See
-http://gnuwin32.sourceforge.net/packages.html for a list of all of the tools
-available in the GNUWin32 package.
+ The Windows native build will depend upon a few Unix-like tools that can be
+ provided either by MSYS or GNUWin32. The GNUWin32 are available from
+ http://gnuwin32.sourceforge.net/. GNUWin32 provides ports of tools with a
+ GPL or similar open source license to modern MS-Windows (Microsoft Windows
+ 2000 / XP / 2003 / Vista / 2008 / 7). See
+ http://gnuwin32.sourceforge.net/packages.html for a list of all of the tools
+ available in the GNUWin32 package.
-The SourceForge project is located here:
-http://sourceforge.net/projects/gnuwin32/. The project is still being
-actively supported (although some of the Windows ports have gotten very old).
+ The SourceForge project is located here:
+ http://sourceforge.net/projects/gnuwin32/. The project is still being
+ actively supported (although some of the Windows ports have gotten very old).
-Some commercial toolchains include a subset of the GNUWin32 tools in the
-installation. My recommendation is that you download the GNUWin32 tools
-directly from the sourceforge.net website so that you will know what you are
-using and can reproduce your build environment.
+ Some commercial toolchains include a subset of the GNUWin32 tools in the
+ installation. My recommendation is that you download the GNUWin32 tools
+ directly from the sourceforge.net website so that you will know what you are
+ using and can reproduce your build environment.
-GNUWin32 Installation Steps:
+ GNUWin32 Installation Steps:
-The following steps will download and execute the GNUWin32 installer.
+ The following steps will download and execute the GNUWin32 installer.
-1. Download GetGNUWin32-x.x.x.exe from
- http://sourceforge.net/projects/getgnuwin32/files/. This is the
- installer. The current version as of this writing is 0.6.3.
+ 1. Download GetGNUWin32-x.x.x.exe from
+ http://sourceforge.net/projects/getgnuwin32/files/. This is the
+ installer. The current version as of this writing is 0.6.3.
-2. Run the installer.
+ 2. Run the installer.
-3. Accept the license.
+ 3. Accept the license.
-4. Select the installation directory. My recommendation is the
- directory that contains this README file (<this-directory>).
+ 4. Select the installation directory. My recommendation is the
+ directory that contains this README file (<this-directory>).
-5. After running GetGNUWin32-0.x.x.exe, you will have a new directory
- <this-directory>/GetGNUWin32
+ 5. After running GetGNUWin32-0.x.x.exe, you will have a new directory
+ <this-directory>/GetGNUWin32
-Note the the GNUWin32 installer didn't install GNUWin32. Instead, it
-installed another, smarter downloader. That downloader is the GNUWin32
-package management tool developed by the Open SSL project.
+ Note the the GNUWin32 installer didn't install GNUWin32. Instead, it
+ installed another, smarter downloader. That downloader is the GNUWin32
+ package management tool developed by the Open SSL project.
-The following steps probably should be performed from inside a DOS shell.
+ The following steps probably should be performed from inside a DOS shell.
-6. Change to the directory created by GetGNUWin32-x.x.x.exe
+ 6. Change to the directory created by GetGNUWin32-x.x.x.exe
- cd GetGNUWin32
+ cd GetGNUWin32
-7. Execute the download.bat script. The download.bat script will download
- about 446 packages! Enough to have a very complete Linux-like environment
- under the DOS shell. This will take awhile. This step only downloads
- the packages and the next step will install the packages.
+ 7. Execute the download.bat script. The download.bat script will download
+ about 446 packages! Enough to have a very complete Linux-like environment
+ under the DOS shell. This will take awhile. This step only downloads
+ the packages and the next step will install the packages.
- download
+ download
-8. This step will install the downloaded packages. The argument of the
- install.bat script is the installation location. C:\gnuwin32 is the
- standard install location:
+ 8. This step will install the downloaded packages. The argument of the
+ install.bat script is the installation location. C:\gnuwin32 is the
+ standard install location:
- install C:\gnuwin32
+ install C:\gnuwin32
-NOTE: This installation step will install *all* GNUWin32 packages... far
-more than you will ever need. If disc space is a problem for you, you might
-need to perform a manual installation of the individual ZIP files that you
-will find in the <this directory>/GetGNUWin32/packages directory.
+ NOTE: This installation step will install *all* GNUWin32 packages... far
+ more than you will ever need. If disc space is a problem for you, you might
+ need to perform a manual installation of the individual ZIP files that you
+ will find in the <this directory>/GetGNUWin32/packages directory.
CYGWIN BUILD PROBLEMS
^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/TODO b/nuttx/TODO
index 6c28bfd43..c302760ab 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated November 25, 2012)
+NuttX TODO List (Last updated January 23, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -6,23 +6,22 @@ standards, things that could be improved, and ideas for enhancements.
nuttx/
- (6) Task/Scheduler (sched/)
- (1) On-demand paging (sched/)
+ (11) Task/Scheduler (sched/)
(1) Memory Managment (mm/)
- (2) Signals (sched/, arch/)
+ (3) Signals (sched/, arch/)
(2) pthreads (sched/)
(2) C++ Support
(6) Binary loaders (binfmt/)
(17) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
- (11) Libraries (libc/, )
+ (12) Libraries (libc/, )
(9) File system/Generic drivers (fs/, drivers/)
(5) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Documentation (Documentation/)
- (8) Build system / Toolchains
+ (7) Build system / Toolchains
(5) Linux/Cywgin simulation (arch/sim)
- (6) ARM (arch/arm/)
+ (5) ARM (arch/arm/)
(1) ARM/C5471 (arch/arm/src/c5471/)
(3) ARM/DM320 (arch/arm/src/dm320/)
(2) ARM/i.MX (arch/arm/src/imx/)
@@ -31,22 +30,22 @@ nuttx/
(2) ARM/LPC313x (arch/arm/src/lpc313x/)
(0) ARM/LPC43x (arch/arm/src/lpc43xx/)
(3) ARM/STR71x (arch/arm/src/str71x/)
- (3) ARM/LM3S6918 (arch/arm/src/lm3s/)
- (4) ARM/STM32 (arch/arm/src/stm32/)
+ (3) ARM/LM3S6918 (arch/arm/src/lm/)
+ (5) ARM/STM32 (arch/arm/src/stm32/)
(3) AVR (arch/avr)
(0) Intel x86 (arch/x86)
(5) 8051 / MCS51 (arch/8051/)
(3) MIPS/PIC32 (arch/mips)
(1) Hitachi/Renesas SH-1 (arch/sh/src/sh1)
(4) Renesas M16C/26 (arch/sh/src/m16c)
- (10) z80/z8/ez80 (arch/z80/)
+ (11) z80/z8/ez80/z180 (arch/z80/)
(9) z16 (arch/z16/)
(1) mc68hc1x (arch/hc)
apps/
(5) Network Utilities (apps/netutils/)
- (4) NuttShell (NSH) (apps/nshlib)
+ (5) NuttShell (NSH) (apps/nshlib)
(1) System libraries apps/system (apps/system)
(5) Other Applications & Tests (apps/examples/)
@@ -56,33 +55,9 @@ o Task/Scheduler (sched/)
Title: CHILD PTHREAD TERMINATION
Description: When a tasks exits, shouldn't all of its child pthreads also be
terminated?
- Status: Open
+ Status: Closed. No, this behavior will not be implemented.
Priority: Medium, required for good emulation of process/pthread model.
- Title: MMAN.H
- Description: Implement sys/mman.h and functions
- Status: Open
- Priority: Low
-
- Title: WAIT.H
- Description: Implement sys/wait.h and functions. Consider implementing wait,
- waitpid, waitid. At present, a parent has no information about
- child tasks.
-
- Update: A simple but usable version of waitpid() has been included.
- This version is not compliant with all specifications and can be
- enabled with CONFIG_SCHED_WAITPID.
- Status: Open
- Priority: Low
-
- Title: MISSING ERRNO SETTINGS
- Description: Several APIs do not set errno. Need to review all APIs.
- Update: These are being fixed as they are encountered. There is
- no accounting of how many interfaces have this problem.
- Status: Open
- Priority: Medium, required for standard compliance (but makes the
- code bigger)
-
Title: TICKLESS OS
Description: On a side note, I have thought about a tick-less timer for the OS
for a long time. Basically we could replace the periodic system
@@ -107,18 +82,22 @@ o Task/Scheduler (sched/)
3) sched_process_timeslice(). Then there is round-robin time-slicing.
- Status: Open
+ The primary advantage of a tickless OS is that is would allow for
+ reduce power consumptions. That is because timer interrupts will
+ usually awaken CPUs from reduced power consumption states.
+ Status: Open. There will probably be no tickless OS implementation unless
+ someone gets motivated and drives the change.
Priority: Low
- Title: posix_spawn()
- Description: This would be a good interface to add to NuttX. It is really
- just a re-packaging of the existing, non-standard NuttX exec()
- function.
- Status: Open
- Priority: Medium low.
-
-o On-demand paging (sched/)
- ^^^^^^^^^^^^^^^^^^^^^^^^^
+ Title: pause() NON-COMPLIANCE
+ Description: In the POSIX description of this function is the pause() function
+ will suspend the calling thread until delivery of a signal whose
+ action is either to execute a signal-catching function or to
+ terminate the process. The current implementation only waits for
+ any non-blocked signal to be received. It should only wake up if
+ the signal is delivered to a handler.
+ Status: Open.
+ Priority: Medium Low.
Title: ON-DEMAND PAGE INCOMPLETE
Description: On-demand paging has recently been incorporated into the RTOS.
@@ -130,19 +109,16 @@ o On-demand paging (sched/)
configs/ea3131/pgnsh and locked directories). There are
some limitations of this testing so I still cannot say that
the feature is fully functional.
- Status: Open
+ Status: Open. This has been put on the shelf for some time.
Priority: Medium-Low
-o Other core OS logic
- ^^^^^^^^^^^^^^^^^^^
-
Title: GET_ENVIRON_PTR()
Description: get_environ_ptr() (sched/sched_getenvironptr.c) is not implemented.
The representation of the the environment strings selected for
NutX is not compatible with the operation. Some significant
re-design would be required to implement this funcion and that
effort is thought to be not worth the result.
- Status: Open
+ Status: Open. No change is planned.
Priority: Low -- There is no plan to implement this.
Title: TIMER_GETOVERRUN()
@@ -150,6 +126,92 @@ o Other core OS logic
Status: Open
Priority: Low -- There is no plan to implement this.
+ Title: USER-SPACE WORK QUEUES
+ Description: There has been some use of work queues that has crept into some
+ user code. I am thinking of NxWidgets::CNxTimer. That timer
+ logic was originally implemented (correctly) using POSIX timers,
+ but was re-implemented using timed work.
+
+ The issue is that NxWidgets::CNxTimer is a user-space application
+ but the work queues are an OS internal feature. This will be a
+ problem for KERNEL builds. Hooks and definitions have been added
+ in include/nuttx/wqueue.h to support a user-space work queue, but
+ the corresponding logic has not been implemented.
+
+ The work queue logic will need to be moved from sched/ to libc/wqueue/
+ Status: Open. No work will probably be done until a functional KERNEL build
+ that includes NxWisges::CNxTimer is needed.
+ Priority: Medium Low for now
+
+ Title: INCOMPATIBILITES WITH execv() AND execl()
+ Description: Simplified 'execl()' and 'execv()' functions are provided by
+ NuttX. NuttX does not support processes and hence the concept
+ of overlaying a tasks process image with a new process image
+ does not make any sense. In NuttX, these functions are
+ wrapper functions that:
+
+ 1. Call the non-standard binfmt function 'exec', and then
+ 2. exit(0).
+
+ As a result, the current implementations of 'execl()' and
+ 'execv()' suffer from some incompatibilities, the most
+ serious of these is that the exec'ed task will not have
+ the same task ID as the vfork'ed function. So the parent
+ function cannot know the ID of the exec'ed task.
+ Status: Open
+ Priority: Medium Low for now
+
+ Title: IMPROVED TASK CONTROL BLOCK STRUCTURE
+ Description: All task resources that are shared amongst threads have
+ their own "break-away", reference-counted structure. The
+ Task Control Block (TCB) of each thread holds a reference
+ to each breakaway structure (see include/nuttx/sched.h).
+ It would be more efficent to have one reference counted
+ structure that holds all of the shared resources.
+
+ These are the current shared structures:
+ - Environment varaibles (struct environ_s)
+ - PIC data space and address environments (struct dspace_s)
+ - File descriptors (struct filelist)
+ - FILE streams (struct streamlist)
+ - Sockets (struct socketlist)
+ Status: Open
+ Priority: Low. This is an enhancement. It would slight reduce
+ memory usage but would also increase coupling. These
+ resources are nicely modular now.
+
+ Title: ISSUES WITH atexit() AND on_exit()
+ Description: These functions execute with the following bad properties:
+
+ 1. They run with interrupts disabled,
+ 2. They run in supervisor mode (if applicable), and
+ 3. They do not obey any setup of PIC or address
+ environments. Do they need to?
+
+ The fix for all of these issues it to have the callbacks
+ run on the caller's thread (as with signal handlers).
+ Status: Open
+ Priority: Medium Low. This is an important change to some less
+ important interfaces. For the average user, these
+ functions are just fine the way they are.
+
+ Title: execv() AND vfork()
+ Description: There is a problem when vfork() calls execv() (or execl()) to
+ start a new appliction: When the parent thread calls vfork()
+ it receives and gets the pid of the vforked task, and *not*
+ the pid of the desired execv'ed application.
+
+ The same tasking arrangement is used by the standard function
+ posix_spawn(). However, posix_spawn uses the non-standard, internal
+ NuttX interface task_reparent() to replace the childs parent task
+ with the caller of posix_spawn(). That cannot be done with vfork()
+ because we don't know what vfor() is going to do.
+
+ Any solution to this is either very difficult or impossible with
+ an MMU.
+ Status: Open
+ Priority: Low (it might as well be low since it isn't going to be fixed).
+
o Memory Managment (mm/)
^^^^^^^^^^^^^^^^^^^^^^
@@ -212,7 +274,7 @@ o Memory Managment (mm/)
be required to keep this memory on the correct list (or on
no list at all).
- Status: Open
+ Status: Open. No changes are planned.
Priority: Medium/Low, a good feature to prevent memory leaks but would
have negative impact on memory usage and code size.
@@ -221,8 +283,10 @@ o Signals (sched/, arch/)
Title: STANDARD SIGNALS
Description: 'Standard' signals and signal actions are not supported.
- (e.g., SIGINT, SIGCHLD, SIGSEGV, etc).
- Status: Open
+ (e.g., SIGINT, SIGSEGV, etc).
+
+ Update: SIG_CHLD is support if configured.
+ Status: Open. No changes are planned.
Priority: Low, required by standards but not so critical for an
embedded system.
@@ -234,17 +298,25 @@ o Signals (sched/, arch/)
are required by the POSIX standard.
Priority: Low for now
+ Title: SIGNAL NUMBERING
+ Description: In signal.h, the range of valid signals is listed as 0-31. However,
+ in many interfaces, 0 is not a valid signal number. The valid
+ signal number should be 1-32. The signal set operations would need
+ to map bits appropriately.
+ Status: Open
+ Priority: Low. Even if there are only 31 usable signals, that is still a lot.
+
o pthreads (sched/)
^^^^^^^^^^^^^^^^^
Title: CANCELLATION POINTS
Description: pthread_cancel(): Should implement cancellation points and
pthread_testcancel()
- Status: Open
+ Status: Open. No changes are planned.
Priority: Low, probably not that useful
Title: PTHREAD_PRIO_PROTECT
- Description: Extended pthread_mutexattr_setprotocol() suport PTHREAD_PRIO_PROTECT:
+ Description: Extended pthread_mutexattr_setprotocol() suport PTHREAD_PRIO_PROTECT:
"When a thread owns one or more mutexes initialized with the
PTHREAD_PRIO_PROTECT protocol, it shall execute at the higher of its
priority or the highest of the priority ceilings of all the mutexes
@@ -260,7 +332,7 @@ o pthreads (sched/)
PTHREAD_PRIO_PROTECT protocol attributes, it shall not be subject to
being moved to the tail of the scheduling queue at its priority in the
event that its original priority is changed."
- Status: Open
+ Status: Open. No changes planned.
Priority: Low -- about zero, probably not that useful. Priority inheritance is
already supported and is a much better solution. And it turns out
that priority protection is just about as complex as priority inheritance.
@@ -442,21 +514,25 @@ o Network (net/, drivers/net)
Title: SOCK_RAW/SOCK_PACKET
Description: Should implement SOCK_RAW, SOCK_PACKET
- Status: Open
+ Status: Open. No changes are planned.
Priority: Low
- Tile: MULTIPLE NETWORK INTERFACE SUPPORT
+ Title: MULTIPLE NETWORK INTERFACE SUPPORT
Description: uIP polling issues / Multiple network interface support:
+
(1) Current logic will not support multiple ethernet drivers.
Each driver should poll on TCP connections connect on the
network supported by the driver; UDP polling should respond
with TX data only if the UDP packet is intended for the
the network supported by the driver.
+
(2) If there were multiple drivers, polling would occur at
double the rate. Fix by using bound IP address in TCP
connection (lipaddr) and verifying that it is in the subnet
served by the driver.
- Status: Open
+
+ Status: Open. Nothing will probably be done until I have a platform
+ with two network interfaces that I need to support.
Priority: Medium, The feature is not important, but it is important
for NuttX to resolve the architectural issues.
@@ -464,7 +540,7 @@ o Network (net/, drivers/net)
Description: sendto() and multiple network interface support:
When polled, would have to assure that the destination IP
is on the subnet served by the polling driver.
- Status: Open
+ Status: Open. This is really part of the above issue.
Priority: Medium, The feature is not important, but it is important
for NuttX to resolve the architectural issues.
@@ -472,7 +548,8 @@ o Network (net/, drivers/net)
Description: IPv6 support is incomplete. Adam Dunkels has recently announced
IPv6 support for uIP (currently only as part of Contiki). Those
changes need to be ported to NuttX.
- Status: Open
+ Status: Open. No work will probably be done until there is a specific
+ requirement for IPv6.
Priority: Medium
Title: LISTENING FOR UDP BROADCASTS
@@ -488,7 +565,7 @@ o Network (net/, drivers/net)
driver should be throttled. Perhaps the driver should disable
RX interrupts when throttled and re-anable on each poll time.
recvfrom would, of course, have to un-throttle.
- Status: Open
+ Status: Open. This is just a thought experiment. No changes are planned.
Priority: Medium
Title: STANDARDIZE ETHERNET DRIVER STATISTICS
@@ -590,6 +667,21 @@ o Network (net/, drivers/net)
Status: Open
Priority: Low... fix defconfig files as necessary.
+ Title: net_poll() DOES NOT HANDLE LOSS-OF-CONNECTION CORRECTLY
+ Description: When a loss of connection is detected by any logic waiting on the
+ networking events, the function net_lostconnection() must be called.
+ That function just sets some bits in the socket structure so that
+ it remembers that the connection is lost.
+
+ That is currently done in recvfrom(), send(), and net_monitor.c. But
+ it is not done in the net_poll() logic; that logic correctly sets
+ the POLLHUP status, but it does not call net_lostconnection(). As a
+ result, if recv() is called after the poll() or select(), the system
+ will hang because the recv() does not know that the connection has
+ been lost.
+ Status: Open
+ Priority: High
+
o USB (drivers/usbdev, drivers/usbhost)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -637,6 +729,15 @@ o USB (drivers/usbdev, drivers/usbhost)
o Libraries (libc/)
^^^^^^^^^^^^^^^^^
+ Title: SIGNED time_t
+ Description: The NuttX time_t is type uint32_t. I think this is consistent
+ with all standards and with normal usage of time_t. However,
+ according to Wikipedia, time_t is usually implemented as a
+ signed 32-bit value.
+ Status: Open
+ Priority: Very low unless there is some compelling issue that I do not
+ know about.
+
Title: ENVIRON
Description: The definition of environ in stdlib.h is bogus and will not
work as it should. This is because the underlying
@@ -974,13 +1075,13 @@ o Build system
Priority: Low -- the kernel build configuration is not fully fielded
yet.
- Title: mconf NOT AVAILABLE IN NATIVE WINDOWS BUILD
- Description: NuttX is migrating to the use of the kconfig-frontends mconf
+ Title: kconfig-mconf NOT AVAILABLE IN NATIVE WINDOWS BUILD
+ Description: NuttX is migrating to the use of the kconfig-frontends kconfig-mconf
tool for all configurations. In NuttX 6.24, support for native
- Windows builds was added. However, the mconf tool does not
+ Windows builds was added. However, thekconfig- mconf tool does not
build to run natively under Windows.
- Some effort was spent trying to get a clean mconf build under
+ Some effort was spent trying to get a clean kconfig-mconf build under
Windows. This is documented in the message thread beginning
here: http://tech.groups.yahoo.com/group/nuttx/message/2900.
The build was successfully completed using: MinGW-GCC, MSYS,
@@ -992,8 +1093,8 @@ o Build system
was considered a show stopper and the changs were not checked
in.
- Options: (1) Use conf (not mconf). confis the text-only
- configuration tool, (2) fix mconf, (3) write another variant
+ Options: (1) Use kconfigs-conf (not kconfig-mconf). confis the text-only
+ configuration tool, (2) fix kconfig-mconf, (3) write another variant
of the configuration tool for windows, or (4) do all configuration
under Cygwin or MSYS. I am doing (4) now, but this is very
awkward because I have to set the apps path to ../apps (vs
@@ -1002,20 +1103,6 @@ o Build system
Status: Open, there are some workarounds, but none are good.
Priority: High
- Title: configure.sh NOT AVAILABLE IN NATIVE WINDOWS BUILD
- Description: configure.sh is a Bash script and cannot be used from a Windows
- CMD.exe window. I started a configure.bat script, but I do
- not have the batch file programming skills to duplicate some
- of the more complex operations.
-
- I also considered adding a configure.c file that could be
- compiled and then executed by configure.bat (and configure.sh?).
- But I have not gone down that path yet.
-
- The current work-around is to configure under Cygwin.
- Status: Open
- Priority: High
-
o Linux/Cywgin simulation (arch/sim)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1090,27 +1177,6 @@ o ARM (arch/arm/)
Status: Open
Priority: Low
- Title: SVCALLS AND HARDFAULTS
- Description: The Cortex-M3 user context switch logic uses SVCall instructions.
- This user context switching time could be improved by eliminating
- the SVCalls and developing assembly language implementations
- of the context save and restore logic.
- Also, because interrupts are always disabled when the SVCall is
- executed, the SVC goes to the hard fault handler where it must
- be handled as a special case. I recall seeing some controls
- somewhere that will allow to suppress one hard fault. I don't
- recall the control, but something like this should be used before
- executing the SVCall so that it vectors directly to the SVC
- handler.
- Another, more standard option would be to use interrupt priority
- levels to control interrupts. In that case, (1) The SVC would
- be the highest priority interrupt (0), (2) irqsave() would set
- the interrupt mask level to just above that, and (2) irqrestore
- would restore the interrupt level. This would not be diffult,
- but does affect a lot of files!
- Status: Open
- Priority: Low
-
Title: ARM INTERRUPTS AND USER MODE
Description: The ARM interrupt handling (arch/arm/src/arm/up_vectors.S) returns
using 'ldmia sp, {r0-r15}^' My understanding is that this works
@@ -1370,7 +1436,7 @@ o ARM/STR71x (arch/arm/src/str71x/)
Status: Open
Priority: Medium -- Will be very high if you do SPI access from multiple threads.
-o ARM/LM3S6918 (arch/arm/src/lm3s/)
+o ARM/LM3S6918 (arch/arm/src/lm/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: I2C DRIVER
@@ -1460,6 +1526,11 @@ o ARM/STM32 (arch/arm/src/stm32/)
Status: Open
Priority: Low
+ Title: STM32 F4 USB OTG FS DEVICE-SIDE DRIVER
+ Description: This driver is reported to be buggy and to need some TLC.
+ Status: Open
+ Priority: High
+
o AVR (arch/avr)
^^^^^^^^^^^^^^
@@ -1693,8 +1764,8 @@ o Renesas M16C/26 (arch/sh/src/m16c)
Status: Open
Priority: Medium
-o z80/z8/ez80 (arch/z80)
- ^^^^^^^^^^^^^^^^^^^^^^^
+o z80/z8/ez80/z180 (arch/z80)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: SDCC INTEGER OVERFLOWS
Description: The SDCC version the same problems with integer overflow during
@@ -1784,6 +1855,14 @@ o z80/z8/ez80 (arch/z80)
Status: Open
Priority: Med
+ Title: UNFINISHED Z180 LOGIC NEEDED BY THE P112 BOARD
+ Description: 1) Need to revist the start-up logic. Looking at the P112 Bios
+ (Bios.mcd), I see that quite of bit of register setup is done
+ there.
+ 2) Finish ESCC driver logic.
+ Status: Open
+ Priority: Low (at least until I get P112 hardware)
+
o z16 (arch/z16)
^^^^^^^^^^^^^^^^
@@ -1975,6 +2054,32 @@ o NuttShell (NSH) (apps/nshlib)
Status: Open
Priority: Low (enhancement)
+ Title: RE-DIRECTION OF BUILTIN APPLICATONS
+ Description: There is a problem with the re-direction of output form built-in
+ applications in NSH. When output is re-directed, exec_builtin()
+ spawns a tiny trampoline task that re-directs the output as
+ requested, starts the built-in task and then exit.
+
+ The problem is that when exec_builtin() starts the trampoline task,
+ it receives and returns the pid of the trampoline task, and *not*
+ the pid of the desired builtin application. This bad pid is returned
+ to NSH and when NSH tries to use that pid in the waitpid() call, it
+ fails because the trampoline task no longer exists.
+
+ The same tasking arrangement is used by the standard function
+ posix_spawn(). However, posix_spawn uses the non-standard, internal
+ NuttX interface task_reparent() to replace the childs parent task
+ with the caller of posix_spawn().
+
+ exec_builtin() should not use this internal interface, however,
+ since it resides in the application space. The suggested solution
+ is (1) move the exec_builtin() logic into nuttx/sched, (2) make it
+ a semi-standard interface renamed to task_spawn() and prototyped
+ in nuttx/include/sched.h, and then (2) use task_reparent to solve
+ the parental problem in the same way that posix_spawn does.
+ Status: Open
+ Priority: Medium
+
o System libraries apps/system (apps/system)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig
index f19228143..c0f235c5d 100644
--- a/nuttx/arch/Kconfig
+++ b/nuttx/arch/Kconfig
@@ -16,6 +16,7 @@ config ARCH_8051
config ARCH_ARM
bool "ARM"
select ARCH_HAVE_INTERRUPTSTACK
+ select ARCH_HAVE_VFORK
---help---
The ARM architectures
@@ -102,12 +103,141 @@ source arch/x86/Kconfig
source arch/z16/Kconfig
source arch/z80/Kconfig
+comment "External Memory Configuration"
+
+config ARCH_HAVE_EXTNAND
+ bool
+
+config ARCH_HAVE_EXTNOR
+ bool
+
+config ARCH_HAVE_EXTDRAM
+ bool
+
+config ARCH_HAVE_EXTSRAM0
+ bool
+
+config ARCH_HAVE_EXTSRAM1
+ bool
+
+config ARCH_EXTNAND
+ bool "Configure external NAND"
+ default n
+ depends on ARCH_HAVE_EXTNAND
+ ---help---
+ Configure external NAND memory and, if applicable, map then external
+ NAND into the memory map.
+
+if ARCH_EXTNAND
+
+config ARCH_EXTNANDSIZE
+ int "External NAND size"
+ default 0
+ ---help---
+ Size of the external NAND in bytes.
+
+endif
+
+config ARCH_EXTNOR
+ bool "Configure external NOR memory"
+ default n
+ depends on ARCH_HAVE_EXTNOR
+ ---help---
+ Configure external NOR memory and, if applicable, map then external
+ NOR into the memory map.
+
+if ARCH_EXTNOR
+
+config ARCH_EXTNORSIZE
+ int "External NOR size"
+ default 0
+ ---help---
+ Size of the external NOR in bytes.
+
+endif
+
+config ARCH_EXTDRAM
+ bool "Configure external DRAM"
+ default n
+ depends on ARCH_HAVE_EXTDRAM
+ ---help---
+ Configure external DRAM memory and, if applicable, map then external
+ DRAM into the memory map.
+
+if ARCH_EXTDRAM
+
+config ARCH_EXTDRAMSIZE
+ int "External SDRAM size"
+ default 0
+ ---help---
+ Size of the external SDRAM in bytes.
+
+config ARCH_EXTDRAMHEAP
+ bool "Add external SDRAM to the heap"
+ default y
+ ---help---
+ Add the external SDRAM into the heap.
+
+endif
+
+config ARCH_EXTSRAM0
+ bool "Configure external SRAM (Bank 0)"
+ default n
+ depends on ARCH_HAVE_EXTSRAM0
+ ---help---
+ Configure external SRAM Bank 0 memory and, if applicable, map then
+ external SRAM Bank 0 into the memory map.
+
+if ARCH_EXTSRAM0
+
+config ARCH_EXTSRAM0SIZE
+ int "External SRAM size"
+ default 0
+ ---help---
+ Size of the external SRAM Bank 0 in bytes.
+
+config ARCH_EXTSRAM0HEAP
+ bool "Add external SRAM (Bank 0) to the heap"
+ default y
+ ---help---
+ Add external SRAM Bank 0 into the heap.
+
+endif
+
+config ARCH_EXTSRAM1
+ bool "Configure external SRAM (Bank 1)"
+ default n
+ depends on ARCH_HAVE_EXTSRAM1
+ ---help---
+ Configure external SRAM Bank 1 memory and, if applicable, map then
+ external SRAM Bank 1 into the memory map.
+
+if ARCH_EXTSRAM1
+
+config ARCH_EXTSRAM1SIZE
+ int "External SRAM1 size"
+ default 0
+ ---help---
+ Size of the external SRAM Bank 1 in bytes.
+
+config ARCH_EXTSRAM1HEAP
+ bool "Add external SRAM (Bank 1) to the heap"
+ default y
+ ---help---
+ Add external SRAM Bank 1 into the heap.
+
+endif
+
comment "Architecture Options"
config ARCH_NOINTC
bool
default n
+config ARCH_VECNOTIRQ
+ bool
+ default n
+
config ARCH_DMA
bool
default n
@@ -124,6 +254,10 @@ config ADDRENV
bool
default n
+config ARCH_HAVE_VFORK
+ bool
+ default n
+
config ARCH_STACKDUMP
bool "Dump stack on assertions"
default n
@@ -136,6 +270,20 @@ config ENDIAN_BIG
---help---
Select if architecture operates using big-endian byte ordering.
+config ARCH_HAVE_RAMFUNCS
+ bool
+ default n
+
+config ARCH_RAMFUNCS
+ bool "Copy functions to RAM on startup"
+ default n
+ depends on ARCH_HAVE_RAMFUNCS
+ ---help---
+ Copy some functions to RAM at boot time. This is done in some
+ architectures to improve performance. In other cases, it is done
+ so that FLASH can be reconfigured while the MCU executes out of
+ SRAM.
+
comment "Board Settings"
config BOARD_LOOPSPERMSEC
diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt
index 67b99b255..14704aa76 100644
--- a/nuttx/arch/README.txt
+++ b/nuttx/arch/README.txt
@@ -170,12 +170,12 @@ arch/arm - ARM-based micro-controllers
STATUS: This port has stalled because of development tool issues. Coding
is complete on the basic port (timer, serial console, SPI).
- arch/arm/include/lm3s and arch/arm/src/lm3s
- These directories contain support for the Luminary LMS family, particularly
- for the LM3S6918. The initial, release of this port was included in NuttX version
- 0.4.6. The current port includes timer, serial console, Ethernet, SSI, and microSD
- support. There are working configurations the NuttX OS test, to run the NuttShell
- (NSH), the NuttX networking test, and the uIP web server.
+ arch/arm/include/lm and arch/arm/src/lm
+ These directories contain support for the Luminary LM3S/4F family. The
+ initial, release of this port was included in NuttX version 0.4.6. The
+ current port includes timer, serial console, Ethernet, SSI, and microSD
+ support. There are working configurations the NuttX OS test, to run the
+ NuttShell (NSH), the NuttX networking test, and the uIP web server.
arch/arm/include/lpc214x and arch/arm/src/lpc214x
These directories provide support for NXP LPC214x family of
diff --git a/nuttx/arch/arm/Kconfig b/nuttx/arch/arm/Kconfig
index 4fce8efbf..5709f890f 100644
--- a/nuttx/arch/arm/Kconfig
+++ b/nuttx/arch/arm/Kconfig
@@ -46,15 +46,14 @@ config ARCH_CHIP_KINETIS
bool "Freescale Kinetis"
select ARCH_CORTEXM4
select ARCH_HAVE_MPU
- select ARCH_IRQPRIO
+ select ARCH_HAVE_RAMFUNCS
+ select ARCH_RAMFUNCS
---help---
Freescale Kinetis Architectures (ARM Cortex-M4)
-config ARCH_CHIP_LM3S
+config ARCH_CHIP_LM
bool "TI Stellaris"
- select ARCH_CORTEXM3
select ARCH_HAVE_MPU
- select ARCH_IRQPRIO
---help---
TI Stellaris LMS3 architecutres (ARM Cortex-M3)
@@ -62,7 +61,6 @@ config ARCH_CHIP_LPC17XX
bool "NXP LPC17xx"
select ARCH_CORTEXM3
select ARCH_HAVE_MPU
- select ARCH_IRQPRIO
---help---
NXP LPC17xx architectures (ARM Cortex-M3)
@@ -94,7 +92,6 @@ config ARCH_CHIP_LPC43XX
select ARCH_HAVE_CMNVECTOR
select ARMV7M_CMNVECTOR
select ARCH_HAVE_MPU
- select ARCH_IRQPRIO
---help---
NPX LPC43XX architectures (ARM Cortex-M4).
@@ -102,7 +99,6 @@ config ARCH_CHIP_SAM3U
bool "Atmel AT91SAM3U"
select ARCH_CORTEXM3
select ARCH_HAVE_MPU
- select ARCH_IRQPRIO
---help---
Atmel AT91SAM3U architectures (ARM Cortex-M3)
@@ -111,7 +107,6 @@ config ARCH_CHIP_STM32
select ARCH_HAVE_CMNVECTOR
select ARCH_HAVE_MPU
select ARCH_HAVE_I2CRESET
- select ARCH_IRQPRIO
---help---
STMicro STM32 architectures (ARM Cortex-M3/4).
@@ -135,9 +130,11 @@ config ARCH_ARM920T
config ARCH_CORTEXM3
bool
+ select ARCH_IRQPRIO
config ARCH_CORTEXM4
bool
+ select ARCH_IRQPRIO
config ARCH_FAMILY
string
@@ -151,7 +148,7 @@ config ARCH_CHIP
default "dm320" if ARCH_CHIP_DM320
default "imx" if ARCH_CHIP_IMX
default "kinetis" if ARCH_CHIP_KINETIS
- default "lm3s" if ARCH_CHIP_LM3S
+ default "lm" if ARCH_CHIP_LM
default "lpc17xx" if ARCH_CHIP_LPC17XX
default "lpc214x" if ARCH_CHIP_LPC214X
default "lpc2378" if ARCH_CHIP_LPC2378
@@ -161,6 +158,17 @@ config ARCH_CHIP
default "stm32" if ARCH_CHIP_STM32
default "str71x" if ARCH_CHIP_STR71X
+config ARMV7M_USEBASEPRI
+ bool "Use BASEPRI Register"
+ default n
+ depends on ARCH_CORTEXM3 || ARCH_CORTEXM4
+ ---help---
+ Use the BASEPRI register to enable and disable able interrupts. By
+ default, the PRIMASK register is used for this purpose. This
+ usually results in hardfaults that are properly handling by the
+ RTOS. Using the BASEPRI register will avoid these hardfault.
+ That is needed primarily for integration with some toolchains.
+
config ARCH_HAVE_CMNVECTOR
bool
@@ -274,8 +282,8 @@ endif
if ARCH_CHIP_KINETIS
source arch/arm/src/kinetis/Kconfig
endif
-if ARCH_CHIP_LM3S
-source arch/arm/src/lm3s/Kconfig
+if ARCH_CHIP_LM
+source arch/arm/src/lm/Kconfig
endif
if ARCH_CHIP_LPC17XX
source arch/arm/src/lpc17xx/Kconfig
diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h
index 606b3988f..8acec4c07 100644
--- a/nuttx/arch/arm/include/armv7-m/irq.h
+++ b/nuttx/arch/arm/include/armv7-m/irq.h
@@ -60,6 +60,10 @@
# include <arch/armv7-m/irq_lazyfpu.h>
#endif
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+# include <arch/chip/chip.h>
+#endif
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -114,7 +118,11 @@ struct xcptcontext
*/
uint32_t saved_pc;
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ uint32_t saved_basepri;
+#else
uint32_t saved_primask;
+#endif
uint32_t saved_xpsr;
#endif
@@ -130,12 +138,75 @@ struct xcptcontext
#ifndef __ASSEMBLY__
+/* Get/set the PRIMASK register */
+
+static inline uint8_t getprimask(void) inline_function;
+static inline uint8_t getprimask(void)
+{
+ uint32_t primask;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, primask\n"
+ : "=r" (primask)
+ :
+ : "memory");
+
+ return (uint8_t)primask;
+}
+
+static inline void setprimask(uint32_t primask) inline_function;
+static inline void setprimask(uint32_t primask)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr primask, %0\n"
+ :
+ : "r" (primask)
+ : "memory");
+}
+
+/* Get/set the BASEPRI register. The BASEPRI register defines the minimum
+ * priority for exception processing. When BASEPRI is set to a nonzero
+ * value, it prevents the activation of all exceptions with the same or
+ * lower priority level as the BASEPRI value.
+ */
+
+static inline uint8_t getbasepri(void) inline_function;
+static inline uint8_t getbasepri(void)
+{
+ uint32_t basepri;
+
+ __asm__ __volatile__
+ (
+ "\tmrs %0, basepri\n"
+ : "=r" (basepri)
+ :
+ : "memory");
+
+ return (uint8_t)basepri;
+}
+
+static inline void setbasepri(uint32_t basepri) inline_function;
+static inline void setbasepri(uint32_t basepri)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr basepri, %0\n"
+ :
+ : "r" (basepri)
+ : "memory");
+}
+
/* Disable IRQs */
static inline void irqdisable(void) inline_function;
static inline void irqdisable(void)
{
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
+#else
__asm__ __volatile__ ("\tcpsid i\n");
+#endif
}
/* Save the current primask state & disable IRQs */
@@ -143,6 +214,14 @@ static inline void irqdisable(void)
static inline irqstate_t irqsave(void) inline_function;
static inline irqstate_t irqsave(void)
{
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+
+ uint8_t basepri = getbasepri();
+ setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
+ return (irqstate_t)basepri;
+
+#else
+
unsigned short primask;
/* Return the current value of primask register and set
@@ -158,6 +237,7 @@ static inline irqstate_t irqsave(void)
: "memory");
return primask;
+#endif
}
/* Enable IRQs */
@@ -165,14 +245,18 @@ static inline irqstate_t irqsave(void)
static inline void irqenable(void) inline_function;
static inline void irqenable(void)
{
+ setbasepri(0);
__asm__ __volatile__ ("\tcpsie i\n");
}
/* Restore saved primask state */
-static inline void irqrestore(irqstate_t primask) inline_function;
-static inline void irqrestore(irqstate_t primask)
+static inline void irqrestore(irqstate_t flags) inline_function;
+static inline void irqrestore(irqstate_t flags)
{
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ setbasepri((uint32_t)flags);
+#else
/* If bit 0 of the primask is 0, then we need to restore
* interupts.
*/
@@ -184,63 +268,9 @@ static inline void irqrestore(irqstate_t primask)
"\tcpsie i\n"
"1:\n"
:
- : "r" (primask)
- : "memory");
-}
-
-/* Get/set the primask register */
-
-static inline uint8_t getprimask(void) inline_function;
-static inline uint8_t getprimask(void)
-{
- uint32_t primask;
- __asm__ __volatile__
- (
- "\tmrs %0, primask\n"
- : "=r" (primask)
- :
- : "memory");
-
- return (uint8_t)primask;
-}
-
-static inline void setprimask(uint32_t primask) inline_function;
-static inline void setprimask(uint32_t primask)
-{
- __asm__ __volatile__
- (
- "\tmsr primask, %0\n"
- :
- : "r" (primask)
- : "memory");
-}
-
-/* Get/set the basepri register */
-
-static inline uint8_t getbasepri(void) inline_function;
-static inline uint8_t getbasepri(void)
-{
- uint32_t basepri;
-
- __asm__ __volatile__
- (
- "\tmrs %0, basepri\n"
- : "=r" (basepri)
- :
- : "memory");
-
- return (uint8_t)basepri;
-}
-
-static inline void setbasepri(uint32_t basepri) inline_function;
-static inline void setbasepri(uint32_t basepri)
-{
- __asm__ __volatile__
- (
- "\tmsr basepri, %0\n"
- :
- : "r" (basepri)
+ : "r" (flags)
: "memory");
+#endif
}
/* Get/set IPSR */
diff --git a/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h
index e646731eb..bc67004ed 100644
--- a/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h
+++ b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h
@@ -51,7 +51,11 @@
*/
#define REG_R13 (0) /* R13 = SP at time of interrupt */
-#define REG_PRIMASK (1) /* PRIMASK */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+# define REG_BASEPRI (1) /* BASEPRI */
+#else
+# define REG_PRIMASK (1) /* PRIMASK */
+#endif
#define REG_R4 (2) /* R4 */
#define REG_R5 (3) /* R5 */
#define REG_R6 (4) /* R6 */
diff --git a/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h
index 2c3600b7f..f2380cbb6 100644
--- a/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h
+++ b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h
@@ -51,7 +51,11 @@
*/
#define REG_R13 (0) /* R13 = SP at time of interrupt */
-#define REG_PRIMASK (1) /* PRIMASK */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+# define REG_BASEPRI (1) /* BASEPRI */
+#else
+# define REG_PRIMASK (1) /* PRIMASK */
+#endif
#define REG_R4 (2) /* R4 */
#define REG_R5 (3) /* R5 */
#define REG_R6 (4) /* R6 */
diff --git a/nuttx/arch/arm/include/stm32/chip.h b/nuttx/arch/arm/include/stm32/chip.h
index d34c2eb4f..14d92ea3d 100644
--- a/nuttx/arch/arm/include/stm32/chip.h
+++ b/nuttx/arch/arm/include/stm32/chip.h
@@ -183,9 +183,43 @@
# define STM32_NRNG 0 /* No random number generator (RNG) */
# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+/* STM32 F103 Medium Density Family *************************************************/
+/* STM32F103RB is in the Medium-density performance line and is provided in 64 pin
+ * packages with 128K Flash, USB, CAN, 7 timers, 2 ADCs, 9 com. interfaces
+ */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F103RBT6)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# define CONFIG_STM32_MEDIUMDENSITY 1 /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F100x, STM32F101x, and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */
+# define STM32_NFSMC 0 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timer TIM1 */
+# define STM32_NGTIM 3 /* General timers TIM2,3,4 */
+# define STM32_NBTIM 0 /* Two basic timers TIM6 and TIM7 */
+# define STM32_NDMA 1 /* DMA1 */
+# define STM32_NSPI 2 /* SPI1-2 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 3 /* USART1-3 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 1 /* bxCAN1 */
+# define STM32_NSDIO 0 /* No SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 51 /* GPIOA-E */
+# define STM32_NADC 2 /* ADC1-2 */
+# define STM32_NDAC 0 /* No DAC */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NTHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
/* STM32 F103 High Density Family ***************************************************/
-/* STM32F103RC, STM32F103RD, and STM32F103RE are all provided in 64 pin packages and differ
- * only in the available FLASH and SRAM.
+/* STM32F103RC, STM32F103RD, and STM32F103RE are all provided in 64 pin packages and
+ * differ only in the available FLASH and SRAM.
*/
#elif defined(CONFIG_ARCH_CHIP_STM32F103RET6)
@@ -658,5 +692,15 @@
# error "Unsupported STM32 chip"
#endif
+/* NVIC priority levels *************************************************************/
+
+#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* All bits set in minimum priority */
+#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */
+#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */
+#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */
+
+#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP)
+#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX
+
#endif /* __ARCH_ARM_INCLUDE_STM32_CHIP_H */
diff --git a/nuttx/arch/arm/include/types.h b/nuttx/arch/arm/include/types.h
index c06b28950..1d2ea4cfe 100644
--- a/nuttx/arch/arm/include/types.h
+++ b/nuttx/arch/arm/include/types.h
@@ -44,6 +44,8 @@
* Included Files
****************************************************************************/
+#include <nuttx/config.h>
+
/****************************************************************************
* Definitions
****************************************************************************/
@@ -87,7 +89,11 @@ typedef unsigned int _uintptr_t;
*/
#ifdef __thumb2__
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+typedef unsigned char irqstate_t;
+#else
typedef unsigned short irqstate_t;
+#endif
#else /* __thumb2__ */
typedef unsigned int irqstate_t;
#endif /* __thumb2__ */
diff --git a/nuttx/arch/arm/src/armv7-m/Kconfig b/nuttx/arch/arm/src/armv7-m/Kconfig
index dc5aa3915..a154a4c5c 100644
--- a/nuttx/arch/arm/src/armv7-m/Kconfig
+++ b/nuttx/arch/arm/src/armv7-m/Kconfig
@@ -49,3 +49,11 @@ config ARMV7M_TOOLCHAIN_RAISONANCE
depends on HOST_WINDOWS
endchoice
+
+config ARMV7M_OABI_TOOLCHAIN
+ bool "OABI (vs EABI)"
+ default y
+ depends on ARMV7M_TOOLCHAIN_BUILDROOT
+ ---help---
+ Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi-
+
diff --git a/nuttx/arch/arm/src/armv7-m/Toolchain.defs b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
index e214ce8bd..45ee9e36c 100644
--- a/nuttx/arch/arm/src/armv7-m/Toolchain.defs
+++ b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
@@ -53,7 +53,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_BUILDROOT) \
- $(CONFIG_LM3S_BUILDROOT) \
+ $(CONFIG_LM_BUILDROOT) \
$(CONFIG_LPC17_BUILDROOT) \
$(CONFIG_LPC43_BUILDROOT) \
$(CONFIG_SAM3U_BUILDROOT) \
@@ -77,7 +77,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_CODESOURCERYL) \
- $(CONFIG_LM3S_CODESOURCERYL) \
+ $(CONFIG_LM_CODESOURCERYL) \
$(CONFIG_LPC17_CODESOURCERYL) \
$(CONFIG_LPC43_CODESOURCERYL) \
$(CONFIG_SAM3U_CODESOURCERYL) \
@@ -88,7 +88,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_CODESOURCERYW) \
- $(CONFIG_LM3S_CODESOURCERYW) \
+ $(CONFIG_LM_CODESOURCERYW) \
$(CONFIG_LPC17_CODESOURCERYW) \
$(CONFIG_LPC43_CODESOURCERYW) \
$(CONFIG_SAM3U_CODESOURCERYW) \
@@ -99,7 +99,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_DEVKITARM) \
- $(CONFIG_LM3S_DEVKITARM) \
+ $(CONFIG_LM_DEVKITARM) \
$(CONFIG_LPC17_DEVKITARM) \
$(CONFIG_LPC43_DEVKITARM) \
$(CONFIG_SAM3U_DEVKITARM) \
@@ -160,14 +160,15 @@ endif
# NuttX buildroot under Linux or Cygwin
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),BUILDROOT)
- # OABI
- # CROSSDEV = arm-nuttx-elf-
- # ARCROSSDEV = arm-nuttx-elf-
- # ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft
- # EABI
+ifeq ($(CONFIG_ARMV7M_OABI_TOOLCHAIN),y)
+ CROSSDEV = arm-nuttx-elf-
+ ARCROSSDEV = arm-nuttx-elf-
+ ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft
+else
CROSSDEV = arm-nuttx-eabi-
ARCROSSDEV = arm-nuttx-eabi-
ARCHCPUFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft
+endif
MAXOPTIMIZATION = -Os
endif
diff --git a/nuttx/arch/arm/src/armv7-m/up_assert.c b/nuttx/arch/arm/src/armv7-m/up_assert.c
index 282ff6a57..ab30b09f3 100644
--- a/nuttx/arch/arm/src/armv7-m/up_assert.c
+++ b/nuttx/arch/arm/src/armv7-m/up_assert.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_assert.c
*
- * Copyright (C) 2009-2010, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2010, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -147,8 +147,13 @@ static inline void up_registerdump(void)
current_regs[REG_R10], current_regs[REG_R11],
current_regs[REG_R12], current_regs[REG_R13],
current_regs[REG_R14], current_regs[REG_R15]);
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ lldbg("xPSR: %08x BASEPRI: %08x\n",
+ current_regs[REG_XPSR], current_regs[REG_BASEPRI]);
+#else
lldbg("xPSR: %08x PRIMASK: %08x\n",
current_regs[REG_XPSR], current_regs[REG_PRIMASK]);
+#endif
}
}
#else
diff --git a/nuttx/arch/arm/src/armv7-m/up_doirq.c b/nuttx/arch/arm/src/armv7-m/up_doirq.c
index 375054fba..6063f9ca1 100644
--- a/nuttx/arch/arm/src/armv7-m/up_doirq.c
+++ b/nuttx/arch/arm/src/armv7-m/up_doirq.c
@@ -79,9 +79,11 @@ uint32_t *up_doirq(int irq, uint32_t *regs)
uint32_t *savestate;
/* Nested interrupts are not supported in this implementation. If you want
- * implemented nested interrupts, you would have to (1) change the way that
- * current regs is handled and (2) the design associated with
- * CONFIG_ARCH_INTERRUPTSTACK.
+ * to implement nested interrupts, you would have to (1) change the way that
+ * current_regs is handled and (2) the design associated with
+ * CONFIG_ARCH_INTERRUPTSTACK. The savestate variable will not work for
+ * that purpose as implemented here because only the outermost nested
+ * interrupt can result in a context switch (it can probably be deleted).
*/
/* Current regs non-zero indicates that we are processing an interrupt;
diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S
index c9f216027..17344db41 100644
--- a/nuttx/arch/arm/src/armv7-m/up_exception.S
+++ b/nuttx/arch/arm/src/armv7-m/up_exception.S
@@ -2,7 +2,7 @@
* arch/arm/src/stm32/up_exception.S
* arch/arm/src/chip/up_exception.S
*
- * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Michael Smith. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
@@ -100,7 +100,11 @@ exception_common:
mov r2, r1 /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
/* (ignoring the xPSR[9] alignment bit) */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ mrs r3, basepri /* R3=Current BASEPRI setting */
+#else
mrs r3, primask /* R3=Current PRIMASK setting */
+#endif
#ifdef CONFIG_ARCH_FPU
@@ -205,7 +209,12 @@ exception_common:
/* Restore the interrupt state */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ msr basepri, r3 /* Restore interrupts priority masking*/
+ cpsie i /* Re-enable interrupts */
+#else
msr primask, r3 /* Restore interrupts */
+#endif
/* Always return with R14 containing the special value that will: (1)
* return to thread mode, and (2) select the correct stack.
diff --git a/nuttx/arch/arm/src/armv7-m/up_hardfault.c b/nuttx/arch/arm/src/armv7-m/up_hardfault.c
index c30015ad2..fa750b525 100644
--- a/nuttx/arch/arm/src/armv7-m/up_hardfault.c
+++ b/nuttx/arch/arm/src/armv7-m/up_hardfault.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_hardfault.c
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,9 @@
* Pre-processor Definitions
****************************************************************************/
-/* Debug output from this file may interfere with context switching! */
+/* If CONFIG_ARMV7M_USEBASEPRI=n, then debug output from this file may
+ * interfere with context switching!
+ */
#ifdef CONFIG_DEBUG_HARDFAULT
# define hfdbg(format, arg...) lldbg(format, ##arg)
@@ -92,18 +94,19 @@
int up_hardfault(int irq, FAR void *context)
{
+#if defined(CONFIG_DEBUG_HARDFAULT) || !defined(CONFIG_ARMV7M_USEBASEPRI)
uint32_t *regs = (uint32_t*)context;
- uint16_t *pc;
- uint16_t insn;
+#endif
/* Get the value of the program counter where the fault occurred */
- pc = (uint16_t*)regs[REG_PC] - 1;
+#ifndef CONFIG_ARMV7M_USEBASEPRI
+ uint16_t *pc = (uint16_t*)regs[REG_PC] - 1;
if ((void*)pc >= (void*)&_stext && (void*)pc < (void*)&_etext)
{
/* Fetch the instruction that caused the Hard fault */
- insn = *pc;
+ uint16_t insn = *pc;
hfdbg(" PC: %p INSN: %04x\n", pc, insn);
/* If this was the instruction 'svc 0', then forward processing
@@ -116,6 +119,7 @@ int up_hardfault(int irq, FAR void *context)
return up_svcall(irq, context);
}
}
+#endif
/* Dump some hard fault info */
@@ -133,7 +137,13 @@ int up_hardfault(int irq, FAR void *context)
hfdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
- hfdbg(" PSR=%08x\n", regs[REG_XPSR]);
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ hfdbg(" xPSR: %08x BASEPRI: %08x (saved)\n",
+ current_regs[REG_XPSR], current_regs[REG_BASEPRI]);
+#else
+ hfdbg(" xPSR: %08x PRIMASK: %08x (saved)\n",
+ current_regs[REG_XPSR], current_regs[REG_PRIMASK]);
+#endif
(void)irqsave();
lldbg("PANIC!!! Hard fault: %08x\n", getreg32(NVIC_HFAULTS));
diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
index 52a2682a0..4af553f25 100644
--- a/nuttx/arch/arm/src/armv7-m/up_initialstate.c
+++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_initialstate.c
*
- * Copyright (C) 2009, 2011-2 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -156,7 +156,7 @@ void up_initial_state(_TCB *tcb)
xcp->regs[REG_FPSCR] = 0; // XXX initial FPSCR should be configurable
xcp->regs[REG_FPReserved] = 0;
-#endif
+#endif /* CONFIG_ARCH_FPU */
#ifdef CONFIG_NUTTX_KERNEL
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
@@ -165,7 +165,7 @@ void up_initial_state(_TCB *tcb)
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PROCESS_STACK;
}
-#endif
+#endif /* CONFIG_NUTTX_KERNEL */
#else /* CONFIG_ARMV7M_CMNVECTOR */
@@ -189,12 +189,16 @@ void up_initial_state(_TCB *tcb)
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
}
-#endif
+#endif /* CONFIG_NUTTX_KERNEL */
#endif /* CONFIG_ARMV7M_CMNVECTOR */
/* Enable or disable interrupts, based on user configuration */
#ifdef CONFIG_SUPPRESS_INTERRUPTS
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ xcp->regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
+#else
xcp->regs[REG_PRIMASK] = 1;
#endif
+#endif /* CONFIG_SUPPRESS_INTERRUPTS */
}
diff --git a/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c
index 9e6dbd14b..9221a69a2 100644
--- a/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c
+++ b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_schedulesigaction.c
*
- * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -155,7 +155,11 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_pc = current_regs[REG_PC];
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ tcb->xcp.saved_basepri = current_regs[REG_BASEPRI];
+#else
tcb->xcp.saved_primask = current_regs[REG_PRIMASK];
+#endif
tcb->xcp.saved_xpsr = current_regs[REG_XPSR];
/* Then set up to vector to the trampoline with interrupts
@@ -163,7 +167,11 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
*/
current_regs[REG_PC] = (uint32_t)up_sigdeliver;
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ current_regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
+#else
current_regs[REG_PRIMASK] = 1;
+#endif
current_regs[REG_XPSR] = ARMV7M_XPSR_T;
/* And make sure that the saved context in the TCB
@@ -189,7 +197,11 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ tcb->xcp.saved_basepri = tcb->xcp.regs[REG_BASEPRI];
+#else
tcb->xcp.saved_primask = tcb->xcp.regs[REG_PRIMASK];
+#endif
tcb->xcp.saved_xpsr = tcb->xcp.regs[REG_XPSR];
/* Then set up to vector to the trampoline with interrupts
@@ -197,7 +209,11 @@ void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
*/
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
+#else
tcb->xcp.regs[REG_PRIMASK] = 1;
+#endif
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
}
diff --git a/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c
index 38673c41d..654214b39 100644
--- a/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c
+++ b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_sigdeliver.c
*
- * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2010, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,11 @@ void up_sigdeliver(void)
up_copystate(regs, rtcb->xcp.regs);
regs[REG_PC] = rtcb->xcp.saved_pc;
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ regs[REG_BASEPRI] = rtcb->xcp.saved_basepri;
+#else
regs[REG_PRIMASK] = rtcb->xcp.saved_primask;
+#endif
regs[REG_XPSR] = rtcb->xcp.saved_xpsr;
/* Get a local copy of the sigdeliver function pointer. We do this so that
@@ -115,7 +119,11 @@ void up_sigdeliver(void)
/* Then restore the task interrupt state */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ irqrestore((uint8_t)regs[REG_BASEPRI]);
+#else
irqrestore((uint16_t)regs[REG_PRIMASK]);
+#endif
/* Deliver the signals */
diff --git a/nuttx/arch/arm/src/armv7-m/vfork.S b/nuttx/arch/arm/src/armv7-m/vfork.S
new file mode 100644
index 000000000..f36ff23aa
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/vfork.S
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/vfork.S
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "up_vfork.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .syntax unified
+ .thumb
+ .file "vfork.S"
+ .globl up_vfork
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: vfork
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the behavior is
+ * undefined if the process created by vfork() either modifies any data other than
+ * a variable of type pid_t used to store the return value from vfork(), or returns
+ * from the function in which vfork() was called, or calls any other function before
+ * successfully calling _exit() or one of the exec family of functions.
+ *
+ * This thin layer implements vfork by simply calling up_vfork() with the vfork()
+ * context as an argument. The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() collects context information and
+ * transfers control up up_vfork().
+ * 2) up_vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * None
+ *
+ * Return:
+ * Upon successful completion, vfork() returns 0 to the child process and returns
+ * the process ID of the child process to the parent process. Otherwise, -1 is
+ * returned to the parent, no child process is created, and errno is set to
+ * indicate the error.
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .globl vfork
+ .type vfork, function
+vfork:
+ /* Create a stack frame */
+
+ mov r0, sp /* Save the value of the stack on entry */
+ sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */
+
+ /* CPU registers */
+ /* Save the volatile registers */
+
+ str r4, [sp, #VFORK_R4_OFFSET]
+ str r5, [sp, #VFORK_R5_OFFSET]
+ str r6, [sp, #VFORK_R6_OFFSET]
+ str r7, [sp, #VFORK_R7_OFFSET]
+ str r8, [sp, #VFORK_R8_OFFSET]
+ str r9, [sp, #VFORK_R9_OFFSET]
+ str r10, [sp, #VFORK_R10_OFFSET]
+
+ /* Save the frame pointer, stack pointer, and return address */
+
+ str fp, [sp, #VFORK_FP_OFFSET]
+ str r0, [sp, #VFORK_SP_OFFSET]
+ str lr, [sp, #VFORK_LR_OFFSET]
+
+ /* Floating point registers (not yet) */
+
+ /* Then, call up_vfork(), passing it a pointer to the stack structure */
+
+ mov r0, sp
+ bl up_vfork
+
+ /* Release the stack data and return the value returned by up_vfork */
+
+ ldr lr, [sp, #VFORK_LR_OFFSET]
+ add sp, sp, #VFORK_SIZEOF
+ bx lr
+ .size vfork, .-vfork
+ .end
+
diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h
index 0d3c5b1f2..55071345f 100644
--- a/nuttx/arch/arm/src/common/up_internal.h
+++ b/nuttx/arch/arm/src/common/up_internal.h
@@ -188,7 +188,7 @@ extern uint32_t _ebss; /* End+1 of .bss */
* will create a function named foo that will execute from RAM.
*/
-#ifdef CONFIG_BOOT_RAMFUNCS
+#ifdef CONFIG_ARCH_RAMFUNCS
# define __ramfunc__ __attribute__ ((section(".ramfunc")))
@@ -204,7 +204,7 @@ extern const uint32_t _framfuncs; /* Copy source address in FLASH */
extern uint32_t _sramfuncs; /* Copy destination start address in RAM */
extern uint32_t _eramfuncs; /* Copy destination start address in RAM */
-#endif /* CONFIG_BOOT_RAMFUNCS */
+#endif /* CONFIG_ARCH_RAMFUNCS */
#endif /* __ASSEMBLY__ */
/****************************************************************************
diff --git a/nuttx/arch/arm/src/common/up_vfork.c b/nuttx/arch/arm/src/common/up_vfork.c
new file mode 100644
index 000000000..3b653e317
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_vfork.c
@@ -0,0 +1,233 @@
+/****************************************************************************
+ * arch/arm/src/common/up_vfork.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "up_vfork.h"
+#include "os_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* ARM requires at least a 4-byte stack alignment. For use with EABI and
+ * floating point, the stack must be aligned to 8-byte addresses.
+ */
+
+#ifndef CONFIG_STACK_ALIGNMENT
+
+/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you
+ * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly!
+ */
+
+# ifdef __ARM_EABI__
+# define CONFIG_STACK_ALIGNMENT 8
+# else
+# define CONFIG_STACK_ALIGNMENT 4
+# endif
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_vfork
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() collects context information and
+ * transfers control up up_vfork().
+ * 2) up_vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * task_vforkabort() may be called if an error occurs between steps 3 and 6.
+ *
+ * Input Paremeters:
+ * context - Caller context information saved by vfork()
+ *
+ * Return:
+ * Upon successful completion, vfork() returns 0 to the child process and
+ * returns the process ID of the child process to the parent process.
+ * Otherwise, -1 is returned to the parent, no child process is created,
+ * and errno is set to indicate the error.
+ *
+ ****************************************************************************/
+
+pid_t up_vfork(const struct vfork_s *context)
+{
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+ _TCB *child;
+ size_t stacksize;
+ uint32_t newsp;
+ uint32_t newfp;
+ uint32_t stackutil;
+ int ret;
+
+ svdbg("r4:%08x r5:%08x r6:%08x r7:%08x\n",
+ context->r4, context->r5, context->r6, context->r7);
+ svdbg("r8:%08x r9:%08x r10:%08x\n",
+ context->r8, context->r9, context->r10);
+ svdbg("fp:%08x sp:%08x lr:%08x\n",
+ context->fp, context->sp, context->lr);
+
+ /* Allocate and initialize a TCB for the child task. */
+
+ child = task_vforksetup((start_t)(context->lr & ~1));
+ if (!child)
+ {
+ sdbg("task_vforksetup failed\n");
+ return (pid_t)ERROR;
+ }
+
+ svdbg("Parent=%p Child=%p\n", parent, child);
+
+ /* Get the size of the parent task's stack. Due to alignment operations,
+ * the adjusted stack size may be smaller than the stack size originally
+ * requrested.
+ */
+
+ stacksize = parent->adj_stack_size + CONFIG_STACK_ALIGNMENT - 1;
+
+ /* Allocate the stack for the TCB */
+
+ ret = up_create_stack(child, stacksize);
+ if (ret != OK)
+ {
+ sdbg("up_create_stack failed: %d\n", ret);
+ task_vforkabort(child, -ret);
+ return (pid_t)ERROR;
+ }
+
+ /* How much of the parent's stack was utilized? The ARM uses
+ * a push-down stack so that the current stack pointer should
+ * be lower than the initial, adjusted stack pointer. The
+ * stack usage should be the difference between those two.
+ */
+
+ DEBUGASSERT((uint32_t)parent->adj_stack_ptr > context->sp);
+ stackutil = (uint32_t)parent->adj_stack_ptr - context->sp;
+
+ svdbg("stacksize:%d stackutil:%d\n", stacksize, stackutil);
+
+ /* Make some feeble effort to perserve the stack contents. This is
+ * feeble because the stack surely contains invalid pointers and other
+ * content that will not work in the child context. However, if the
+ * user follows all of the caveats of vfor() usage, even this feeble
+ * effort is overkill.
+ */
+
+ newsp = (uint32_t)child->adj_stack_ptr - stackutil;
+ memcpy((void *)newsp, (const void *)context->sp, stackutil);
+
+ /* Was there a frame pointer in place before? */
+
+ if (context->fp <= (uint32_t)parent->adj_stack_ptr &&
+ context->fp >= (uint32_t)parent->adj_stack_ptr - stacksize)
+ {
+ uint32_t frameutil = (uint32_t)parent->adj_stack_ptr - context->fp;
+ newfp = (uint32_t)child->adj_stack_ptr - frameutil;
+ }
+ else
+ {
+ newfp = context->fp;
+ }
+
+ svdbg("Old stack base:%08x SP:%08x FP:%08x\n",
+ parent->adj_stack_ptr, context->sp, context->fp);
+ svdbg("New stack base:%08x SP:%08x FP:%08x\n",
+ child->adj_stack_ptr, newsp, newfp);
+
+ /* Update the stack pointer, frame pointer, and volatile registers. When
+ * the child TCB was initialized, all of the values were set to zero.
+ * up_initial_state() altered a few values, but the return value in R0
+ * should be cleared to zero, providing the indication to the newly started
+ * child thread.
+ */
+
+ child->xcp.regs[REG_R4] = context->r4; /* Volatile register r4 */
+ child->xcp.regs[REG_R5] = context->r5; /* Volatile register r5 */
+ child->xcp.regs[REG_R6] = context->r6; /* Volatile register r6 */
+ child->xcp.regs[REG_R7] = context->r7; /* Volatile register r7 */
+ child->xcp.regs[REG_R8] = context->r8; /* Volatile register r8 */
+ child->xcp.regs[REG_R9] = context->r9; /* Volatile register r9 */
+ child->xcp.regs[REG_R10] = context->r10; /* Volatile register r10 */
+ child->xcp.regs[REG_FP] = newfp; /* Frame pointer */
+ child->xcp.regs[REG_SP] = newsp; /* Stack pointer */
+
+ /* And, finally, start the child task. On a failure, task_vforkstart()
+ * will discard the TCB by calling task_vforkabort().
+ */
+
+ return task_vforkstart(child);
+}
diff --git a/nuttx/arch/arm/src/common/up_vfork.h b/nuttx/arch/arm/src/common/up_vfork.h
new file mode 100644
index 000000000..97edf9aaa
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_vfork.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * arch/arm/src/common/up_vfork.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_ARM_VFORK_H
+#define __ARCH_ARM_SRC_ARM_VFORK_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define VFORK_R4_OFFSET (0*4) /* Volatile register r4 */
+#define VFORK_R5_OFFSET (1*4) /* Volatile register r5 */
+#define VFORK_R6_OFFSET (2*4) /* Volatile register r6 */
+#define VFORK_R7_OFFSET (3*4) /* Volatile register r7 */
+#define VFORK_R8_OFFSET (4*4) /* Volatile register r8 */
+#define VFORK_R9_OFFSET (5*4) /* Volatile register r9 */
+#define VFORK_R10_OFFSET (6*4) /* Volatile register r10 */
+
+#define VFORK_FP_OFFSET (7*4) /* Frame pointer */
+#define VFORK_SP_OFFSET (8*4) /* Stack pointer*/
+#define VFORK_LR_OFFSET (9*4) /* Return address*/
+
+#define VFORK_SIZEOF (10*4)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+struct vfork_s
+{
+ /* CPU registers */
+
+ uint32_t r4; /* Volatile register r4 */
+ uint32_t r5; /* Volatile register r5 */
+ uint32_t r6; /* Volatile register r6 */
+ uint32_t r7; /* Volatile register r7 */
+ uint32_t r8; /* Volatile register r8 */
+ uint32_t r9; /* Volatile register r9 */
+ uint32_t r10; /* Volatile register r10 */
+
+ uint32_t fp; /* Frame pointer */
+ uint32_t sp; /* Stack pointer*/
+ uint32_t lr; /* Return address*/
+
+ /* Floating point registers (not yet) */
+};
+#endif
+
+#endif /* __ARCH_ARM_SRC_ARM_VFORK_H */
diff --git a/nuttx/arch/arm/src/stm32/Kconfig b/nuttx/arch/arm/src/stm32/Kconfig
index 99dde3209..41724be2d 100644
--- a/nuttx/arch/arm/src/stm32/Kconfig
+++ b/nuttx/arch/arm/src/stm32/Kconfig
@@ -457,32 +457,38 @@ config STM32_USART1
bool "USART1"
default n
select ARCH_HAVE_USART1
+ select STM32_USART
config STM32_USART2
bool "USART2"
default n
select ARCH_HAVE_USART2
+ select STM32_USART
config STM32_USART3
bool "USART3"
default n
select ARCH_HAVE_USART3
+ select STM32_USART
config STM32_UART4
bool "UART4"
default n
select ARCH_HAVE_UART4
+ select STM32_USART
config STM32_UART5
bool "UART5"
default n
select ARCH_HAVE_UART5
+ select STM32_USART
config STM32_USART6
bool "USART6"
default n
depends on STM32_STM32F20XX || STM32_STM32F40XX
select ARCH_HAVE_USART6
+ select STM32_USART
config STM32_USB
bool "USB Device"
@@ -1804,8 +1810,11 @@ config STM32_TIM14_DAC2
endchoice
+config STM32_USART
+ bool
+
menu "U[S]ART Configuration"
- depends on STM32_USART1 || STM32_USART2 || STM32_USART3 || STM32_USART4 || STM32_USART5 || STM32_USART6
+ depends on STM32_USART
config USART1_RS485
bool "RS-485 on USART1"
@@ -1968,6 +1977,14 @@ config SERIAL_TERMIOS
endmenu
+config STM32_USART_SINGLEWIRE
+ bool "Single Wire Support"
+ default n
+ depends on STM32_USART
+ ---help---
+ Enable single wire UART support. The option enables support for the
+ TIOCSSINGLEWIRE ioctl in the STM32 serial driver.
+
menu "SPI Configuration"
depends on STM32_SPI
diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs
index baa751c7d..940ff6517 100644
--- a/nuttx/arch/arm/src/stm32/Make.defs
+++ b/nuttx/arch/arm/src/stm32/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# arch/arm/src/stm32/Make.defs
#
-# Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -39,15 +39,16 @@ else
HEAD_ASRC = stm32_vectors.S
endif
-CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S
+CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S \
+ vfork.S
CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c \
up_createstack.c up_mdelay.c up_udelay.c up_exit.c \
up_initialize.c up_initialstate.c up_interruptcontext.c \
up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \
up_releasepending.c up_releasestack.c up_reprioritizertr.c \
up_schedulesigaction.c up_sigdeliver.c up_systemreset.c \
- up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c up_svcall.c \
- up_stackcheck.c
+ up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c \
+ up_svcall.c up_stackcheck.c up_vfork.c
ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
CMN_ASRCS += up_exception.S
diff --git a/nuttx/arch/arm/src/stm32/chip.h b/nuttx/arch/arm/src/stm32/chip.h
index 3fac597ef..41a87feae 100644
--- a/nuttx/arch/arm/src/stm32/chip.h
+++ b/nuttx/arch/arm/src/stm32/chip.h
@@ -1,7 +1,7 @@
/************************************************************************************
* arch/arm/src/stm32/chip.h
*
- * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/arch/arm/src/stm32/stm32.h b/nuttx/arch/arm/src/stm32/stm32.h
index 44a23aece..95fd19779 100644
--- a/nuttx/arch/arm/src/stm32/stm32.h
+++ b/nuttx/arch/arm/src/stm32/stm32.h
@@ -68,12 +68,6 @@
# undef CONFIG_DEBUG_QENCODER
#endif
-/* NVIC priority levels *************************************************************/
-
-#define NVIC_SYSH_PRIORITY_MIN 0xff /* All bits set in minimum priority */
-#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */
-#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */
-
/* Peripherals **********************************************************************/
#include "chip.h"
diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.c b/nuttx/arch/arm/src/stm32/stm32_flash.c
index 83fcc6172..20b0cfe10 100644
--- a/nuttx/arch/arm/src/stm32/stm32_flash.c
+++ b/nuttx/arch/arm/src/stm32/stm32_flash.c
@@ -35,7 +35,7 @@
/* Provides standard flash access functions, to be used by the flash mtd driver.
* The interface is defined in the include/nuttx/progmem.h
- *
+ *
* Requirements during write/erase operations on FLASH:
* - HSI must be ON.
* - Low Power Modes are not permitted during write/erase
@@ -80,7 +80,7 @@ void stm32_flash_unlock(void)
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
{
/* Unlock sequence */
-
+
putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
}
@@ -112,6 +112,11 @@ uint16_t up_progmem_pagesize(uint16_t page)
int up_progmem_getpage(uint32_t addr)
{
+ if (addr >= STM32_FLASH_BASE)
+ {
+ addr -= STM32_FLASH_BASE;
+ }
+
if (addr >= STM32_FLASH_SIZE)
{
return -EFAULT;
@@ -131,14 +136,14 @@ int up_progmem_erasepage(uint16_t page)
}
/* Get flash ready and begin erasing single page */
-
+
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
{
return -EPERM;
}
-
+
stm32_flash_unlock();
-
+
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER);
putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR);
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
@@ -146,10 +151,10 @@ int up_progmem_erasepage(uint16_t page)
while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0);
-
+
/* Verify */
-
- for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
count; count-=4, addr += 4)
{
if (getreg32(addr) != 0xffffffff)
@@ -173,8 +178,8 @@ int up_progmem_ispageerased(uint16_t page)
}
/* Verify */
-
- for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
count; count--, addr++)
{
if (getreg8(addr) != 0xff)
@@ -200,6 +205,11 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
/* Check for valid address range */
+ if (addr >= STM32_FLASH_BASE)
+ {
+ addr -= STM32_FLASH_BASE;
+ }
+
if ((addr+count) >= STM32_FLASH_SIZE)
{
return -EFAULT;
@@ -213,10 +223,10 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
}
stm32_flash_unlock();
-
+
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
-
- for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2)
+
+ for (addr += STM32_FLASH_BASE; count; count-=2, hword++, addr+=2)
{
/* Write half-word and wait to complete */
@@ -237,7 +247,6 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
return -EIO;
}
-
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
diff --git a/nuttx/arch/arm/src/stm32/stm32_irq.c b/nuttx/arch/arm/src/stm32/stm32_irq.c
index 36a5cf5fa..a952c2486 100644
--- a/nuttx/arch/arm/src/stm32/stm32_irq.c
+++ b/nuttx/arch/arm/src/stm32/stm32_irq.c
@@ -2,7 +2,7 @@
* arch/arm/src/stm32/stm32_irq.c
* arch/arm/src/chip/stm32_irq.c
*
- * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -195,6 +195,29 @@ static int stm32_reserved(int irq, FAR void *context)
#endif
/****************************************************************************
+ * Name: stm32_prioritize_syscall
+ *
+ * Description:
+ * Set the priority of an exception. This function may be needed
+ * internally even if support for prioritized interrupts is not enabled.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+static inline void stm32_prioritize_syscall(int priority)
+{
+ uint32_t regval;
+
+ /* SVCALL is system handler 11 */
+
+ regval = getreg32(NVIC_SYSH8_11_PRIORITY);
+ regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK;
+ regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT);
+ putreg32(regval, NVIC_SYSH8_11_PRIORITY);
+}
+#endif
+
+/****************************************************************************
* Name: stm32_irqinfo
*
* Description:
@@ -335,6 +358,9 @@ void up_irqinitialize(void)
#ifdef CONFIG_ARCH_IRQPRIO
/* up_prioritize_irq(STM32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */
#endif
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ stm32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY);
+#endif
/* If the MPU is enabled, then attach and enable the Memory Management
* Fault handler.
@@ -365,8 +391,7 @@ void up_irqinitialize(void)
/* And finally, enable interrupts */
- setbasepri(NVIC_SYSH_PRIORITY_MAX);
- irqrestore(0);
+ irqenable();
#endif
}
@@ -451,15 +476,28 @@ int up_prioritize_irq(int irq, int priority)
uint32_t regval;
int shift;
- DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN);
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS &&
+ priority >= NVIC_SYSH_DISABLE_PRIORITY &&
+ priority <= NVIC_SYSH_PRIORITY_MIN);
+#else
+ DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS &&
+ (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN);
+#endif
if (irq < STM32_IRQ_INTERRUPTS)
{
- irq -= 4;
+ /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority
+ * registers (0-3 are invalid)
+ */
+
regaddr = NVIC_SYSH_PRIORITY(irq);
+ irq -= 4;
}
else
{
+ /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */
+
irq -= STM32_IRQ_INTERRUPTS;
regaddr = NVIC_IRQ_PRIORITY(irq);
}
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c
index aa46a8987..6aaecb2d9 100644
--- a/nuttx/arch/arm/src/stm32/stm32_serial.c
+++ b/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/stm32/stm32_serial.c
*
- * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -79,22 +79,22 @@
#if SERIAL_HAVE_DMA
-/* Verify that DMA has been enabled an the DMA channel has been defined.
- * NOTE: These assignments may only be true for the F4.
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+/* Verify that DMA has been enabled and the DMA channel has been defined.
*/
-# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA)
-# ifndef CONFIG_STM32_DMA2
-# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2
+# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA)
+# ifndef CONFIG_STM32_DMA2
+# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2
+# endif
# endif
-# endif
-# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \
+# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \
defined(CONFIG_UART4_RXDMA) || defined(CONFIG_UART5_RXDMA)
-# ifndef CONFIG_STM32_DMA1
-# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1
+# ifndef CONFIG_STM32_DMA1
+# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1
+# endif
# endif
-# endif
/* Currently RS-485 support cannot be enabled when RXDMA is in use due to lack
* of testing - RS-485 support was developed on STM32F1x
@@ -114,28 +114,52 @@
* the following in the board.h file.
*/
-# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
-# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
-# endif
+# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
+# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
+# endif
-# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
-# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
-# endif
+# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
+# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
+# endif
-# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
-# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
-# endif
+# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
+# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
+# endif
-# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX)
-# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
-# endif
+# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX)
+# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
+# endif
-# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX)
-# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
-# endif
+# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX)
+# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
+# endif
+
+# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX)
+# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)"
+# endif
+
+# elif defined(CONFIG_STM32_STM32F10XX)
+
+# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \
+ defined(CONFIG_USART3_RXDMA)
+# ifndef CONFIG_STM32_DMA1
+# error STM32 USART1/2/3 receive DMA requires CONFIG_STM32_DMA1
+# endif
+# endif
+
+# if defined(CONFIG_UART4_RXDMA)
+# ifndef CONFIG_STM32_DMA2
+# error STM32 USART4 receive DMA requires CONFIG_STM32_DMA2
+# endif
+# endif
+
+/* There are no optional DMA channel assignments for the F1 */
+
+# define DMAMAP_USART1_RX DMACHAN_USART1_RX
+# define DMAMAP_USART2_RX DMACHAN_USART2_RX
+# define DMAMAP_USART3_RX DMACHAN_USART3_RX
+# define DMAMAP_UART4_RX DMACHAN_USART4_RX
-# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX)
-# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)"
# endif
/* The DMA buffer size when using RX DMA to emulate a FIFO.
@@ -169,6 +193,27 @@
# error "Unknown STM32 DMA"
# endif
+/* DMA control word */
+
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SERIAL_DMA_CONTROL_WORD \
+ (DMA_SCR_DIR_P2M | \
+ DMA_SCR_CIRC | \
+ DMA_SCR_MINC | \
+ DMA_SCR_PSIZE_8BITS | \
+ DMA_SCR_MSIZE_8BITS | \
+ CONFIG_USART_DMAPRIO | \
+ DMA_SCR_PBURST_SINGLE | \
+ DMA_SCR_MBURST_SINGLE)
+# else
+# define SERIAL_DMA_CONTROL_WORD \
+ (DMA_CCR_CIRC | \
+ DMA_CCR_MINC | \
+ DMA_CCR_PSIZE_8BITS | \
+ DMA_CCR_MSIZE_8BITS | \
+ CONFIG_USART_DMAPRIO)
+# endif
+
#endif
/* Power management definitions */
@@ -1115,14 +1160,7 @@ static int up_dma_setup(struct uart_dev_s *dev)
priv->usartbase + STM32_USART_DR_OFFSET,
(uint32_t)priv->rxfifo,
RXDMA_BUFFER_SIZE,
- DMA_SCR_DIR_P2M |
- DMA_SCR_CIRC |
- DMA_SCR_MINC |
- DMA_SCR_PSIZE_8BITS |
- DMA_SCR_MSIZE_8BITS |
- CONFIG_USART_DMAPRIO |
- DMA_SCR_PBURST_SINGLE |
- DMA_SCR_MBURST_SINGLE);
+ SERIAL_DMA_CONTROL_WORD);
/* Reset our DMA shadow pointer to match the address just
* programmed above.
@@ -1401,6 +1439,31 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
}
break;
+#ifdef CONFIG_STM32_USART_SINGLEWIRE
+ case TIOCSSINGLEWIRE:
+ {
+ /* Change the TX port to be open-drain/push-pull and enable/disable
+ * half-duplex mode.
+ */
+
+ uint32_t cr = up_serialin(priv, STM32_USART_CR3_OFFSET);
+
+ if (arg == SER_SINGLEWIRE_ENABLED)
+ {
+ stm32_configgpio(priv->tx_gpio | GPIO_OPENDRAIN);
+ cr |= USART_CR3_HDSEL;
+ }
+ else
+ {
+ stm32_configgpio(priv->tx_gpio | GPIO_PUSHPULL);
+ cr &= ~USART_CR3_HDSEL;
+ }
+
+ up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
+ }
+ break;
+#endif
+
#ifdef CONFIG_SERIAL_TERMIOS
case TCGETS:
{
diff --git a/nuttx/arch/arm/src/stm32/stm32_uart.h b/nuttx/arch/arm/src/stm32/stm32_uart.h
index 8ff6a9975..a26ea2009 100644
--- a/nuttx/arch/arm/src/stm32/stm32_uart.h
+++ b/nuttx/arch/arm/src/stm32/stm32_uart.h
@@ -140,12 +140,9 @@
# undef HAVE_CONSOLE
#endif
-/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration.
- * Furthermore, DMA support is currently only implemented for the F4 (but could be
- * extended to the F1 and F2 with a little effort in the DMA code.
- */
+/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration */
-#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA) || !defined(CONFIG_STM32_STM32F40XX)
+#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA)
# undef CONFIG_USART1_RXDMA
# undef CONFIG_USART2_RXDMA
# undef CONFIG_USART3_RXDMA
diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S
index ab4dadb77..c9b62d762 100644
--- a/nuttx/arch/arm/src/stm32/stm32_vectors.S
+++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S
@@ -2,7 +2,7 @@
* arch/arm/src/stm32/stm32_vectors.S
* arch/arm/src/chip/stm32_vectors.S
*
- * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -235,7 +235,11 @@ stm32_common:
mov r2, r1 /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ mrs r3, basepri /* R3=Current BASEPRI setting */
+#else
mrs r3, primask /* R3=Current PRIMASK setting */
+#endif
#ifdef CONFIG_ARCH_FPU
/* Skip over the block of memory reserved for floating pointer register save.
@@ -248,8 +252,8 @@ stm32_common:
#endif
/* Save the the remaining registers on the stack after the registers pushed
- * by the exception handling logic. r2=SP and r3=primask, r4-r11,r14=register
- * values.
+ * by the exception handling logic. r2=SP and r3=primask or basepri, r4-r11,
+ * r14=register values.
*/
#ifdef CONFIG_NUTTX_KERNEL
@@ -349,7 +353,7 @@ stm32_common:
* Here:
* r1 = Address on the target thread's stack position at the start of
* the registers saved by hardware
- * r3 = primask
+ * r3 = primask or basepri
* r4-r11 = restored register values
*/
2:
@@ -375,7 +379,12 @@ stm32_common:
/* Restore the interrupt state */
+#ifdef CONFIG_ARMV7M_USEBASEPRI
+ msr basepri, r3 /* Restore interrupts priority masking*/
+ cpsie i /* Re-enable interrupts */
+#else
msr primask, r3 /* Restore interrupts */
+#endif
/* Always return with R14 containing the special value that will: (1)
* return to thread mode, and (2) continue to use the MSP
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
index 89b279bea..13324b8ac 100644
--- a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
@@ -303,13 +303,13 @@ static int stm32_dmainterrupt(int irq, void *context)
}
dmach = &g_dma[chndx];
- /* Get the interrupt status (for this channel only) -- not currently used */
+ /* Get the interrupt status (for this channel only) */
isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
- /* Disable the DMA channel */
+ /* Clear the interrupts we are handling */
- stm32_dmachandisable(dmach);
+ dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, isr);
/* Invoke the callback */
@@ -528,14 +528,34 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
ccr |= DMA_CCR_EN;
- /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
- * set and an interrupt is generated if the Half-Transfer Interrupt Enable
- * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
- * (TCIF) is set and an interrupt is generated if the Transfer Complete
- * Interrupt Enable bit (TCIE) is set.
+ /* In normal mode, interrupt at either half or full completion. In circular mode,
+ * always interrupt on buffer wrap, and optionally interrupt at the halfway point.
*/
- ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE));
+ if ((ccr & DMA_CCR_CIRC) == 0)
+ {
+ /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
+ * set and an interrupt is generated if the Half-Transfer Interrupt Enable
+ * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
+ * (TCIF) is set and an interrupt is generated if the Transfer Complete
+ * Interrupt Enable bit (TCIE) is set.
+ */
+
+ ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE));
+
+ }
+ else
+ {
+ /* In nonstop mode, when the transfer completes it immediately resets
+ * and starts again. The transfer-complete interrupt is thus always
+ * enabled, and the half-complete interrupt can be used in circular
+ * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when one of the two buffers is full.
+ */
+
+ ccr |= (half ? DMA_CCR_HTIE : 0) | DMA_CCR_TCIE | DMA_CCR_TEIE;
+ }
+
dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, ccr);
}
@@ -559,6 +579,24 @@ void stm32_dmastop(DMA_HANDLE handle)
}
/****************************************************************************
+ * Name: stm32_dmaresidual
+ *
+ * Description:
+ * Returns the number of bytes remaining to be transferred
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+size_t stm32_dmaresidual(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+
+ return dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET);
+}
+
+/****************************************************************************
* Name: stm32_dmasample
*
* Description:
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
index dcbbf1856..40fce8cb5 100644
--- a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
@@ -94,7 +94,6 @@ struct stm32_dma_s
uint8_t irq; /* DMA stream IRQ number */
uint8_t shift; /* ISR/IFCR bit shift value */
uint8_t channel; /* DMA channel number (0-7) */
- bool nonstop; /* Stream is configured in a non-stopping mode. */
sem_t sem; /* Used to wait for DMA channel to become available */
uint32_t base; /* DMA register channel base address */
dma_callback_t callback; /* Callback invoked when the DMA completes */
@@ -728,7 +727,6 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
DMA_SCR_DBM|DMA_SCR_CIRC|
DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
regval |= scr;
- dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
}
@@ -764,7 +762,12 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
scr |= DMA_SCR_EN;
- if (!dmast->nonstop)
+ /* In normal mode, interrupt at either half or full completion. In circular
+ * and double-buffered modes, always interrupt on buffer wrap, and optionally
+ * interrupt at the halfway point.
+ */
+
+ if ((scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) == 0)
{
/* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
* set and an interrupt is generated if the Half-Transfer Interrupt Enable
@@ -777,7 +780,7 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
}
else
{
- /* In nonstop mode, when the transfer completes it immediately resets
+ /* In non-stop modes, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
* mode to determine when the buffer is half-full, or in double-buffered
diff --git a/nuttx/binfmt/Kconfig b/nuttx/binfmt/Kconfig
index 495bd050f..8d6c0bb18 100644
--- a/nuttx/binfmt/Kconfig
+++ b/nuttx/binfmt/Kconfig
@@ -49,6 +49,20 @@ if ELF
source binfmt/libelf/Kconfig
endif
+config BUILTIN
+ bool "Support Builtin Applications"
+ default n
+ ---help---
+ Enable support for builtin applications. This features assigns a string
+ name to an application and in addition if FS_BINFS is defined, retaining
+ those names in a file system from which they can be executed. This feature
+ is also the underlying requirement to support built-in applications in the
+ NuttShell (NSH).
+
+if BUILTIN
+source binfmt/libbuiltin/Kconfig
+endif
+
endif
config PIC
diff --git a/nuttx/binfmt/Makefile b/nuttx/binfmt/Makefile
index 8ec0d877c..2f692beb1 100644
--- a/nuttx/binfmt/Makefile
+++ b/nuttx/binfmt/Makefile
@@ -1,7 +1,7 @@
############################################################################
# nxflat/Makefile
#
-# Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,10 @@ ifeq ($(CONFIG_BINFMT_EXEPATH),y)
BINFMT_CSRCS += binfmt_exepath.c
endif
+ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
+BINFMT_CSRCS += binfmt_schedunload.c
+endif
+
# Symbol table source files
BINFMT_CSRCS += symtab_findbyname.c symtab_findbyvalue.c
@@ -65,6 +69,7 @@ DEPPATH = --dep-path .
include libnxflat$(DELIM)Make.defs
include libelf$(DELIM)Make.defs
+include libbuiltin$(DELIM)Make.defs
BINFMT_AOBJS = $(BINFMT_ASRCS:.S=$(OBJEXT))
BINFMT_COBJS = $(BINFMT_CSRCS:.c=$(OBJEXT))
diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c
index 60e8d8efd..4226b6cfc 100644
--- a/nuttx/binfmt/binfmt_exec.c
+++ b/nuttx/binfmt/binfmt_exec.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_exec.c
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -40,10 +40,10 @@
#include <nuttx/config.h>
#include <string.h>
-#include <sched.h>
#include <debug.h>
#include <errno.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h"
@@ -75,7 +75,9 @@
*
* Description:
* This is a convenience function that wraps load_ and exec_module into
- * one call.
+ * one call. If CONFIG_SCHED_ONEXIT is also defined, this function will
+ * automatically call schedule_unload() to unload the module when task
+ * exits.
*
* Input Parameter:
* filename - Fulll path to the binary to be loaded
@@ -85,7 +87,7 @@
*
* Returned Value:
* This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
+ * It returns the PID of the exec'ed module. On failure, it returns
* -1 (ERROR) and sets errno appropriately.
*
****************************************************************************/
@@ -93,9 +95,71 @@
int exec(FAR const char *filename, FAR const char **argv,
FAR const struct symtab_s *exports, int nexports)
{
+#ifdef CONFIG_SCHED_ONEXIT
+ FAR struct binary_s *bin;
+ int pid;
+ int ret;
+
+ /* Allocate the load information */
+
+ bin = (FAR struct binary_s *)kzalloc(sizeof(struct binary_s));
+ if (!bin)
+ {
+ set_errno(ENOMEM);
+ return ERROR;
+ }
+
+ /* Load the module into memory */
+
+ bin->filename = filename;
+ bin->exports = exports;
+ bin->nexports = nexports;
+
+ ret = load_module(bin);
+ if (ret < 0)
+ {
+ bdbg("ERROR: Failed to load program '%s'\n", filename);
+ kfree(bin);
+ return ERROR;
+ }
+
+ /* Disable pre-emption so that the executed module does
+ * not return until we get a chance to connect the on_exit
+ * handler.
+ */
+
+ sched_lock();
+
+ /* Then start the module */
+
+ pid = exec_module(bin);
+ if (pid < 0)
+ {
+ bdbg("ERROR: Failed to execute program '%s'\n", filename);
+ sched_unlock();
+ unload_module(bin);
+ kfree(bin);
+ return ERROR;
+ }
+
+ /* Set up to unload the module (and free the binary_s structure)
+ * when the task exists.
+ */
+
+ ret = schedule_unload(pid, bin);
+ if (ret < 0)
+ {
+ bdbg("ERROR: Failed to schedul unload '%s'\n", filename);
+ }
+
+ sched_unlock();
+ return pid;
+#else
struct binary_s bin;
int ret;
+ /* Load the module into memory */
+
memset(&bin, 0, sizeof(struct binary_s));
bin.filename = filename;
bin.exports = exports;
@@ -108,7 +172,9 @@ int exec(FAR const char *filename, FAR const char **argv,
return ERROR;
}
- ret = exec_module(&bin, 50);
+ /* Then start the module */
+
+ ret = exec_module(&bin);
if (ret < 0)
{
bdbg("ERROR: Failed to execute program '%s'\n", filename);
@@ -116,7 +182,10 @@ int exec(FAR const char *filename, FAR const char **argv,
return ERROR;
}
+ /* TODO: How does the module get unloaded in this case? */
+
return ret;
+#endif
}
#endif /* CONFIG_BINFMT_DISABLE */
diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c
index 400451c40..afa445abb 100644
--- a/nuttx/binfmt/binfmt_execmodule.c
+++ b/nuttx/binfmt/binfmt_execmodule.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_execmodule.c
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
#include <errno.h>
#include <nuttx/arch.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h>
#include "os_internal.h"
@@ -143,7 +144,7 @@ static inline int exec_ctors(FAR const struct binary_s *binp)
*
****************************************************************************/
-int exec_module(FAR const struct binary_s *binp, int priority)
+int exec_module(FAR const struct binary_s *binp)
{
FAR _TCB *tcb;
#ifndef CONFIG_CUSTOM_STACK
@@ -167,7 +168,7 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Allocate a TCB for the new task. */
- tcb = (FAR _TCB*)zalloc(sizeof(_TCB));
+ tcb = (FAR _TCB*)kzalloc(sizeof(_TCB));
if (!tcb)
{
err = ENOMEM;
@@ -177,7 +178,7 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Allocate the stack for the new task */
#ifndef CONFIG_CUSTOM_STACK
- stack = (FAR uint32_t*)malloc(binp->stacksize);
+ stack = (FAR uint32_t*)kmalloc(binp->stacksize);
if (!tcb)
{
err = ENOMEM;
@@ -186,12 +187,12 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Initialize the task */
- ret = task_init(tcb, binp->filename, priority, stack,
+ ret = task_init(tcb, binp->filename, binp->priority, stack,
binp->stacksize, binp->entrypt, binp->argv);
#else
/* Initialize the task */
- ret = task_init(tcb, binp->filename, priority, stack,
+ ret = task_init(tcb, binp->filename, binp->priority, stack,
binp->entrypt, binp->argv);
#endif
if (ret < 0)
@@ -201,6 +202,9 @@ int exec_module(FAR const struct binary_s *binp, int priority)
goto errout_with_stack;
}
+ /* Note that tcb->flags are not modified. 0=normal task */
+ /* tcb->flags |= TCB_FLAG_TTYPE_TASK; */
+
/* Add the D-Space address as the PIC base address. By convention, this
* must be the first allocated address space.
*/
@@ -257,14 +261,14 @@ errout_with_stack:
#ifndef CONFIG_CUSTOM_STACK
tcb->stack_alloc_ptr = NULL;
sched_releasetcb(tcb);
- free(stack);
+ kfree(stack);
#else
sched_releasetcb(tcb);
#endif
goto errout;
errout_with_tcb:
- free(tcb);
+ kfree(tcb);
errout:
errno = err;
bdbg("returning errno: %d\n", err);
diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c
index 112a6b35b..322ed2c48 100644
--- a/nuttx/binfmt/binfmt_loadmodule.c
+++ b/nuttx/binfmt/binfmt_loadmodule.c
@@ -67,6 +67,41 @@
****************************************************************************/
/****************************************************************************
+ * Name: load_default_priority
+ *
+ * Description:
+ * Set the default priority of the module to be loaded. This may be
+ * changed (1) by the actions of the binary format's load() method if
+ * the binary format contains priority informaition, or (2) by the user
+ * between calls to load_module() and exec_module().
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; Otherwise, -1 (ERROR) is returned and
+ * the errno variable is set appropriately.
+ *
+ ****************************************************************************/
+
+static int load_default_priority(FAR struct binary_s *bin)
+{
+ struct sched_param param;
+ int ret;
+
+ /* Get the priority of this thread */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ bdbg("ERROR: sched_getparam failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Save that as the priority of child thread */
+
+ bin->priority = param.sched_priority;
+ return ret;
+}
+
+/****************************************************************************
* Name: load_absmodule
*
* Description:
@@ -145,6 +180,16 @@ int load_module(FAR struct binary_s *bin)
if (bin && bin->filename)
#endif
{
+ /* Set the default priority of the new program. */
+
+ ret = load_default_priority(bin);
+ if (ret < 0)
+ {
+ /* The errno is already set in this case */
+
+ return ERROR;
+ }
+
/* Were we given a relative path? Or an absolute path to the file to
* be loaded? Absolute paths start with '/'.
*/
diff --git a/nuttx/binfmt/binfmt_schedunload.c b/nuttx/binfmt/binfmt_schedunload.c
new file mode 100644
index 000000000..972d17963
--- /dev/null
+++ b/nuttx/binfmt/binfmt_schedunload.c
@@ -0,0 +1,333 @@
+/****************************************************************************
+ * binfmt/binfmt_schedunload.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/binfmt.h>
+
+#include "binfmt_internal.h"
+
+#if !defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+FAR struct binary_s *g_unloadhead;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: unload_list_add
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will
+ * manage instances of struct binary_s allocated with kmalloc. It
+ * will keep the binary data in a link list and when SIGCHLD is received
+ * (meaning that the task has exit'ed, schedul_unload() will find the
+ * data, unload the module, and free the structure.
+ *
+ * This function will add one structure to the linked list
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ * bin - This structure must have been allocated with kmalloc() and must
+ * persist until the task unloads
+
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void unload_list_add(pid_t pid, FAR struct binary_s *bin)
+{
+ irqstate_t flags;
+
+ /* Save the PID in the structure so that we recover it later */
+
+ bin->pid = pid;
+
+ /* Disable deliver of any signals while we muck with the list. The graceful
+ * way to do this would be block delivery of SIGCHLD would be with
+ * sigprocmask. Here we do it the quick'n'dirty way by just disabling
+ * interrupts.
+ */
+
+ flags = irqsave();
+ bin->flink = g_unloadhead;
+ g_unloadhead = bin;
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: unload_list_remove
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will
+ * manage instances of struct binary_s allocated with kmalloc. It
+ * will keep the binary data in a link list and when SIGCHLD is received
+ * (meaning that the task has exit'ed, schedul_unload() will find the
+ * data, unload the module, and free the structure.
+ *
+ * This function will remove one structure to the linked list
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ *
+ * Returned Value:
+ * On success, the load structure is returned. NULL is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static FAR struct binary_s *unload_list_remove(pid_t pid)
+{
+ FAR struct binary_s *curr;
+ FAR struct binary_s *prev;
+
+ /* Note the asymmetry. We do not have to disable interrupts here because
+ * the main thread cannot run while we are in the interrupt handler. Here,
+ * it should be sufficient to disable pre-emption so that no other thread
+ * can run.
+ */
+
+ sched_lock();
+
+ /* Find the structure in the unload list with the matching PID */
+
+ for (prev = NULL, curr = g_unloadhead;
+ curr && (curr->pid != pid);
+ prev = curr, curr = curr->flink);
+
+ /* Did we find it? It must be there. Hmmm.. we should probably ASSERT if
+ * we do not!
+ */
+
+ if (curr)
+ {
+ /* Was there another entry before this one? */
+
+ if (prev)
+ {
+ /* Yes.. remove the current entry from after the previous entry */
+
+ prev->flink = curr->flink;
+ }
+ else
+ {
+ /* No.. remove the current entry from the head of the list */
+
+ g_unloadhead = curr->flink;
+ }
+
+ /* Nullify the forward link ... superstitious */
+
+ curr->flink = NULL;
+ }
+
+ sched_unlock();
+ return curr;
+}
+
+/****************************************************************************
+ * Name: unload_callback
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called to
+ * automatically unload the module when task exits. It assumes that
+ * bin was allocated with kmalloc() or friends and will also automatically
+ * free the structure with kfree() when the task exists.
+ *
+ * Input Parameter:
+ * pid - The ID of the task that just exited
+ * arg - A reference to the load structure cast to FAR void *
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void unload_callback(int signo, siginfo_t *info, void *ucontext)
+{
+ FAR struct binary_s *bin;
+ int ret;
+
+ /* Sanity checking */
+
+ if (!info || signo != SIGCHLD)
+ {
+ blldbg("ERROR:Bad signal callback: signo=%d info=%p\n", signo, callback);
+ return;
+ }
+
+ /* Get the load information for this pid */
+
+ bin = unload_list_remove(info->si_pid);
+ if (!bin)
+ {
+ blldbg("ERROR: Could not find load info for PID=%d\n", info->si_pid);
+ return;
+ }
+
+ /* Unload the module */
+
+ ret = unload_module(bin);
+ if (ret < 0)
+ {
+ blldbg("ERROR: unload_module failed: %d\n", get_errno());
+ }
+
+ /* Free the load structure */
+
+ kfree(bin);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: schedule_unload
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called by
+ * the parent of the the newly created task to automatically unload the
+ * module when the task exits. This assumes that (1) the caller is the
+ * parent of the created task, (2) that bin was allocated with kmalloc()
+ * or friends. It will also automatically free the structure with kfree()
+ * after unloading the module.
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ * bin - This structure must have been allocated with kmalloc() and must
+ * persist until the task unloads
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * It returns 0 (OK) if the callback was successfully scheduled. On
+ * failure, it returns -1 (ERROR) and sets errno appropriately.
+ *
+ * On failures, the 'bin' structure will not be deallocated and the
+ * module not not be unloaded.
+ *
+ ****************************************************************************/
+
+int schedule_unload(pid_t pid, FAR struct binary_s *bin)
+{
+ struct sigaction act;
+ struct sigaction oact;
+ sigset_t sigset;
+ irqstate_t flags;
+ int errorcode;
+ int ret;
+
+ /* Make sure that SIGCHLD is unmasked */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+ ret = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (ret != OK)
+ {
+ /* The errno value will get trashed by the following debug output */
+
+ errorcode = get_errno();
+ bvdbg("ERROR: sigprocmask failed: %d\n", ret);
+ goto errout;
+ }
+
+ /* Add the structure to the list. We want to do this *before* connecting
+ * the signal handler. This does, however, make error recovery more
+ * complex if sigaction() fails below because then we have to remove the
+ * unload structure for the list in an unexpected context.
+ */
+
+ unload_list_add(pid, bin);
+
+ /* Register the SIGCHLD handler */
+
+ act.sa_sigaction = unload_callback;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, SIGCHLD);
+
+ ret = sigaction(SIGCHLD, &act, &oact);
+ if (ret != OK)
+ {
+ /* The errno value will get trashed by the following debug output */
+
+ errorcode = get_errno();
+ bvdbg("ERROR: sigaction failed: %d\n" , ret);
+
+ /* Emergency removal from the list */
+
+ flags = irqsave();
+ if (unload_list_remove(pid) != bin)
+ {
+ blldbg("ERROR: Failed to remove structure\n");
+ }
+
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ set_errno(errorcode);
+ return ERROR;
+}
+
+#endif /* !CONFIG_BINFMT_DISABLE && CONFIG_SCHED_HAVE_PARENT */
+
diff --git a/nuttx/binfmt/builtin.c b/nuttx/binfmt/builtin.c
new file mode 100644
index 000000000..e492f72e5
--- /dev/null
+++ b/nuttx/binfmt/builtin.c
@@ -0,0 +1,198 @@
+/****************************************************************************
+ * binfmt/builtin.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/binfmt/binfmt.h>
+#include <nuttx/binfmt/builtin.h>
+
+#ifdef CONFIG_BUILTIN
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int builtin_loadbinary(FAR struct binary_s *binp);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct binfmt_s g_builtin_binfmt =
+{
+ NULL, /* next */
+ builtin_loadbinary, /* load */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_loadbinary
+ *
+ * Description:
+ * Verify that the file is an builtin binary.
+ *
+ ****************************************************************************/
+
+static int builtin_loadbinary(struct binary_s *binp)
+{
+ FAR const char *filename;
+ FAR const struct builtin_s *b;
+ int fd;
+ int index;
+ int ret;
+
+ bvdbg("Loading file: %s\n", binp->filename);
+
+ /* Open the binary file for reading (only) */
+
+ fd = open(binp->filename, O_RDONLY);
+ if (fd < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: Failed to open binary %s: %d\n", binp->filename, errval);
+ return -errval;
+ }
+
+ /* If this file is a BINFS file system, then we can recover the name of
+ * the file using the FIOC_FILENAME ioctl() call.
+ */
+
+ ret = ioctl(fd, FIOC_FILENAME, (unsigned long)((uintptr_t)&filename));
+ if (ret < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval);
+ return -errval;
+ }
+
+ /* Other file systems may also support FIOC_FILENAME, so the real proof
+ * is that we can look up the index to this name in g_builtins[].
+ */
+
+ index = builtin_isavail(filename);
+ if (index < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: %s is not a builtin application\n", filename);
+ return -errval;
+
+ }
+
+ /* Return the load information. NOTE: that there is no way to configure
+ * the priority. That is a bug and needs to be fixed.
+ */
+
+ b = builtin_for_index(index);
+ binp->entrypt = b->main;
+ binp->stacksize = b->stacksize;
+ binp->priority = b->priority;
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_initialize
+ *
+ * Description:
+ * Builtin support is built unconditionally. However, it order to
+ * use this binary format, this function must be called during system
+ * format in order to register the builtin binary format.
+ *
+ * Returned Value:
+ * This is a NuttX internal function so it follows the convention that
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int builtin_initialize(void)
+{
+ int ret;
+
+ /* Register ourselves as a binfmt loader */
+
+ bvdbg("Registering Builtin Loader\n");
+
+ ret = register_binfmt(&g_builtin_binfmt);
+ if (ret != 0)
+ {
+ bdbg("Failed to register binfmt: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: builtin_uninitialize
+ *
+ * Description:
+ * Unregister the builtin binary loader
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void builtin_uninitialize(void)
+{
+ unregister_binfmt(&g_builtin_binfmt);
+}
+
+#endif /* CONFIG_BUILTIN */
+
diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c
index bcebf13ca..9dc59fbdd 100644
--- a/nuttx/binfmt/elf.c
+++ b/nuttx/binfmt/elf.c
@@ -183,7 +183,7 @@ static int elf_loadbinary(struct binary_s *binp)
bvdbg("Loading file: %s\n", binp->filename);
- /* Initialize the xflat library to load the program binary. */
+ /* Initialize the ELF library to load the program binary. */
ret = elf_init(binp->filename, &loadinfo);
elf_dumploadinfo(&loadinfo);
diff --git a/nuttx/binfmt/libbuiltin/Kconfig b/nuttx/binfmt/libbuiltin/Kconfig
new file mode 100644
index 000000000..ae2bf3130
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/Kconfig
@@ -0,0 +1,4 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
diff --git a/nuttx/binfmt/libbuiltin/Make.defs b/nuttx/binfmt/libbuiltin/Make.defs
new file mode 100644
index 000000000..5eec1acde
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/Make.defs
@@ -0,0 +1,52 @@
+############################################################################
+# binfmt/libbuiltin/Make.defs
+#
+# Copyright (C) 2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+ifeq ($(CONFIG_BUILTIN),y)
+
+# Builtin application interfaces
+
+BINFMT_CSRCS += builtin.c
+
+# Builtin library interfaces
+
+BINFMT_CSRCS += libbuiltin_getname.c libbuiltin_isavail.c
+
+# Hook the libbuiltin subdirectory into the build
+
+VPATH += libbuiltin
+SUBDIRS += libbuiltin
+DEPPATH += --dep-path libbuiltin
+
+endif
diff --git a/nuttx/binfmt/libbuiltin/libbuiltin_getname.c b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
new file mode 100644
index 000000000..d1e3958b3
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * binfmt/libbuiltin/libbuiltin_getname.c
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_getname
+ *
+ * Description:
+ * Return the name of the application at index in the table of builtin
+ * applications.
+ *
+ ****************************************************************************/
+
+FAR const char *builtin_getname(int index)
+{
+ FAR const struct builtin_s *builtin;
+
+ builtin = builtin_for_index(index);
+
+ if (builtin != NULL)
+ {
+ return builtin->name;
+ }
+
+ return NULL;
+}
diff --git a/apps/namedapp/exec_namedapp.c b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
index 264fca7b9..7a480c0f3 100644
--- a/apps/namedapp/exec_namedapp.c
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
@@ -1,13 +1,15 @@
/****************************************************************************
- * apps/namedaps/exec_namedapp.c
+ * binfmt/libbuiltin/libbuiltin_isavail.c
+ *
+ * Originally by:
*
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
- * With updates, modifications, and general maintenance by:
+ * With subsequent updates, modifications, and general maintenance by:
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
- * Auther: Gregory Nutt <gnutt@nuttx.org>
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,13 +45,16 @@
****************************************************************************/
#include <nuttx/config.h>
-#include <apps/apps.h>
-#include <sched.h>
#include <string.h>
+#include <limits.h>
#include <errno.h>
-#include "namedapp.h"
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
/****************************************************************************
* Private Types
@@ -72,40 +77,22 @@
****************************************************************************/
/****************************************************************************
- * Name: namedapp_getname
+ * Name: builtin_isavail
*
* Description:
- * Return the name of the application at index in the table of named
- * applications.
- *
- ****************************************************************************/
-
-const char *namedapp_getname(int index)
-{
- if (index < 0 || index >= number_namedapps())
- {
- return NULL;
- }
-
- return namedapps[index].name;
-}
-
-/****************************************************************************
- * Name: namedapp_isavail
- *
- * Description:
- * Return the index into the table of applications for the applicaiton with
+ * Return the index into the table of applications for the application with
* the name 'appname'.
*
****************************************************************************/
-int namedapp_isavail(FAR const char *appname)
+int builtin_isavail(FAR const char *appname)
{
+ FAR const char *name;
int i;
-
- for (i = 0; namedapps[i].name; i++)
+
+ for (i = 0; (name = builtin_getname(i)); i++)
{
- if (!strcmp(namedapps[i].name, appname))
+ if (!strncmp(name, appname, NAME_MAX))
{
return i;
}
@@ -114,74 +101,3 @@ int namedapp_isavail(FAR const char *appname)
set_errno(ENOENT);
return ERROR;
}
-
-/****************************************************************************
- * Name: namedapp_isavail
- *
- * Description:
- * Execute the application with name 'appname', providing the arguments
- * in the argv[] array.
- *
- * Returned Value:
- * On success, the task ID of the named application is returned. On
- * failure, -1 (ERROR) is returned an the errno value is set appropriately.
- *
- ****************************************************************************/
-
-int exec_namedapp(FAR const char *appname, FAR const char **argv)
-{
- pid_t pid;
- int index;
-
- /* Verify that an application with this name exists */
-
- index = namedapp_isavail(appname);
- if (index >= 0)
- {
- /* Disable pre-emption. This means that although we start the named
- * application here, it will not actually run until pre-emption is
- * re-enabled below.
- */
-
- sched_lock();
-
- /* Start the named application task */
-
- pid = TASK_CREATE(namedapps[index].name, namedapps[index].priority,
- namedapps[index].stacksize, namedapps[index].main,
- (argv) ? &argv[1] : (const char **)NULL);
-
- /* If robin robin scheduling is enabled, then set the scheduling policy
- * of the new task to SCHED_RR before it has a chance to run.
- */
-
-#if CONFIG_RR_INTERVAL > 0
- if (pid > 0)
- {
- struct sched_param param;
-
- /* Pre-emption is disabled so the task creation and the
- * following operation will be atomic. The priority of the
- * new task cannot yet have changed from its initial value.
- */
-
- param.sched_priority = namedapps[index].priority;
- sched_setscheduler(pid, SCHED_RR, &param);
- }
-#endif
- /* Now let the named application run */
-
- sched_unlock();
-
- /* Return the task ID of the new task if the task was sucessfully
- * started. Otherwise, pid will be ERROR (and the errno value will
- * be set appropriately).
- */
-
- return pid;
- }
-
- /* Return ERROR with errno set appropriately */
-
- return ERROR;
-}
diff --git a/nuttx/binfmt/libelf/Kconfig b/nuttx/binfmt/libelf/Kconfig
new file mode 100644
index 000000000..f6f579276
--- /dev/null
+++ b/nuttx/binfmt/libelf/Kconfig
@@ -0,0 +1,40 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config ELF_ALIGN_LOG2
+ int "Log2 Section Alignment"
+ default 2
+ ---help---
+ Align all sections to this Log2 value: 0->1, 1->2, 2->4, etc.
+
+config ELF_STACKSIZE
+ int "ELF Stack Size"
+ default 2048
+ ---help---
+ This is the default stack size that will will be used when starting ELF binaries.
+
+config ELF_BUFFERSIZE
+ int "ELF I/O Buffer Size"
+ default 128
+ ---help---
+ This is an I/O buffer that is used to access the ELF file. Variable length items
+ will need to be read (such as symbol names). This is really just this initial
+ size of the buffer; it will be reallocated as necessary to hold large symbol
+ names). Default: 128
+
+config ELF_BUFFERINCR
+ int "ELF I/O Buffer Realloc Increment"
+ default 32
+ ---help---
+ This is an I/O buffer that is used to access the ELF file. Variable length items
+ will need to be read (such as symbol names). This value specifies the size
+ increment to use each time the buffer is reallocated. Default: 32
+
+config ELF_DUMPBUFFER
+ bool "Dump ELF buffers"
+ default n
+ depends on DEBUG && DEBUG_VERBOSE
+ ---help---
+ Dump various ELF buffers for debug purposes
diff --git a/nuttx/binfmt/libelf/gnu-elf.ld b/nuttx/binfmt/libelf/gnu-elf.ld
new file mode 100644
index 000000000..b2a3dc113
--- /dev/null
+++ b/nuttx/binfmt/libelf/gnu-elf.ld
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * binfmt/libelf/gnu-elf.ld
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+SECTIONS
+{
+ .text 0x00000000 :
+ {
+ _stext = . ;
+ *(.text)
+ *(.text.*)
+ *(.gnu.warning)
+ *(.stub)
+ *(.glue_7)
+ *(.glue_7t)
+ *(.jcr)
+
+ /* C++ support: The .init and .fini sections contain specific logic
+ * to manage static constructors and destructors.
+ */
+
+ *(.gnu.linkonce.t.*)
+ *(.init) /* Old ABI */
+ *(.fini) /* Old ABI */
+ _etext = . ;
+ }
+
+ .rodata :
+ {
+ _srodata = . ;
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.*)
+ *(.gnu.linkonce.r*)
+ _erodata = . ;
+ }
+
+ .data :
+ {
+ _sdata = . ;
+ *(.data)
+ *(.data1)
+ *(.data.*)
+ *(.gnu.linkonce.d*)
+ _edata = . ;
+ }
+
+ /* C++ support. For each global and static local C++ object,
+ * GCC creates a small subroutine to construct the object. Pointers
+ * to these routines (not the routines themselves) are stored as
+ * simple, linear arrays in the .ctors section of the object file.
+ * Similarly, pointers to global/static destructor routines are
+ * stored in .dtors.
+ */
+
+ .ctors :
+ {
+ _sctors = . ;
+ *(.ctors) /* Old ABI: Unallocated */
+ *(.init_array) /* New ABI: Allocated */
+ _edtors = . ;
+ }
+
+ .dtors :
+ {
+ _sdtors = . ;
+ *(.dtors) /* Old ABI: Unallocated */
+ *(.fini_array) /* New ABI: Allocated */
+ _edtors = . ;
+ }
+
+ .bss :
+ {
+ _sbss = . ;
+ *(.bss)
+ *(.bss.*)
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.b*)
+ *(COMMON)
+ _ebss = . ;
+ }
+
+ /* Stabs debugging sections. */
+
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_info 0 : { *(.debug_info) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+}
diff --git a/nuttx/binfmt/libelf/libelf_ctors.c b/nuttx/binfmt/libelf/libelf_ctors.c
new file mode 100644
index 000000000..20f1256e2
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_ctors.c
@@ -0,0 +1,215 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_ctors.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_loadctors
+ *
+ * Description:
+ * Load pointers to static constructors into an in-memory array.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
+{
+ FAR Elf32_Shdr *shdr;
+ size_t ctorsize;
+ int ctoridx;
+ int ret;
+ int i;
+
+ DEBUGASSERT(loadinfo->ctors == NULL);
+
+ /* Allocate an I/O buffer if necessary. This buffer is used by
+ * elf_sectname() to accumulate the variable length symbol name.
+ */
+
+ ret = elf_allocbuffer(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("elf_allocbuffer failed: %d\n", ret);
+ return -ENOMEM;
+ }
+
+ /* Find the index to the section named ".ctors." NOTE: On old ABI system,
+ * .ctors is the name of the section containing the list of constructors;
+ * On newer systems, the similar section is called .init_array. It is
+ * expected that the linker script will force the section name to be ".ctors"
+ * in either case.
+ */
+
+ ctoridx = elf_findsection(loadinfo, ".ctors");
+ if (ctoridx < 0)
+ {
+ /* This may not be a failure. -ENOENT indicates that the file has no
+ * static constructor section.
+ */
+
+ bvdbg("elf_findsection .ctors section failed: %d\n", ctoridx);
+ return ret == -ENOENT ? OK : ret;
+ }
+
+ /* Now we can get a pointer to the .ctor section in the section header
+ * table.
+ */
+
+ shdr = &loadinfo->shdr[ctoridx];
+
+ /* Get the size of the .ctor section and the number of constructors that
+ * will need to be called.
+ */
+
+ ctorsize = shdr->sh_size;
+ loadinfo->nctors = ctorsize / sizeof(binfmt_ctor_t);
+
+ bvdbg("ctoridx=%d ctorsize=%d sizeof(binfmt_ctor_t)=%d nctors=%d\n",
+ ctoridx, ctorsize, sizeof(binfmt_ctor_t), loadinfo->nctors);
+
+ /* Check if there are any constructors. It is not an error if there
+ * are none.
+ */
+
+ if (loadinfo->nctors > 0)
+ {
+ /* Check an assumption that we made above */
+
+ DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(binfmt_ctor_t));
+
+ /* In the old ABI, the .ctors section is not allocated. In that case,
+ * we need to allocate memory to hold the .ctors and then copy the
+ * from the file into the allocated memory.
+ *
+ * SHF_ALLOC indicates that the section requires memory during
+ * execution.
+ */
+
+ if ((shdr->sh_flags & SHF_ALLOC) == 0)
+ {
+ /* Allocate memory to hold a copy of the .ctor section */
+
+ loadinfo->ctoralloc = (binfmt_ctor_t*)kmalloc(ctorsize);
+ if (!loadinfo->ctoralloc)
+ {
+ bdbg("Failed to allocate memory for .ctors\n");
+ return -ENOMEM;
+ }
+
+ loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc;
+
+ /* Read the section header table into memory */
+
+ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize,
+ shdr->sh_offset);
+ if (ret < 0)
+ {
+ bdbg("Failed to allocate .ctors: %d\n", ret);
+ return ret;
+ }
+
+ /* Fix up all of the .ctor addresses. Since the addresses
+ * do not lie in allocated memory, there will be no relocation
+ * section for them.
+ */
+
+ for (i = 0; i < loadinfo->nctors; i++)
+ {
+ FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);
+
+ bvdbg("ctor %d: %08lx + %08lx = %08lx\n",
+ i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc);
+
+ *ptr += loadinfo->elfalloc;
+ }
+ }
+ else
+ {
+
+ /* Save the address of the .ctors (actually, .init_array) where it was
+ * loaded into memory. Since the .ctors lie in allocated memory, they
+ * will be relocated via the normal mechanism.
+ */
+
+ loadinfo->ctors = (binfmt_ctor_t*)shdr->sh_addr;
+ }
+ }
+
+ return OK;
+}
+
+#endif /* CONFIG_BINFMT_CONSTRUCTORS */
diff --git a/nuttx/binfmt/libelf/libelf_dtors.c b/nuttx/binfmt/libelf/libelf_dtors.c
new file mode 100644
index 000000000..c0c73a337
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_dtors.c
@@ -0,0 +1,215 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_dtors.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_loaddtors
+ *
+ * Description:
+ * Load pointers to static destructors into an in-memory array.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
+{
+ FAR Elf32_Shdr *shdr;
+ size_t dtorsize;
+ int dtoridx;
+ int ret;
+ int i;
+
+ DEBUGASSERT(loadinfo->dtors == NULL);
+
+ /* Allocate an I/O buffer if necessary. This buffer is used by
+ * elf_sectname() to accumulate the variable length symbol name.
+ */
+
+ ret = elf_allocbuffer(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("elf_allocbuffer failed: %d\n", ret);
+ return -ENOMEM;
+ }
+
+ /* Find the index to the section named ".dtors." NOTE: On old ABI system,
+ * .dtors is the name of the section containing the list of destructors;
+ * On newer systems, the similar section is called .fini_array. It is
+ * expected that the linker script will force the section name to be ".dtors"
+ * in either case.
+ */
+
+ dtoridx = elf_findsection(loadinfo, ".dtors");
+ if (dtoridx < 0)
+ {
+ /* This may not be a failure. -ENOENT indicates that the file has no
+ * static destructor section.
+ */
+
+ bvdbg("elf_findsection .dtors section failed: %d\n", dtoridx);
+ return ret == -ENOENT ? OK : ret;
+ }
+
+ /* Now we can get a pointer to the .dtor section in the section header
+ * table.
+ */
+
+ shdr = &loadinfo->shdr[dtoridx];
+
+ /* Get the size of the .dtor section and the number of destructors that
+ * will need to be called.
+ */
+
+ dtorsize = shdr->sh_size;
+ loadinfo->ndtors = dtorsize / sizeof(binfmt_dtor_t);
+
+ bvdbg("dtoridx=%d dtorsize=%d sizeof(binfmt_dtor_t)=%d ndtors=%d\n",
+ dtoridx, dtorsize, sizeof(binfmt_dtor_t), loadinfo->ndtors);
+
+ /* Check if there are any destructors. It is not an error if there
+ * are none.
+ */
+
+ if (loadinfo->ndtors > 0)
+ {
+ /* Check an assumption that we made above */
+
+ DEBUGASSERT(shdr->sh_size == loadinfo->ndtors * sizeof(binfmt_dtor_t));
+
+ /* In the old ABI, the .dtors section is not allocated. In that case,
+ * we need to allocate memory to hold the .dtors and then copy the
+ * from the file into the allocated memory.
+ *
+ * SHF_ALLOC indicates that the section requires memory during
+ * execution.
+ */
+
+ if ((shdr->sh_flags & SHF_ALLOC) == 0)
+ {
+ /* Allocate memory to hold a copy of the .dtor section */
+
+ loadinfo->ctoralloc = (binfmt_dtor_t*)kmalloc(dtorsize);
+ if (!loadinfo->ctoralloc)
+ {
+ bdbg("Failed to allocate memory for .dtors\n");
+ return -ENOMEM;
+ }
+
+ loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc;
+
+ /* Read the section header table into memory */
+
+ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->dtors, dtorsize,
+ shdr->sh_offset);
+ if (ret < 0)
+ {
+ bdbg("Failed to allocate .dtors: %d\n", ret);
+ return ret;
+ }
+
+ /* Fix up all of the .dtor addresses. Since the addresses
+ * do not lie in allocated memory, there will be no relocation
+ * section for them.
+ */
+
+ for (i = 0; i < loadinfo->ndtors; i++)
+ {
+ FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]);
+
+ bvdbg("dtor %d: %08lx + %08lx = %08lx\n",
+ i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc);
+
+ *ptr += loadinfo->elfalloc;
+ }
+ }
+ else
+ {
+
+ /* Save the address of the .dtors (actually, .init_array) where it was
+ * loaded into memory. Since the .dtors lie in allocated memory, they
+ * will be relocated via the normal mechanism.
+ */
+
+ loadinfo->dtors = (binfmt_dtor_t*)shdr->sh_addr;
+ }
+ }
+
+ return OK;
+}
+
+#endif /* CONFIG_BINFMT_CONSTRUCTORS */
diff --git a/nuttx/binfmt/libelf/libelf_init.c b/nuttx/binfmt/libelf/libelf_init.c
new file mode 100644
index 000000000..fa4b7983c
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_init.c
@@ -0,0 +1,202 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_init.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <elf32.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
+ * defined or CONFIG_ELF_DUMPBUFFER does nothing.
+ */
+
+#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
+# undef CONFIG_ELF_DUMPBUFFER
+#endif
+
+#ifdef CONFIG_ELF_DUMPBUFFER
+# define elf_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
+#else
+# define elf_dumpbuffer(m,b,n)
+#endif
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_filelen
+ *
+ * Description:
+ * Get the size of the ELF file
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const char *filename)
+{
+ struct stat buf;
+ int ret;
+
+ /* Get the file stats */
+
+ ret = stat(filename, &buf);
+ if (ret < 0)
+ {
+ int errval = errno;
+ bdbg("Failed to fstat file: %d\n", errval);
+ return -errval;
+ }
+
+ /* Verify that it is a regular file */
+
+ if (!S_ISREG(buf.st_mode))
+ {
+ bdbg("Not a regular file. mode: %d\n", buf.st_mode);
+ return -ENOENT;
+ }
+
+ /* TODO: Verify that the file is readable. Not really important because
+ * we will detect this when we try to open the file read-only.
+ */
+
+ /* Return the size of the file in the loadinfo structure */
+
+ loadinfo->filelen = buf.st_size;
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_init
+ *
+ * Description:
+ * This function is called to configure the library to process an ELF
+ * program binary.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
+{
+ int ret;
+
+ bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo);
+
+ /* Clear the load info structure */
+
+ memset(loadinfo, 0, sizeof(struct elf_loadinfo_s));
+
+ /* Get the length of the file. */
+
+ ret = elf_filelen(loadinfo, filename);
+ if (ret < 0)
+ {
+ bdbg("elf_filelen failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Open the binary file for reading (only) */
+
+ loadinfo->filfd = open(filename, O_RDONLY);
+ if (loadinfo->filfd < 0)
+ {
+ int errval = errno;
+ bdbg("Failed to open ELF binary %s: %d\n", filename, errval);
+ return -errval;
+ }
+
+ /* Read the ELF ehdr from offset 0 */
+
+ ret = elf_read(loadinfo, (FAR uint8_t*)&loadinfo->ehdr, sizeof(Elf32_Ehdr), 0);
+ if (ret < 0)
+ {
+ bdbg("Failed to read ELF header: %d\n", ret);
+ return ret;
+ }
+
+ elf_dumpbuffer("ELF header", (FAR const uint8_t*)&loadinfo->ehdr, sizeof(Elf32_Ehdr));
+
+ /* Verify the ELF header */
+
+ ret = elf_verifyheader(&loadinfo->ehdr);
+ if (ret <0)
+ {
+ /* This may not be an error because we will be called to attempt loading
+ * EVERY binary. If elf_verifyheader() does not recognize the ELF header,
+ * it will -ENOEXEC whcih simply informs the system that the file is not an
+ * ELF file. elf_verifyheader() will return other errors if the ELF header
+ * is not correctly formed.
+ */
+
+ bdbg("Bad ELF header: %d\n", ret);
+ return ret;
+ }
+
+ return OK;
+}
+
diff --git a/nuttx/binfmt/libelf/libelf_iobuffer.c b/nuttx/binfmt/libelf/libelf_iobuffer.c
new file mode 100644
index 000000000..ead99ca09
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_iobuffer.c
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * binfmt/libelf/elf_iobuffer.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_allocbuffer
+ *
+ * Description:
+ * Perform the initial allocation of the I/O buffer, if it has not already
+ * been allocated.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo)
+{
+ /* Has a buffer been allocated> */
+
+ if (!loadinfo->iobuffer)
+ {
+ /* No.. allocate one now */
+
+ loadinfo->iobuffer = (FAR uint8_t *)kmalloc(CONFIG_ELF_BUFFERSIZE);
+ if (!loadinfo->iobuffer)
+ {
+ bdbg("Failed to allocate an I/O buffer\n");
+ return -ENOMEM;
+ }
+
+ loadinfo->buflen = CONFIG_ELF_BUFFERSIZE;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: elf_reallocbuffer
+ *
+ * Description:
+ * Increase the size of I/O buffer by the specified buffer increment.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment)
+{
+ FAR void *buffer;
+ size_t newsize;
+
+ /* Get the new size of the allocation */
+
+ newsize = loadinfo->buflen + increment;
+
+ /* And perform the reallocation */
+
+ buffer = krealloc((FAR void *)loadinfo->iobuffer, newsize);
+ if (!buffer)
+ {
+ bdbg("Failed to reallocate the I/O buffer\n");
+ return -ENOMEM;
+ }
+
+ /* Save the new buffer info */
+
+ loadinfo->iobuffer = buffer;
+ loadinfo->buflen = newsize;
+ return OK;
+}
+
diff --git a/nuttx/binfmt/libelf/libelf_sections.c b/nuttx/binfmt/libelf/libelf_sections.c
new file mode 100644
index 000000000..c41793544
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_sections.c
@@ -0,0 +1,284 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_sections.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_sectname
+ *
+ * Description:
+ * Get the symbol name in loadinfo->iobuffer[].
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const Elf32_Shdr *shdr)
+{
+ FAR Elf32_Shdr *shstr;
+ FAR uint8_t *buffer;
+ off_t offset;
+ size_t readlen;
+ size_t bytesread;
+ int shstrndx;
+ int ret;
+
+ /* Get the section header table index of the entry associated with the
+ * section name string table. If the file has no section name string table,
+ * this member holds the value SH_UNDEF.
+ */
+
+ shstrndx = loadinfo->ehdr.e_shstrndx;
+ if (shstrndx == SHN_UNDEF)
+ {
+ bdbg("No section header string table\n");
+ return -EINVAL;
+ }
+
+ /* Get the section name string table section header */
+
+ shstr = &loadinfo->shdr[shstrndx];
+
+ /* Get the file offset to the string that is the name of the section. This
+ * is the sum of:
+ *
+ * shstr->sh_offset: The file offset to the first byte of the section
+ * header string table data.
+ * shdr->sh_name: The offset to the name of the section in the section
+ * name table
+ */
+
+ offset = shstr->sh_offset + shdr->sh_name;
+
+ /* Loop until we get the entire section name into memory */
+
+ buffer = loadinfo->iobuffer;
+ bytesread = 0;
+
+ for (;;)
+ {
+ /* Get the number of bytes to read */
+
+ readlen = loadinfo->buflen - bytesread;
+ if (offset + readlen > loadinfo->filelen)
+ {
+ readlen = loadinfo->filelen - offset;
+ if (readlen <= 0)
+ {
+ bdbg("At end of file\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Read that number of bytes into the array */
+
+ buffer = &loadinfo->iobuffer[bytesread];
+ ret = elf_read(loadinfo, buffer, readlen, offset);
+ if (ret < 0)
+ {
+ bdbg("Failed to read section name\n");
+ return ret;
+ }
+
+ bytesread += readlen;
+
+ /* Did we read the NUL terminator? */
+
+ if (memchr(buffer, '\0', readlen) != NULL)
+ {
+ /* Yes, the buffer contains a NUL terminator. */
+
+ return OK;
+ }
+
+ /* No.. then we have to read more */
+
+ ret = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
+ if (ret < 0)
+ {
+ bdbg("elf_reallocbuffer failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* We will not get here */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_loadshdrs
+ *
+ * Description:
+ * Loads section headers into memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
+{
+ size_t shdrsize;
+ int ret;
+
+ DEBUGASSERT(loadinfo->shdr == NULL);
+
+ /* Verify that there are sections */
+
+ if (loadinfo->ehdr.e_shnum < 1)
+ {
+ bdbg("No sections(?)\n");
+ return -EINVAL;
+ }
+
+ /* Get the total size of the section header table */
+
+ shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum;
+ if(loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen)
+ {
+ bdbg("Insufficent space in file for section header table\n");
+ return -ESPIPE;
+ }
+
+ /* Allocate memory to hold a working copy of the sector header table */
+
+ loadinfo->shdr = (FAR Elf32_Shdr*)kmalloc(shdrsize);
+ if (!loadinfo->shdr)
+ {
+ bdbg("Failed to allocate the section header table. Size: %ld\n", (long)shdrsize);
+ return -ENOMEM;
+ }
+
+ /* Read the section header table into memory */
+
+ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->shdr, shdrsize, loadinfo->ehdr.e_shoff);
+ if (ret < 0)
+ {
+ bdbg("Failed to read section header table: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: elf_findsection
+ *
+ * Description:
+ * A section by its name.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ * sectname - Name of the section to find
+ *
+ * Returned Value:
+ * On success, the index to the section is returned; A negated errno value
+ * is returned on failure.
+ *
+ ****************************************************************************/
+
+int elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const char *sectname)
+{
+ FAR const Elf32_Shdr *shdr;
+ int ret;
+ int i;
+
+ /* Search through the shdr[] array in loadinfo for a section named 'sectname' */
+
+ for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
+ {
+ /* Get the name of this section */
+
+ shdr = &loadinfo->shdr[i];
+ ret = elf_sectname(loadinfo, shdr);
+ if (ret < 0)
+ {
+ bdbg("elf_sectname failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Check if the name of this section is 'sectname' */
+
+ bvdbg("%d. Comparing \"%s\" and .\"%s\"\n",
+ i, loadinfo->iobuffer, sectname);
+
+ if (strcmp((FAR const char *)loadinfo->iobuffer, sectname) == 0)
+ {
+ /* We found it... return the index */
+
+ return i;
+ }
+ }
+
+ /* We failed to find a section with this name. */
+
+ return -ENOENT;
+}
diff --git a/nuttx/binfmt/libelf/libelf_symbols.c b/nuttx/binfmt/libelf/libelf_symbols.c
new file mode 100644
index 000000000..2d94b11af
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_symbols.c
@@ -0,0 +1,329 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_symbols.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <elf32.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/elf.h>
+#include <nuttx/binfmt/symtab.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_ELF_BUFFERINCR
+# define CONFIG_ELF_BUFFERINCR 32
+#endif
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_symname
+ *
+ * Description:
+ * Get the symbol name in loadinfo->iobuffer[].
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int elf_symname(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const Elf32_Sym *sym)
+{
+ FAR uint8_t *buffer;
+ off_t offset;
+ size_t readlen;
+ size_t bytesread;
+ int ret;
+
+ /* Get the file offset to the string that is the name of the symbol. The
+ * st_name member holds an offset into the file's symbol string table.
+ */
+
+ if (sym->st_name == 0)
+ {
+ bdbg("Symbol has no name\n");
+ return -ENOENT;
+ }
+
+ offset = loadinfo->shdr[loadinfo->strtabidx].sh_offset + sym->st_name;
+
+ /* Loop until we get the entire symbol name into memory */
+
+ bytesread = 0;
+
+ for (;;)
+ {
+ /* Get the number of bytes to read */
+
+ readlen = loadinfo->buflen - bytesread;
+ if (offset + readlen > loadinfo->filelen)
+ {
+ readlen = loadinfo->filelen - offset;
+ if (readlen <= 0)
+ {
+ bdbg("At end of file\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Read that number of bytes into the array */
+
+ buffer = &loadinfo->iobuffer[bytesread];
+ ret = elf_read(loadinfo, buffer, readlen, offset);
+ if (ret < 0)
+ {
+ bdbg("elf_read failed: %d\n", ret);
+ return ret;
+ }
+
+ bytesread += readlen;
+
+ /* Did we read the NUL terminator? */
+
+ if (memchr(buffer, '\0', readlen) != NULL)
+ {
+ /* Yes, the buffer contains a NUL terminator. */
+
+ return OK;
+ }
+
+ /* No.. then we have to read more */
+
+ ret = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
+ if (ret < 0)
+ {
+ bdbg("elf_reallocbuffer failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* We will not get here */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_findsymtab
+ *
+ * Description:
+ * Find the symbol table section.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo)
+{
+ int i;
+
+ /* Find the symbol table section header and its associated string table */
+
+ for (i = 1; i < loadinfo->ehdr.e_shnum; i++)
+ {
+ if (loadinfo->shdr[i].sh_type == SHT_SYMTAB)
+ {
+ loadinfo->symtabidx = i;
+ loadinfo->strtabidx = loadinfo->shdr[i].sh_link;
+ break;
+ }
+ }
+
+ /* Verify that there is a symbol and string table */
+
+ if (loadinfo->symtabidx == 0)
+ {
+ bdbg("No symbols in ELF file\n");
+ return -EINVAL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: elf_readsym
+ *
+ * Description:
+ * Read the ELFT symbol structure at the specfied index into memory.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ * index - Symbol table index
+ * sym - Location to return the table entry
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
+ FAR Elf32_Sym *sym)
+{
+ FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
+ off_t offset;
+
+ /* Verify that the symbol table index lies within symbol table */
+
+ if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym)))
+ {
+ bdbg("Bad relocation symbol index: %d\n", index);
+ return -EINVAL;
+ }
+
+ /* Get the file offset to the symbol table entry */
+
+ offset = symtab->sh_offset + sizeof(Elf32_Sym) * index;
+
+ /* And, finally, read the symbol table entry into memory */
+
+ return elf_read(loadinfo, (FAR uint8_t*)sym, sizeof(Elf32_Sym), offset);
+}
+
+/****************************************************************************
+ * Name: elf_symvalue
+ *
+ * Description:
+ * Get the value of a symbol. The updated value of the symbol is returned
+ * in the st_value field of the symbol table entry.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ * sym - Symbol table entry (value might be undefined)
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
+ FAR const struct symtab_s *exports, int nexports)
+{
+ FAR const struct symtab_s *symbol;
+ uintptr_t secbase;
+ int ret;
+
+ switch (sym->st_shndx)
+ {
+ case SHN_COMMON:
+ {
+ /* NuttX ELF modules should be compiled with -fno-common. */
+
+ bdbg("SHN_COMMON: Re-compile with -fno-common\n");
+ return -EINVAL;
+ }
+
+ case SHN_ABS:
+ {
+ /* st_value already holds the correct value */
+
+ bvdbg("SHN_ABS: st_value=%08lx\n", (long)sym->st_value);
+ return OK;
+ }
+
+ case SHN_UNDEF:
+ {
+ /* Get the name of the undefined symbol */
+
+ ret = elf_symname(loadinfo, sym);
+ if (ret < 0)
+ {
+ bdbg("SHN_UNDEF: Failed to get symbol name: %d\n", ret);
+ return ret;
+ }
+
+ /* Check if the base code exports a symbol of this name */
+
+#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
+ symbol = symtab_findorderedbyname(exports, (FAR char *)loadinfo->iobuffer, nexports);
+#else
+ symbol = symtab_findbyname(exports, (FAR char *)loadinfo->iobuffer, nexports);
+#endif
+ if (!symbol)
+ {
+ bdbg("SHN_UNDEF: Exported symbol \"%s\" not found\n", loadinfo->iobuffer);
+ return -ENOENT;
+ }
+
+ /* Yes... add the exported symbol value to the ELF symbol table entry */
+
+ bvdbg("SHN_ABS: name=%s %08x+%08x=%08x\n",
+ loadinfo->iobuffer, sym->st_value, symbol->sym_value,
+ sym->st_value + symbol->sym_value);
+
+ sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value);
+ }
+ break;
+
+ default:
+ {
+ secbase = loadinfo->shdr[sym->st_shndx].sh_addr;
+
+ bvdbg("Other: %08x+%08x=%08x\n",
+ sym->st_value, secbase, sym->st_value + secbase);
+
+ sym->st_value += secbase;
+ }
+ break;
+ }
+
+ return OK;
+}
diff --git a/nuttx/binfmt/libelf/libelf_uninit.c b/nuttx/binfmt/libelf/libelf_uninit.c
new file mode 100644
index 000000000..3ec6f6c61
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_uninit.c
@@ -0,0 +1,126 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_uninit.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <unistd.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_uninit
+ *
+ * Description:
+ * Releases any resources committed by elf_init(). This essentially
+ * undoes the actions of elf_init.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_uninit(struct elf_loadinfo_s *loadinfo)
+{
+ /* Free all working buffers */
+
+ elf_freebuffers(loadinfo);
+
+ /* Close the ELF file */
+
+ if (loadinfo->filfd >= 0)
+ {
+ close(loadinfo->filfd);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: elf_freebuffers
+ *
+ * Description:
+ * Release all working buffers.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_freebuffers(struct elf_loadinfo_s *loadinfo)
+{
+ /* Release all working allocations */
+
+ if (loadinfo->shdr)
+ {
+ kfree((FAR void *)loadinfo->shdr);
+ loadinfo->shdr = NULL;
+ }
+
+ if (loadinfo->iobuffer)
+ {
+ kfree((FAR void *)loadinfo->iobuffer);
+ loadinfo->iobuffer = NULL;
+ loadinfo->buflen = 0;
+ }
+
+ return OK;
+}
diff --git a/nuttx/binfmt/libelf/libelf_verify.c b/nuttx/binfmt/libelf/libelf_verify.c
new file mode 100644
index 000000000..c5f185ec3
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_verify.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * binfmt/libelf/elf_verify.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/binfmt/elf.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+static const char g_elfmagic[EI_MAGIC_SIZE] = { 0x7f, 'E', 'L', 'F' };
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_verifyheader
+ *
+ * Description:
+ * Given the header from a possible ELF executable, verify that it
+ * is an ELF executable.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ * -ENOEXEC : Not an ELF file
+ * -EINVAL : Not a relocatable ELF file or not supported by the current,
+ * configured architecture.
+ *
+ ****************************************************************************/
+
+int elf_verifyheader(FAR const Elf32_Ehdr *ehdr)
+{
+ if (!ehdr)
+ {
+ bdbg("NULL ELF header!");
+ return -ENOEXEC;
+ }
+
+ /* Verify that the magic number indicates an ELF file */
+
+ if (memcmp(ehdr->e_ident, g_elfmagic, EI_MAGIC_SIZE) != 0)
+ {
+ bvdbg("Not ELF magic {%02x, %02x, %02x, %02x}\n",
+ ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
+ return -ENOEXEC;
+ }
+
+ /* Verify that this is a relocatable file */
+
+ if (ehdr->e_type != ET_REL)
+ {
+ bdbg("Not a relocatable file: e_type=%d\n", ehdr->e_type);
+ return -EINVAL;
+ }
+
+ /* Verify that this file works with the currently configured architecture */
+
+ if (arch_checkarch(ehdr))
+ {
+ bdbg("Not a supported architecture\n");
+ return -ENOEXEC;
+ }
+
+ /* Looks good so far... we still might find some problems later. */
+
+ return OK;
+}
+
diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt
index 21aace2af..1b78567a3 100644
--- a/nuttx/configs/README.txt
+++ b/nuttx/configs/README.txt
@@ -334,6 +334,79 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_TASK_NAME_SIZE - Specifies that maximum size of a
task name to save in the TCB. Useful if scheduler
instrumentation is selected. Set to zero to disable.
+ CONFIG_SCHED_HAVE_PARENT - Remember the ID of the parent task
+ when a new child task is created. This support enables some
+ additional features (such as SIGCHLD) and modifies the behavior
+ of other interfaces. For example, it makes waitpid() more
+ standards complete by restricting the waited-for tasks to the
+ children of the caller. Default: disabled.
+ CONFIG_SCHED_CHILD_STATUS
+ If this option is selected, then the exit status of the child task
+ will be retained after the child task exits. This option should be
+ selected if you require knowledge of a child process' exit status.
+ Without this setting, wait(), waitpid() or waitid() may fail. For
+ example, if you do:
+
+ 1) Start child task
+ 2) Wait for exit status (using wait(), waitpid(), or waitid()).
+
+ This can fail because the child task may run to completion before
+ the wait begins. There is a non-standard work-around in this case:
+ The above sequence will work if you disable pre-emption using
+ sched_lock() prior to starting the child task, then re-enable pre-
+ emption with sched_unlock() after the wait completes. This works
+ because the child task is not permitted to run until the wait is in
+ place.
+
+ The standard solution would be to enable CONFIG_SCHED_CHILD_STATUS. In
+ this case the exit status of the child task is retained after the
+ child exits and the wait will successful obtain the child task's
+ exit status whether it is called before the child task exits or not.
+
+ Warning: If you enable this feature, then your application must
+ either (1) take responsibility for reaping the child status with wait(),
+ waitpid(), or waitid(), or (2) suppress retention of child status.
+ If you do not reap the child status, then you have a memory leak and
+ your system will eventually fail.
+
+ Retention of child status can be suppressed on the parent using logic like:
+
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+ int ret = sigaction(SIGCHLD, &sa, NULL);
+
+ CONFIG_PREALLOC_CHILDSTATUS
+ To prevent runaway child status allocations and to improve
+ allocation performance, child task exit status structures are pre-
+ allocated when the system boots. This setting determines the number
+ of child status structures that will be pre-allocated. If this
+ setting is not defined or if it is defined to be zero then a value
+ of 2*MAX_TASKS is used.
+
+ Note that there cannot be more that CONFIG_MAX_TASKS tasks in total.
+ However, the number of child status structures may need to be
+ significantly larger because this number includes the maximum number
+ of tasks that are running PLUS the number of tasks that have exit'ed
+ without having their exit status reaped (via wait(), waitid(), or
+ waitpid()).
+
+ Obviously, if tasks spawn children indefinitely and never have the
+ exit status reaped, then you may have a memory leak! If you enable
+ the SCHED_CHILD_STATUS feature, then your application must take
+ responsibility for either (1) reaping the child status with wait(),
+ waitpid(), or waitid() or it must (2) suppress retention of child
+ status. Otherwise, your system will eventually fail.
+
+ Retention of child status can be suppressed on the parent using logic like:
+
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+ int ret = sigaction(SIGCHLD, &sa, NULL);
+
CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY -
Used to initialize the internal time logic.
CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions.
@@ -400,7 +473,7 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
- the worker thread. Default: 4
+ the worker thread. Default: 17
CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
then an additional, lower-priority work queue will also be created. This
@@ -412,7 +485,12 @@ defconfig -- This is a configuration file similar to the Linux
checks for work in units of microseconds. Default: 50*1000 (50 MS).
CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower
priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
- CONFIG_SCHED_WAITPID - Enables the waitpid() API
+ CONFIG_SCHED_WAITPID - Enables the waitpid() interface in a default,
+ non-standard mode (non-standard in the sense that the waited for
+ PID need not be child of the caller). If SCHED_HAVE_PARENT is
+ also defined, then this setting will modify the behavior or
+ waitpid() (making more spec compliant) and will enable the
+ waitid() and wait() interfaces as well.
CONFIG_SCHED_ATEXIT - Enables the atexit() API
CONFIG_SCHED_ATEXIT_MAX - By default if CONFIG_SCHED_ATEXIT is
selected, only a single atexit() function is supported. That number
@@ -426,6 +504,23 @@ defconfig -- This is a configuration file similar to the Linux
where 'app' is the application name. If not defined, CONFIG_USER_ENTRYPOINT
defaults to user_start.
+ Signal Numbers:
+
+ CONFIG_SIG_SIGUSR1 - Value of standard user signal 1 (SIGUSR1).
+ Default: 1
+ CONFIG_SIG_SIGUSR2 - Value of standard user signal 2 (SIGUSR2).
+ Default: 2
+ CONFIG_SIG_SIGALARM - Default the standard signal used with POSIX
+ timers (SIGALRM). Default: 3
+ CONFIG_SIG_SIGCHLD - The SIGCHLD signal is sent to the parent of a child
+ process when it exits, is interrupted (stopped), or resumes after being
+ interrupted. Default: 4
+
+ CONFIG_SIG_SIGCONDTIMEDOUT - This non-standard signal number is used in
+ the implementation of pthread_cond_timedwait(). Default 16.
+ CONFIG_SIG_SIGWORK - SIGWORK is a non-standard signal used to wake up
+ the internal NuttX worker thread. Default: 17.
+
Binary Loaders:
CONFIG_BINFMT_DISABLE - By default, support for loadable binary formats
is built.
@@ -1562,7 +1657,7 @@ defconfig -- This is a configuration file similar to the Linux
operation from FLASH but must copy initialized .data sections to RAM.
CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH
but copy themselves entirely into RAM for better performance.
- CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions
+ CONFIG_ARCH_RAMFUNCS - Other configurations may copy just some functions
into RAM, either for better performance or for errata workarounds.
CONFIG_STACK_ALIGNMENT - Set if the your application has specific
stack alignment requirements (may not be supported
@@ -1936,6 +2031,11 @@ configs/z8f64200100kit
development kit, Z8F6423 part, and the Zilog ZDS-II Windows command line
tools. The development environment is Cygwin under WinXP.
+configs/zp214xpa
+ This port is for the NXP LPC2148 as provided on the The0.net
+ ZPA213X/4XPA development board. Includes support for the
+ UG-2864AMBAG01 OLED also from The0.net
+
Configuring NuttX
^^^^^^^^^^^^^^^^^
@@ -1955,16 +2055,24 @@ tools/configure.sh
There is a script that automates these steps. The following steps will
accomplish the same configuration:
- cd tools
- ./configure.sh <board-name>/<config-dir>
+ cd tools
+ ./configure.sh <board-name>/<config-dir>
+
+ There is an alternative Windows batch file that can be used in the
+ windows native enironment like:
+
+ cd ${TOPDIR}\tools
+ configure.bat <board-name>\<config-dir>
+
+ See tools/README.txt for more information about these scripts.
-And if configs/<board-name>/<config-dir>/appconfig exists and your
-application directory is not in the standard loction (../apps), then
-you should also specify the location of the application directory on the
-command line like:
+ And if configs/<board-name>/<config-dir>/appconfig exists and your
+ application directory is not in the standard loction (../apps), then
+ you should also specify the location of the application directory on the
+ command line like:
- cd tools
- ./configure.sh -a <app-dir> <board-name>/<config-dir>
+ cd tools
+ ./configure.sh -a <app-dir> <board-name>/<config-dir>
Building Symbol Tables
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/configs/px4fmu/nsh/appconfig b/nuttx/configs/px4fmu/nsh/appconfig
index fcdf689aa..653f97de1 100644
--- a/nuttx/configs/px4fmu/nsh/appconfig
+++ b/nuttx/configs/px4fmu/nsh/appconfig
@@ -92,6 +92,7 @@ CONFIGURED_APPS += fixedwing_att_control
CONFIGURED_APPS += fixedwing_pos_control
CONFIGURED_APPS += position_estimator
CONFIGURED_APPS += attitude_estimator_ekf
+CONFIGURED_APPS += hott_telemetry
# Hacking tools
#CONFIGURED_APPS += system/i2c
diff --git a/nuttx/configs/px4fmu/nsh/defconfig b/nuttx/configs/px4fmu/nsh/defconfig
index 0b27b552e..fd783dec5 100755
--- a/nuttx/configs/px4fmu/nsh/defconfig
+++ b/nuttx/configs/px4fmu/nsh/defconfig
@@ -201,6 +201,12 @@ CONFIG_STM32_TIM10=y
CONFIG_STM32_TIM11=y
#
+# Enable single wire support. If this is not defined, then this mode cannot
+# be enabled.
+#
+CONFIG_STM32_USART_SINGLEWIRE=y
+
+#
# We want the flash prefetch on for max performance.
#
STM32_FLASH_PREFETCH=y
@@ -970,6 +976,7 @@ CONFIG_CDCACM_PRODUCTSTR="PX4 FMU v1.6"
# CONFIG_NSH_FATNSECTORS - FAT FS number of sectors
# CONFIG_NSH_FATMOUNTPT - FAT FS mountpoint
#
+CONFIG_BUILTIN=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_STRERROR=y
@@ -1045,3 +1052,6 @@ CONFIG_PTHREAD_STACK_MIN=512
CONFIG_PTHREAD_STACK_DEFAULT=2048
CONFIG_HEAP_BASE=
CONFIG_HEAP_SIZE=
+
+# enable bindir
+CONFIG_APPS_BINDIR=y
diff --git a/nuttx/drivers/Kconfig b/nuttx/drivers/Kconfig
index 8302d21b7..3ced01b58 100644
--- a/nuttx/drivers/Kconfig
+++ b/nuttx/drivers/Kconfig
@@ -140,7 +140,8 @@ menuconfig SPI
bool "SPI Driver Support"
default n
---help---
- This selection enables building of the "upper-half" SPI driver.
+ This selection enables selection of common SPI options. This option
+ should be enabled by all platforms that support SPI interfaces.
See include/nuttx/spi.h for further SPI driver information.
if SPI
diff --git a/nuttx/drivers/input/Kconfig b/nuttx/drivers/input/Kconfig
index 1f345ee14..6da3a9f39 100644
--- a/nuttx/drivers/input/Kconfig
+++ b/nuttx/drivers/input/Kconfig
@@ -123,6 +123,25 @@ config STMPE811_I2C
endchoice
+config STMPE811_ACTIVELOW
+ bool "Active Low Interrupt"
+ default n
+ ---help---
+ The STMPE811 interrupt is provided by a discrete input (usually a
+ GPIO interrupt on most MCU architectures). This setting determines
+ whether the interrupt is active high (or rising edge triggered) or
+ active low (or falling edge triggered). Default: Active
+ high/rising edge.
+
+config STMPE811_EDGE
+ bool "Edge triggered Interrupt"
+ default n
+ ---help---
+ The STMPE811 interrupt is provided by a discrete input (usually a
+ GPIO interrupt on most MCU architectures). This setting determines
+ whether the interrupt is edge or level triggered. Default: Level
+ triggered.
+
config STMPE811_MULTIPLE
bool "Multiple STMPE811 Devices"
default n
diff --git a/nuttx/drivers/lcd/Make.defs b/nuttx/drivers/lcd/Make.defs
index 1b445b6a7..067f76f4e 100644
--- a/nuttx/drivers/lcd/Make.defs
+++ b/nuttx/drivers/lcd/Make.defs
@@ -51,6 +51,10 @@ ifeq ($(CONFIG_LCD_UG2864AMBAG01),y)
CSRCS += ug-2864ambag01.c
endif
+ifeq ($(CONFIG_LCD_UG2864HSWEG01),y)
+ CSRCS += ug-2864hsweg01.c
+endif
+
ifeq ($(CONFIG_LCD_UG9664HSWAG01),y)
CSRCS += ug-9664hswag01.c
endif
diff --git a/nuttx/drivers/lcd/README.txt b/nuttx/drivers/lcd/README.txt
index 77ae536b2..0472043e6 100644
--- a/nuttx/drivers/lcd/README.txt
+++ b/nuttx/drivers/lcd/README.txt
@@ -119,47 +119,71 @@ that support additional LCDs. LCD drivers in the configuration directory
if they support some differ LCD interface (such as a parallel interface)
that makes then less re-usable:
- configs/compal_e99/src/ssd1783.c
+ SSD1783 Drivers:
- SSD1783
+ configs/compal_e99/src/ssd1783.c
- configs/hymini-stm32v/src/ssd1289.c. See also drivers/lcd/ssd1298.c
- above.
+ SSD1289 Drivers:
+
+ configs/hymini-stm32v/src/ssd1289.c. See also drivers/lcd/ssd1298.c
+ above.
+ configs/stm32f4discovery/src/up_ssd1289.c. This examples is the
+ bottom half for the SSD1289 driver at drivers/lcd/ssd1289.c
+ configs/hymini-stm32v/src/ssd1289.c. See also drivers/lcd/ssd1298.c
+ above.
+ configs/shenzhou/src/up_ssd1289.c
+
+ kwikstik-k40:
- SSD1289
+ configs/kwikstik-k40/src/up_lcd.c. Don't waste your time. This is
+ just a stub.
- configs/kwikstik-k40/src/up_lcd.c. Don't waste your time. This is
- just a stub.
+ Nokia LCD Drivers:
- configs/olimex-lpc1766stk/src/up_lcd.c. This examples is the
- bottom half for the SSD1289 driver at drivers/lcd/nokia6100.c.
- This was never completedly debugged ... there are probably issues
- with that nasty 9-bit SPI interfaces.
+ configs/olimex-lpc1766stk/src/up_lcd.c. This examples is the
+ bottom half for the driver at drivers/lcd/nokia6100.c.
+ This was never completedly debugged ... there are probably issues
+ with that nasty 9-bit SPI interfaces.
- configs/sam3u-ek/src/up_lcd.c
-
- The SAM3U-EK developement board features a TFT/Transmissive color
- LCD module with touch-screen, FTM280C12D, with integrated driver IC
- HX8346.
+ HX8346:
+
+ configs/sam3u-ek/src/up_lcd.c. The SAM3U-EK developement board features
+ a TFT/Transmissive color LCD module with touch-screen, FTM280C12D,
+ with integrated driver IC HX8346.
- configs/skp16c26/src/up_lcd.c. Untested alphanumeric LCD driver.
+ HX8347:
- configs/stm3210e-eval/src/up_lcd.c
+ configs/pic32mx7mmb/src/up_mio283qt2.c. This driver is for the MI0283QT-2
+ LCD from Multi-Inno Technology Co., Ltd. This LCD is based on the Himax
+ HX8347-D LCD controller.
+
+ ILI93xx and Similar:
- This driver supports the following LCDs:
+ configs/stm3210e-eval/src/up_lcd.c. This driver supports the following
+ LCDs:
- 1. Ampire AM-240320LTNQW00H
- 2. Orise Tech SPFD5408B
- 3. RenesasSP R61580
+ 1. Ampire AM-240320LTNQW00H
+ 2. Orise Tech SPFD5408B
+ 3. RenesasSP R61580
- configs/stm3220g-eval/src/up_lcd.c and configs/stm3240g-eval/src/up_lcd.c.
- AM-240320L8TNQW00H (LCD_ILI9320 or LCD_ILI9321) and
- AM-240320D5TOQW01H (LCD_ILI9325)
+ configs/stm3220g-eval/src/up_lcd.c and configs/stm3240g-eval/src/up_lcd.c.
+ AM-240320L8TNQW00H (LCD_ILI9320 or LCD_ILI9321) and
+ AM-240320D5TOQW01H (LCD_ILI9325)
+ configs/shenzhou/src/up_ili93xx.c. Another ILI93xx driver.
- configs/stm32f4discovery/src/up_ssd1289.c. This examples is the
- bottom half for the SSD1289 driver at drivers/lcd/ssd1289.c
+ OLEDs:
+
+ configs/stm32f4discovery/src/up_ug2864ambag01.c
+ configs/stm32f4discovery/src/up_ug2864hsweg01.c
+ configs/zp214xpa/src/up_ug2864ambag01.c
+
+ Alphnumeric LCD Displays:
+
+ configs/skp16c26/src/up_lcd.c. Untested alphanumeric LCD driver.
+ configs/pcblogic-pic32/src/up_lcd1602.c
graphics/
=========
See also the usage of the LCD driver in the graphics/ directory.
+
diff --git a/nuttx/drivers/lcd/ug-2864ambag01.c b/nuttx/drivers/lcd/ug-2864ambag01.c
index 2a47b38eb..6b3d6d5a8 100644
--- a/nuttx/drivers/lcd/ug-2864ambag01.c
+++ b/nuttx/drivers/lcd/ug-2864ambag01.c
@@ -428,7 +428,7 @@ static inline void ug2864ambag01_configspi(FAR struct spi_dev_s *spi)
SPI_SETMODE(spi, CONFIG_UG2864AMBAG01_SPIMODE);
SPI_SETBITS(spi, 8);
- SPI_SETFREQUENCY(spi, CONFIG_UG2864AMBAG01_FREQUENCY)
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864AMBAG01_FREQUENCY);
}
#endif
@@ -1035,7 +1035,7 @@ FAR struct lcd_dev_s *ug2864ambag01_initialize(FAR struct spi_dev_s *spi, unsign
/* Configure the SPI */
- ug2864ambag01_configspi(spi)
+ ug2864ambag01_configspi(spi);
/* Lock and select device */
@@ -1148,8 +1148,8 @@ void ug2864ambag01_fill(FAR struct lcd_dev_s *dev, uint8_t color)
/* Transfer one page of the selected color */
- (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864AMBAG01_XRES],
- UG2864AMBAG01_XRES);
+ (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864AMBAG01_XRES],
+ UG2864AMBAG01_XRES);
}
/* De-select and unlock the device */
diff --git a/nuttx/drivers/lcd/ug-2864hsweg01.c b/nuttx/drivers/lcd/ug-2864hsweg01.c
new file mode 100644
index 000000000..02a59b104
--- /dev/null
+++ b/nuttx/drivers/lcd/ug-2864hsweg01.c
@@ -0,0 +1,1218 @@
+/**************************************************************************************
+ * drivers/lcd/ug-2864hsweg01.c
+ * Driver for Univision UG-2864HSWEG01 OLED display (wih SSD1306 controller) in SPI
+ * mode
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * References:
+ * 1. Product Specification (Preliminary), Part Name: OEL Display Module, Part ID:
+ * UG-2864HSWEG01, Doc No: SAS1-9046-B, Univision Technology Inc.
+ * 2. SSD1306, 128 X 64 Dot Matrix OLED/PLED, Preliminary Segment/Common Driver with
+ * Controller, Solomon Systech
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************************/
+/**************************************************************************************
+ * Device memory organization:
+ *
+ * +----------------------------+
+ * | Column |
+ * --------+----+---+---+---+-...-+-----+
+ * Page | 0 | 1 | 2 | 3 | ... | 127 |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 0 | D0 | X | | | | |
+ * | D1 | X | | | | |
+ * | D2 | X | | | | |
+ * | D3 | X | | | | |
+ * | D4 | X | | | | |
+ * | D5 | X | | | | |
+ * | D6 | X | | | | |
+ * | D7 | X | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 1 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 2 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 3 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 4 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 5 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 6 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 7 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ *
+ * -----------------------------------+---------------------------------------
+ * Landscape Display: | Reverse Landscape Display:
+ * --------+-----------------------+ | --------+---------------------------+
+ * | Column | | | Column |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 0 | 0 | 1 | 2 | | 127 | | Page 7 | 127 | 126 | 125 | | 0 |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 1 | V | | Page 6 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 2 | V | | Page 5 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 3 | V | | Page 4 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 4 | V | | Page 3 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 5 | V | | Page 2 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 6 | V | | Page 1 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 7 | V | | Page 0 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * -----------------------------------+---------------------------------------
+ *
+ * -----------------------------------+---------------------------------------
+ * Portrait Display: | Reverse Portrait Display:
+ * -----------+---------------------+ | -----------+---------------------+
+ * | Page | | | Page |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 0 | 0 | 1 | 2 | | 7 | | Column 127 | 7 | 6 | 5 | | 0 |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 1 | > > > > > | | Column 126 | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 2 | | | Column 125 | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * ... | | | ... | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 127 | | | Column 0 | < < < < < |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * -----------------------------------+----------------------------------------
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Included Files
+ **************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/spi.h>
+#include <nuttx/lcd/lcd.h>
+#include <nuttx/lcd/ug-2864hsweg01.h>
+
+#include <arch/irq.h>
+
+#ifdef CONFIG_LCD_UG2864HSWEG01
+
+/**************************************************************************************
+ * Pre-processor Definitions
+ **************************************************************************************/
+/* Configuration **********************************************************************/
+/* Limitations of the current configuration that I hope to fix someday */
+
+#if CONFIG_UG2864HSWEG01_NINTERFACES != 1
+# warning "This implementation supports only a single OLED device"
+# undef CONFIG_UG2864HSWEG01_NINTERFACES
+# define CONFIG_UG2864HSWEG01_NINTERFACES 1
+#endif
+
+#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
+# warning "No support yet for portrait modes"
+# define CONFIG_LCD_LANDSCAPE 1
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RLANDSCAPE)
+# warning "Reverse landscape mode is untested and, hence, probably buggy"
+#endif
+
+/* SSD1306 Commands *******************************************************************/
+
+#define SSD1306_SETCOLL(ad) (0x00 | ((ad) & 0x0f)) /* Set Lower Column Address: (00h - 0fh) */
+#define SSD1306_SETCOLH(ad) (0x10 | ((ad) & 0x0f)) /* Set Higher Column Address: (10h - 1fh) */
+#define SSD1306_STARTLINE(ln) (0x40 | ((ln) & 0x3f)) /* Set Display Start Line: (40h - 7fh) */
+#define SSD1306_CONTRAST_MODE (0x81) /* Set Contrast Control Register: (Double Bytes Command) */
+# define SSD1306_CONTRAST(c) (c)
+#define SSD1306_SEGREMAP(m) (0xa0 | ((m) & 0x01)) /* Set Segment Re-map: (a0h - a1h) */
+# define SSD1306_REMAPRIGHT SSD1306_SEGREMAP(0) /* Right rotation */
+# define SSD1306_REMAPPLEFT SSD1306_SEGREMAP(1) /* Left rotation */
+#define SSD1306_EDISPOFFON(s) (0xa4 | ((s) & 0x01)) /* Set Entire Display OFF/ON: (a4h - a5h) */
+# define SSD1306_EDISPOFF SSD1306_EDISPOFFON(0) /* Display off */
+# define SSD1306_EDISPON SSD1306_EDISPOFFON(1) /* Display on */
+#define SSD1306_NORMREV(s) (0xa6 | ((s) & 0x01)) /* Set Normal/Reverse Display: (a6h -a7h) */
+# define SSD1306_NORMAL SSD1306_NORMREV(0) /* Normal display */
+# define SSD1306_REVERSE SSD1306_NORMREV(1) /* Reverse display */
+#define SSD1306_MRATIO_MODE (0xa8) /* Set Multiplex Ration: (Double Bytes Command) */
+# define SSD1306_MRATIO(d) ((d) & 0x3f)
+#define SSD1306_DCDC_MODE (0xad) /* Set DC-DC OFF/ON: (Double Bytes Command) */
+# define SSD1306_DCDC_OFF (0x8a)
+# define SSD1306_DCDC_ON (0x8b)
+
+#define SSD1306_DISPOFFON(s) (0xae | ((s) & 0x01)) /* Display OFF/ON: (aeh - afh) */
+# define SSD1306_DISPOFF SSD1306_DISPOFFON(0) /* Display off */
+# define SSD1306_DISPON SSD1306_DISPOFFON(1) /* Display on */
+#define SSD1306_PAGEADDR(a) (0xb0 | ((a) & 0x0f)) /* Set Page Address: (b0h - b7h) */
+#define SSD1306_SCANDIR(d) (0xc0 | ((d) & 0x08)) /* Set Common Output Scan Direction: (c0h - c8h) */
+# define SSD1306_SCANFROMCOM0 SSD1306_SCANDIR(0x00) /* Scan from COM[0] to COM[n-1]*/
+# define SSD1306_SCANTOCOM0 SSD1306_SCANDIR(0x08) /* Scan from COM[n-1] to COM[0] */
+#define SSD1306_DISPOFFS_MODE (0xd3) /* Set Display Offset: (Double Bytes Command) */
+# define SSD1306_DISPOFFS(o) ((o) & 0x3f)
+#define SSD1306_CLKDIV_SET (0xd5) /* Set Display Clock Divide Ratio/Oscillator Frequency: (Double Bytes Command) */
+# define SSD1306_CLKDIV(f,d) ((((f) & 0x0f) << 4) | ((d) & 0x0f))
+#define SSD1306_CHRGPER_SET (0xd9) /* Set Dis-charge/Pre-charge Period: (Double Bytes Command) */
+# define SSD1306_CHRGPER(d,p) ((((d) & 0x0f) << 4) | ((p) & 0x0f))
+#define SSD1306_CMNPAD_CONFIG (0xda) /* Set Common pads hardware configuration: (Double Bytes Command) */
+# define SSD1306_CMNPAD(c) ((0x02) | ((c) & 0x10))
+#define SSD1306_VCOM_SET (0xdb) /* Set VCOM Deselect Level: (Double Bytes Command) */
+# define SSD1306_VCOM(v) (v)
+
+#define SSD1306_CHRPUMP_SET (0x8d) /* Charge Pump Setting */
+# define SSD1306_CHRPUMP_ON (0x14)
+# define SSD1306_CHRPUMP_OFF (0x10)
+
+#define SSD1306_RMWSTART (0xe0) /* Read-Modify-Write: (e0h) */
+#define SSD1306_NOP (0xe3) /* NOP: (e3h) */
+#define SSD1306_END (0xee) /* End: (eeh) */
+
+#define SSD1306_WRDATA(d) (d) /* Write Display Data */
+#define SSD1306_STATUS_BUSY (0x80) /* Read Status */
+#define SSD1306_STATUS_ONOFF (0x40)
+#define SSD1306_RDDATA(d) (d) /* Read Display Data */
+
+/* Color Properties *******************************************************************/
+/* Display Resolution
+ *
+ * The SSD1306 display controller can handle a resolution of 132x64. The UG-2864HSWEG01
+ * on the base board is 128x64.
+ */
+
+#define UG2864HSWEG01_DEV_XRES 128 /* Only 128 of 131 columns used */
+#define UG2864HSWEG01_DEV_YRES 64 /* 8 pages each 8 rows */
+#define UG2864HSWEG01_DEV_XOFFSET 2 /* Offset to logical column 0 */
+#define UG2864HSWEG01_DEV_PAGES 8 /* 8 pages */
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+# define UG2864HSWEG01_XRES UG2864HSWEG01_DEV_XRES
+# define UG2864HSWEG01_YRES UG2864HSWEG01_DEV_YRES
+#else
+# define UG2864HSWEG01_XRES UG2864HSWEG01_DEV_YRES
+# define UG2864HSWEG01_YRES UG2864HSWEG01_DEV_XRES
+#endif
+
+/* Color depth and format */
+
+#define UG2864HSWEG01_BPP 1
+#define UG2864HSWEG01_COLORFMT FB_FMT_Y1
+
+/* Bytes per logical row and actual device row */
+
+#define UG2864HSWEG01_XSTRIDE (UG2864HSWEG01_XRES >> 3)
+#define UG2864HSWEG01_YSTRIDE (UG2864HSWEG01_YRES >> 3)
+
+/* Default contrast */
+
+#define UG2864HSWEG01_CONTRAST (128)
+
+/* The size of the shadow frame buffer or one row buffer.
+ *
+ * Frame buffer size: 128 columns x 64 rows / 8 bits-per-pixel
+ * Row size: 128 columns x 8 rows-per-page / 8 bits-per-pixel
+ */
+
+#define UG2864HSWEG01_FBSIZE (UG2864HSWEG01_XSTRIDE * UG2864HSWEG01_YRES)
+#define UG2864HSWEG01_ROWSIZE (UG2864HSWEG01_XSTRIDE)
+
+/* Bit helpers */
+
+#define LS_BIT (1 << 0)
+#define MS_BIT (1 << 7)
+
+/* Debug ******************************************************************************/
+
+#ifdef CONFIG_DEBUG_LCD
+# define lcddbg(format, arg...) dbg(format, ##arg)
+# define lcdvdbg(format, arg...) vdbg(format, ##arg)
+#else
+# define lcddbg(x...)
+# define lcdvdbg(x...)
+#endif
+
+/**************************************************************************************
+ * Private Type Definition
+ **************************************************************************************/
+
+/* This structure describes the state of this driver */
+
+struct ug2864hsweg01_dev_s
+{
+ struct lcd_dev_s dev; /* Publically visible device structure */
+
+ /* Private LCD-specific information follows */
+
+ FAR struct spi_dev_s *spi; /* Cached SPI device reference */
+ uint8_t contrast; /* Current contrast setting */
+ bool on; /* true: display is on */
+
+
+ /* The SSD1306 does not support reading from the display memory in SPI mode.
+ * Since there is 1 BPP and access is byte-by-byte, it is necessary to keep
+ * a shadow copy of the framebuffer memory. At 128x64, this amounts to 1KB.
+ */
+
+ uint8_t fb[UG2864HSWEG01_FBSIZE];
+};
+
+/**************************************************************************************
+ * Private Function Protototypes
+ **************************************************************************************/
+
+/* Low-level SPI helpers */
+
+#ifdef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_configspi(FAR struct spi_dev_s *spi);
+# define ug2864hsweg01_lock(spi)
+# define ug2864hsweg01_unlock(spi)
+#else
+# define ug2864hsweg01_configspi(spi)
+static void ug2864hsweg01_lock(FAR struct spi_dev_s *spi);
+static void ug2864hsweg01_unlock(FAR struct spi_dev_s *spi);
+#endif
+
+/* LCD Data Transfer Methods */
+
+static int ug2864hsweg01_putrun(fb_coord_t row, fb_coord_t col,
+ FAR const uint8_t *buffer, size_t npixels);
+static int ug2864hsweg01_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
+ size_t npixels);
+
+/* LCD Configuration */
+
+static int ug2864hsweg01_getvideoinfo(FAR struct lcd_dev_s *dev,
+ FAR struct fb_videoinfo_s *vinfo);
+static int ug2864hsweg01_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
+ FAR struct lcd_planeinfo_s *pinfo);
+
+/* LCD RGB Mapping */
+
+#ifdef CONFIG_FB_CMAP
+# error "RGB color mapping not supported by this driver"
+#endif
+
+/* Cursor Controls */
+
+#ifdef CONFIG_FB_HWCURSOR
+# error "Cursor control not supported by this driver"
+#endif
+
+/* LCD Specific Controls */
+
+static int ug2864hsweg01_getpower(struct lcd_dev_s *dev);
+static int ug2864hsweg01_setpower(struct lcd_dev_s *dev, int power);
+static int ug2864hsweg01_getcontrast(struct lcd_dev_s *dev);
+static int ug2864hsweg01_setcontrast(struct lcd_dev_s *dev, unsigned int contrast);
+
+/**************************************************************************************
+ * Private Data
+ **************************************************************************************/
+
+/* This is working memory allocated by the LCD driver for each LCD device
+ * and for each color plane. This memory will hold one raster line of data.
+ * The size of the allocated run buffer must therefore be at least
+ * (bpp * xres / 8). Actual alignment of the buffer must conform to the
+ * bitwidth of the underlying pixel type.
+ *
+ * If there are multiple planes, they may share the same working buffer
+ * because different planes will not be operate on concurrently. However,
+ * if there are multiple LCD devices, they must each have unique run buffers.
+ */
+
+static uint8_t g_runbuffer[UG2864HSWEG01_ROWSIZE];
+
+/* This structure describes the overall LCD video controller */
+
+static const struct fb_videoinfo_s g_videoinfo =
+{
+ .fmt = UG2864HSWEG01_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
+ .xres = UG2864HSWEG01_XRES, /* Horizontal resolution in pixel columns */
+ .yres = UG2864HSWEG01_YRES, /* Vertical resolution in pixel rows */
+ .nplanes = 1, /* Number of color planes supported */
+};
+
+/* This is the standard, NuttX Plane information object */
+
+static const struct lcd_planeinfo_s g_planeinfo =
+{
+ .putrun = ug2864hsweg01_putrun, /* Put a run into LCD memory */
+ .getrun = ug2864hsweg01_getrun, /* Get a run from LCD memory */
+ .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */
+ .bpp = UG2864HSWEG01_BPP, /* Bits-per-pixel */
+};
+
+/* This is the OLED driver instance (only a single device is supported for now) */
+
+static struct ug2864hsweg01_dev_s g_oleddev =
+{
+ .dev =
+ {
+ /* LCD Configuration */
+
+ .getvideoinfo = ug2864hsweg01_getvideoinfo,
+ .getplaneinfo = ug2864hsweg01_getplaneinfo,
+
+ /* LCD RGB Mapping -- Not supported */
+ /* Cursor Controls -- Not supported */
+
+ /* LCD Specific Controls */
+
+ .getpower = ug2864hsweg01_getpower,
+ .setpower = ug2864hsweg01_setpower,
+ .getcontrast = ug2864hsweg01_getcontrast,
+ .setcontrast = ug2864hsweg01_setcontrast,
+ },
+};
+
+/**************************************************************************************
+ * Private Functions
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_configspi
+ *
+ * Description:
+ * Configure the SPI for use with the UG-2864HSWEG01
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifdef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_configspi(FAR struct spi_dev_s *spi)
+{
+ lcdvdbg("Mode: %d Bits: 8 Frequency: %d\n",
+ CONFIG_UG2864HSWEG01_SPIMODE, CONFIG_UG2864HSWEG01_FREQUENCY);
+
+ /* Configure SPI for the UG-2864HSWEG01. But only if we own the SPI bus. Otherwise,
+ * don't bother because it might change.
+ */
+
+ SPI_SETMODE(spi, CONFIG_UG2864HSWEG01_SPIMODE);
+ SPI_SETBITS(spi, 8);
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864HSWEG01_FREQUENCY);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_lock
+ *
+ * Description:
+ * Select the SPI, locking and re-configuring if necessary
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_lock(FAR struct spi_dev_s *spi)
+{
+ /* Lock the SPI bus if there are multiple devices competing for the SPI bus. */
+
+ SPI_LOCK(spi, true);
+
+ /* Now make sure that the SPI bus is configured for the UG-2864HSWEG01 (it
+ * might have gotten configured for a different device while unlocked)
+ */
+
+ SPI_SETMODE(spi, CONFIG_UG2864HSWEG01_SPIMODE);
+ SPI_SETBITS(spi, 8);
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864HSWEG01_FREQUENCY);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_unlock
+ *
+ * Description:
+ * De-select the SPI
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_unlock(FAR struct spi_dev_s *spi)
+{
+ /* De-select UG-2864HSWEG01 chip and relinquish the SPI bus. */
+
+ SPI_LOCK(spi, false);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_putrun
+ *
+ * Description:
+ * This method can be used to write a partial raster line to the LCD.
+ *
+ * Input Parameters:
+ * row - Starting row to write to (range: 0 <= row < yres)
+ * col - Starting column to write to (range: 0 <= col <= xres-npixels)
+ * buffer - The buffer containing the run to be written to the LCD
+ * npixels - The number of pixels to write to the LCD
+ * (range: 0 < npixels <= xres-col)
+ *
+ **************************************************************************************/
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+static int ug2864hsweg01_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
+ size_t npixels)
+{
+ /* Because of this line of code, we will only be able to support a single UG device */
+
+ FAR struct ug2864hsweg01_dev_s *priv = (FAR struct ug2864hsweg01_dev_s *)&g_oleddev;
+ FAR uint8_t *fbptr;
+ FAR uint8_t *ptr;
+ uint8_t devcol;
+ uint8_t fbmask;
+ uint8_t page;
+ uint8_t usrmask;
+ int pixlen;
+ uint8_t i;
+
+ lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels);
+ DEBUGASSERT(buffer);
+
+ /* Clip the run to the display */
+
+ pixlen = npixels;
+ if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG2864HSWEG01_XRES)
+ {
+ pixlen = (int)UG2864HSWEG01_XRES - (int)col;
+ }
+
+ /* Verify that some portion of the run remains on the display */
+
+ if (pixlen <= 0 || row > UG2864HSWEG01_YRES)
+ {
+ return OK;
+ }
+
+ /* Perform coordinate conversion for reverse landscape mode */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ row = (UG2864HSWEG01_YRES-1) - row;
+ col = (UG2864HSWEG01_XRES-1) - col;
+#endif
+
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
+
+ page = row >> 3;
+
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * D0 | | X | | | | |
+ * D1 | | X | | | | |
+ * D2 | | X | | | | |
+ * D3 | | X | | | | |
+ * D4 | | X | | | | |
+ * D5 | | X | | | | |
+ * D6 | | X | | | | |
+ * D7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
+
+ fbmask = 1 << (row & 7);
+ fbptr = &priv->fb[page * UG2864HSWEG01_XRES + col];
+#ifdef CONFIG_LCD_RLANDSCAPE
+ ptr = fbptr + pixlen - 1;
+#else
+ ptr = fbptr;
+#endif
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
+
+ for (i = 0; i < pixlen; i++)
+ {
+ /* Set or clear the corresponding bit */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ if ((*buffer & usrmask) != 0)
+ {
+ *ptr-- |= fbmask;
+ }
+ else
+ {
+ *ptr-- &= ~fbmask;
+ }
+#else
+ if ((*buffer & usrmask) != 0)
+ {
+ *ptr++ |= fbmask;
+ }
+ else
+ {
+ *ptr++ &= ~fbmask;
+ }
+#endif
+
+ /* Inc/Decrement to the next source pixel */
+
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
+ {
+ buffer++;
+ usrmask = MS_BIT;
+ }
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
+ {
+ buffer++;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
+ }
+#endif
+ }
+
+ /* Offset the column position to account for smaller horizontal
+ * display range.
+ */
+
+ devcol = col + UG2864HSWEG01_DEV_XOFFSET;
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the starting position for the run */
+ /* Set the column address to the XOFFSET value */
+
+ SPI_SEND(priv->spi, SSD1306_SETCOLL(devcol & 0x0f));
+ SPI_SEND(priv->spi, SSD1306_SETCOLH(devcol >> 4));
+
+ /* Set the page address */
+
+ SPI_SEND(priv->spi, SSD1306_PAGEADDR(page));
+
+ /* Select data transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, false);
+
+ /* Then transfer all of the data */
+
+ (void)SPI_SNDBLOCK(priv->spi, fbptr, pixlen);
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+#else
+# error "Configuration not implemented"
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getrun
+ *
+ * Description:
+ * This method can be used to read a partial raster line from the LCD:
+ *
+ * Description:
+ * This method can be used to write a partial raster line to the LCD.
+ *
+ * row - Starting row to read from (range: 0 <= row < yres)
+ * col - Starting column to read read (range: 0 <= col <= xres-npixels)
+ * buffer - The buffer in which to return the run read from the LCD
+ * npixels - The number of pixels to read from the LCD
+ * (range: 0 < npixels <= xres-col)
+ *
+ **************************************************************************************/
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+static int ug2864hsweg01_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
+ size_t npixels)
+{
+ /* Because of this line of code, we will only be able to support a single UG device */
+
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+ FAR uint8_t *fbptr;
+ uint8_t page;
+ uint8_t fbmask;
+ uint8_t usrmask;
+ int pixlen;
+ uint8_t i;
+
+ lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels);
+ DEBUGASSERT(buffer);
+
+ /* Clip the run to the display */
+
+ pixlen = npixels;
+ if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG2864HSWEG01_XRES)
+ {
+ pixlen = (int)UG2864HSWEG01_XRES - (int)col;
+ }
+
+ /* Verify that some portion of the run is actually the display */
+
+ if (pixlen <= 0 || row > UG2864HSWEG01_YRES)
+ {
+ return -EINVAL;
+ }
+
+ /* Perform coordinate conversion for reverse landscape mode */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ row = (UG2864HSWEG01_YRES-1) - row;
+ col = (UG2864HSWEG01_XRES-1) - col;
+#endif
+
+ /* Then transfer the display data from the shadow frame buffer memory */
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
+
+ page = row >> 3;
+
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * D0 | | X | | | | |
+ * D1 | | X | | | | |
+ * D2 | | X | | | | |
+ * D3 | | X | | | | |
+ * D4 | | X | | | | |
+ * D5 | | X | | | | |
+ * D6 | | X | | | | |
+ * D7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
+
+ fbmask = 1 << (row & 7);
+#ifdef CONFIG_LCD_RLANDSCAPE
+ fbptr = &priv->fb[page * (UG2864HSWEG01_XRES-1) + col + pixlen];
+#else
+ fbptr = &priv->fb[page * UG2864HSWEG01_XRES + col];
+#endif
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
+
+ *buffer = 0;
+ for (i = 0; i < pixlen; i++)
+ {
+ /* Set or clear the corresponding bit */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ uint8_t byte = *fbptr--;
+#else
+ uint8_t byte = *fbptr++;
+#endif
+ if ((byte & fbmask) != 0)
+ {
+ *buffer |= usrmask;
+ }
+
+ /* Inc/Decrement to the next destination pixel. Hmmmm. It looks like
+ * this logic could write past the end of the user buffer. Revisit
+ * this!
+ */
+
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
+ {
+ buffer++;
+ *buffer = 0;
+ usrmask = MS_BIT;
+ }
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
+ {
+ buffer++;
+ *buffer = 0;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
+ }
+#endif
+ }
+
+ return OK;
+}
+#else
+# error "Configuration not implemented"
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getvideoinfo
+ *
+ * Description:
+ * Get information about the LCD video controller configuration.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getvideoinfo(FAR struct lcd_dev_s *dev,
+ FAR struct fb_videoinfo_s *vinfo)
+{
+ DEBUGASSERT(dev && vinfo);
+ lcdvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n",
+ g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes);
+ memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s));
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getplaneinfo
+ *
+ * Description:
+ * Get information about the configuration of each LCD color plane.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
+ FAR struct lcd_planeinfo_s *pinfo)
+{
+ DEBUGASSERT(pinfo && planeno == 0);
+ lcdvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp);
+ memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s));
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getpower
+ *
+ * Description:
+ * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on. On
+ * backlit LCDs, this setting may correspond to the backlight setting.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getpower(FAR struct lcd_dev_s *dev)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = (FAR struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv);
+
+ lcdvdbg("power: %s\n", priv->on ? "ON" : "OFF");
+ return priv->on ? CONFIG_LCD_MAXPOWER : 0;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_setpower
+ *
+ * Description:
+ * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On
+ * backlit LCDs, this setting may correspond to the backlight setting.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_setpower(struct lcd_dev_s *dev, int power)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER && priv->spi);
+
+ lcdvdbg("power: %d [%d]\n", power, priv->on ? CONFIG_LCD_MAXPOWER : 0);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ if (power <= 0)
+ {
+ /* Turn the display off */
+
+ (void)SPI_SEND(priv->spi, SSD1306_DISPOFF);
+ priv->on = false;
+ }
+ else
+ {
+ /* Turn the display on */
+
+ (void)SPI_SEND(priv->spi, SSD1306_DISPON); /* Display on, dim mode */
+ priv->on = true;
+ }
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getcontrast
+ *
+ * Description:
+ * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getcontrast(struct lcd_dev_s *dev)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv);
+
+ lcdvdbg("contrast: %d\n", priv->contrast);
+ return priv->contrast;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_setcontrast
+ *
+ * Description:
+ * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ unsigned int scaled;
+
+ lcdvdbg("contrast: %d\n", contrast);
+ DEBUGASSERT(priv);
+
+ /* Verify the contrast value */
+
+#ifdef CONFIG_DEBUG
+ if (contrast > CONFIG_LCD_MAXCONTRAST)
+ {
+ return -EINVAL;
+ }
+#endif
+
+ /* Scale contrast: newcontrast = 255 * contrast / CONFIG_LCD_MAXCONTRAST
+ * Where contrast is in the range {1,255}
+ */
+
+#if CONFIG_LCD_MAXCONTRAST != 255
+ scaled = ((contrast << 8) - 1) / CONFIG_LCD_MAXCONTRAST;
+#else
+ scaled = contrast;
+#endif
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the contrast */
+
+ (void)SPI_SEND(priv->spi, SSD1306_CONTRAST_MODE); /* Set contrast control register */
+ (void)SPI_SEND(priv->spi, SSD1306_CONTRAST(scaled)); /* Data 1: Set 1 of 256 contrast steps */
+ priv->contrast = contrast;
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+
+/**************************************************************************************
+ * Public Functions
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_initialize
+ *
+ * Description:
+ * Initialize the UG-2864HSWEG01 video hardware. The initial state of the
+ * OLED is fully initialized, display memory cleared, and the OLED ready
+ * to use, but with the power setting at 0 (full off == sleep mode).
+ *
+ * Input Parameters:
+ *
+ * spi - A reference to the SPI driver instance.
+ * devno - A value in the range of 0 through CONFIG_UG2864HSWEG01_NINTERFACES-1.
+ * This allows support for multiple OLED devices.
+ *
+ * Returned Value:
+ *
+ * On success, this function returns a reference to the LCD object for
+ * the specified OLED. NULL is returned on any failure.
+ *
+ **************************************************************************************/
+
+FAR struct lcd_dev_s *ug2864hsweg01_initialize(FAR struct spi_dev_s *spi, unsigned int devno)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+
+ lcdvdbg("Initializing\n");
+ DEBUGASSERT(spi && devno == 0);
+
+ /* Save the reference to the SPI device */
+
+ priv->spi = spi;
+
+ /* Configure the SPI */
+
+ ug2864hsweg01_configspi(spi);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(spi, SPIDEV_DISPLAY, true);
+
+ /* Configure OLED SPI or I/O, must be delayed 1-10ms */
+
+ up_mdelay(5);
+
+ /* Configure the device */
+
+//#define OLED_WriteCmd(v) SPI_SEND(spi,v)
+//
+// /* Module manufacturers to provide initialization code Ä£¿é³§¼ÒÌṩ³õʼ»¯´úÂë */
+//
+// OLED_WriteCmd(0xAE); /* ¹Ø±ÕOLEDÃæ°åÏÔʾ(ÐÝÃß) */
+// OLED_WriteCmd(0x00); /* ÉèÖÃÁеØÖ·µÍ4bit */
+// OLED_WriteCmd(0x10); /* ÉèÖÃÁеØÖ·¸ß4bit */
+// OLED_WriteCmd(0x40); /* ÉèÖÃÆðʼÐеØÖ·£¨µÍ5bit 0-63£©£¬ Ó²¼þÏà¹Ø*/
+//
+// OLED_WriteCmd(0x81); /* ÉèÖöԱȶÈÃüÁî(Ë«×Ö½ÚÃüÁ£¬µÚ1¸ö×Ö½ÚÊÇÃüÁµÚ2¸ö×Ö½ÚÊǶԱȶȲÎÊý0-255 */
+// OLED_WriteCmd(0xCF); /* ÉèÖöԱȶȲÎÊý */
+//
+// OLED_WriteCmd(0xA1); /* A0 £ºÁеØÖ·0Ó³Éäµ½SEG0; A1 £ºÁеØÖ·127Ó³Éäµ½SEG0 */
+// OLED_WriteCmd(0xA6); /* A6 : ÉèÖÃÕý³£ÏÔʾģʽ; A7 : ÉèÖÃΪ·´ÏÔģʽ */
+//
+// OLED_WriteCmd(0xA8); /* ÉèÖÃCOM·Êý */
+// OLED_WriteCmd(0x3F); /* 1 ->£¨63+1£©Â· */
+//
+// OLED_WriteCmd(0xD3); /* ÉèÖÃÏÔʾƫÒÆ£¨Ë«×Ö½ÚÃüÁ*/
+// OLED_WriteCmd(0x00); /* ÎÞÆ«ÒÆ */
+//
+// OLED_WriteCmd(0xD5); /* ÉèÖÃÏÔʾʱÖÓ·ÖƵϵÊý/Õñµ´ÆµÂÊ */
+// OLED_WriteCmd(0x80); /* ÉèÖ÷ÖƵϵÊý,¸ß4bitÊÇ·ÖƵϵÊý£¬µÍ4bitÊÇÕñµ´ÆµÂÊ */
+//
+// OLED_WriteCmd(0xD9); /* ÉèÖÃÔ¤³äµçÖÜÆÚ */
+// OLED_WriteCmd(0xF1); /* [3:0],PHASE 1; [7:4],PHASE 2; */
+//
+// OLED_WriteCmd(0xDA); /* ÉèÖÃCOM½ÅÓ²¼þ½ÓÏß·½Ê½ */
+// OLED_WriteCmd(0x12);
+//
+// OLED_WriteCmd(0xDB); /* ÉèÖà vcomh µçѹ±¶ÂÊ */
+// OLED_WriteCmd(0x40); /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC */
+//
+// OLED_WriteCmd(0x8D); /* ÉèÖóäµç±Ã£¨ºÍϸöÃüÁî½áºÏʹÓã© */
+// OLED_WriteCmd(0x14); /* 0x14 ʹÄܳäµç±Ã£¬ 0x10 ÊÇ¹Ø±Õ */
+// OLED_WriteCmd(0xAF); /* ´ò¿ªOLEDÃæ°å */
+
+ SPI_SEND(spi, SSD1306_DISPOFF); /* Display off 0xAE*/
+ SPI_SEND(spi, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */
+ SPI_SEND(spi, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */
+ SPI_SEND(spi, SSD1306_STARTLINE(0)); /* Set display start line 0x40*/
+ /* SPI_SEND(spi, SSD1306_PAGEADDR(0));*//* Set page address (Can ignore)*/
+ SPI_SEND(spi, SSD1306_CONTRAST_MODE); /* Contrast control 0x81*/
+ SPI_SEND(spi ,SSD1306_CONTRAST(UG2864HSWEG01_CONTRAST)); /* Default contrast 0xCF */
+ SPI_SEND(spi, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xA1*/
+ /* SPI_SEND(spi, SSD1306_EDISPOFF); */ /* Normal display :off 0xA4 (Can ignore)*/
+ SPI_SEND(spi, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xA6 */
+ SPI_SEND(spi, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xA8*/
+ SPI_SEND(spi, SSD1306_MRATIO(0x3f)); /* Duty = 1/64 */
+ /* SPI_SEND(spi, SSD1306_SCANTOCOM0);*/ /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore)*/
+ SPI_SEND(spi, SSD1306_DISPOFFS_MODE); /* Set display offset 0xD3 */
+ SPI_SEND(spi, SSD1306_DISPOFFS(0));
+ SPI_SEND(spi, SSD1306_CLKDIV_SET); /* Set clock divider 0xD5*/
+ SPI_SEND(spi, SSD1306_CLKDIV(8,0)); /* 0x80*/
+
+ SPI_SEND(spi, SSD1306_CHRGPER_SET); /* ++Set pre-charge period 0xD9*/
+ SPI_SEND(spi, SSD1306_CHRGPER(0x0f,1)); /* 0xf1 or 0x22£¨Enhanced mode?£© */
+
+ SPI_SEND(spi, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xDA*/
+ SPI_SEND(spi, SSD1306_CMNPAD(0x12)); /* 0x12 */
+
+ SPI_SEND(spi, SSD1306_VCOM_SET); /* set vcomh 0xDB*/
+ SPI_SEND(spi, SSD1306_VCOM(0x40));
+
+ SPI_SEND(spi, SSD1306_CHRPUMP_SET); /* ++Set Charge Pump enable/disable 0x8D ssd1306*/
+ SPI_SEND(spi, SSD1306_CHRPUMP_ON); /* 0x14 close 0x10 */
+
+ /*SPI_SEND(spi, SSD1306_DCDC_MODE); */ /* DC/DC control mode: on (SSD1306 Not supported) */
+ /*SPI_SEND(spi, SSD1306_DCDC_ON); */
+
+ SPI_SEND(spi, SSD1306_DISPON); /* display ON 0xAF */
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+
+ /* Clear the display */
+
+ up_mdelay(100);
+ ug2864hsweg01_fill(&priv->dev, UG_Y1_BLACK);
+ return &priv->dev;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_fill
+ *
+ * Description:
+ * This non-standard method can be used to clear the entire display by writing one
+ * color to the display. This is much faster than writing a series of runs.
+ *
+ * Input Parameters:
+ * priv - Reference to private driver structure
+ *
+ * Assumptions:
+ * Caller has selected the OLED section.
+ *
+ **************************************************************************************/
+
+void ug2864hsweg01_fill(FAR struct lcd_dev_s *dev, uint8_t color)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+ unsigned int page;
+
+ /* Make an 8-bit version of the selected color */
+
+ if (color & 1)
+ {
+ color = 0xff;
+ }
+ else
+ {
+ color = 0;
+ }
+
+ /* Initialize the framebuffer */
+
+ memset(priv->fb, color, UG2864HSWEG01_FBSIZE);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Visit each page */
+
+ for (page = 0; page < UG2864HSWEG01_DEV_PAGES; page++)
+ {
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the column address to the XOFFSET value */
+
+ SPI_SEND(priv->spi, SSD1306_SETCOLL(UG2864HSWEG01_DEV_XOFFSET));
+ SPI_SEND(priv->spi, SSD1306_SETCOLH(0));
+
+ /* Set the page address */
+
+ SPI_SEND(priv->spi, SSD1306_PAGEADDR(page));
+
+ /* Select data transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, false);
+
+ /* Transfer one page of the selected color */
+
+ (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864HSWEG01_XRES],
+ UG2864HSWEG01_XRES);
+ }
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+}
+
+#endif /* CONFIG_LCD_UG2864HSWEG01 */
diff --git a/nuttx/drivers/mmcsd/Kconfig b/nuttx/drivers/mmcsd/Kconfig
index c224f220a..2d9a04bbb 100644
--- a/nuttx/drivers/mmcsd/Kconfig
+++ b/nuttx/drivers/mmcsd/Kconfig
@@ -2,6 +2,7 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
+
config MMCSD_NSLOTS
int "Number of MMC/SD slots"
default 1
@@ -38,8 +39,9 @@ config MMCSD_HAVECARDDETECT
100% accurate
config MMCSD_SPI
- bool "MMC/SD spi transfer support"
+ bool "MMC/SD SPI transfer support"
default y
+ depends on SPI
config MMCSD_SPICLOCK
int "MMC/SD maximum SPI clock"
@@ -51,7 +53,7 @@ config MMCSD_SPICLOCK
config MMCSD_SDIO
bool "MMC/SD sdio transfer support"
- default y
+ default n
if MMCSD_SDIO
config SDIO_DMA
diff --git a/nuttx/drivers/mtd/Make.defs b/nuttx/drivers/mtd/Make.defs
index 7db7592d4..3102f1447 100644
--- a/nuttx/drivers/mtd/Make.defs
+++ b/nuttx/drivers/mtd/Make.defs
@@ -37,6 +37,8 @@
# Include MTD drivers
+ifeq ($(CONFIG_MTD),y)
+
CSRCS += at45db.c flash_eraseall.c ftl.c m25px.c rammtd.c ramtron.c
ifeq ($(CONFIG_MTD_AT24XX),y)
@@ -60,3 +62,4 @@ endif
DEPPATH += --dep-path mtd
VPATH += :mtd
+endif
diff --git a/nuttx/drivers/usbdev/composite.c b/nuttx/drivers/usbdev/composite.c
index 4cad8af86..530d64416 100644
--- a/nuttx/drivers/usbdev/composite.c
+++ b/nuttx/drivers/usbdev/composite.c
@@ -523,12 +523,12 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
{
/* Save the configuration and inform the constituent classes */
- ret = CLASS_SETUP(priv->dev1, dev, ctrl);
+ ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen);
dispatched = true;
if (ret >= 0)
{
- ret = CLASS_SETUP(priv->dev2, dev, ctrl);
+ ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen);
if (ret >= 0)
{
priv->config = value;
diff --git a/nuttx/drivers/usbdev/pl2303.c b/nuttx/drivers/usbdev/pl2303.c
index 95f26c185..d10539fa7 100644
--- a/nuttx/drivers/usbdev/pl2303.c
+++ b/nuttx/drivers/usbdev/pl2303.c
@@ -333,7 +333,7 @@ static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
/* USB class device ********************************************************/
-static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
+static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
@@ -1295,7 +1295,7 @@ static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
priv->usbdev = dev;
/* Save the reference to our private data structure in EP0 so that it
- * can be recovered in ep0 completion events (Unless we are part of
+ * can be recovered in ep0 completion events (Unless we are part of
* a composite device and, in that case, the composite device owns
* EP0).
*/
@@ -1859,7 +1859,7 @@ static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
* re-enumerated.
*/
- DEV_CONNECT(dev);
+ DEV_CONNECT(dev);
}
/****************************************************************************
@@ -1878,7 +1878,7 @@ static int usbser_setup(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv;
- usbtrace(PL2303_CLASSASPI_SETUP, 0);
+ usbtrace(PL2303_CLASSAPI_SETUP, 0);
/* Sanity check */
@@ -1919,7 +1919,7 @@ static int usbser_setup(FAR struct uart_dev_s *dev)
static void usbser_shutdown(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_SHUTDOWN, 0);
+ usbtrace(PL2303_CLASSAPI_SHUTDOWN, 0);
/* Sanity check */
@@ -1941,7 +1941,7 @@ static void usbser_shutdown(FAR struct uart_dev_s *dev)
static int usbser_attach(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_ATTACH, 0);
+ usbtrace(PL2303_CLASSAPI_ATTACH, 0);
return OK;
}
@@ -1955,7 +1955,7 @@ static int usbser_attach(FAR struct uart_dev_s *dev)
static void usbser_detach(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_DETACH, 0);
+ usbtrace(PL2303_CLASSAPI_DETACH, 0);
}
/****************************************************************************
@@ -1981,7 +1981,7 @@ static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable)
FAR uart_dev_t *serdev;
irqstate_t flags;
- usbtrace(PL2303_CLASSASPI_RXINT, (uint16_t)enable);
+ usbtrace(PL2303_CLASSAPI_RXINT, (uint16_t)enable);
/* Sanity check */
@@ -2072,7 +2072,7 @@ static void usbser_txint(FAR struct uart_dev_s *dev, bool enable)
{
FAR struct pl2303_dev_s *priv;
- usbtrace(PL2303_CLASSASPI_TXINT, (uint16_t)enable);
+ usbtrace(PL2303_CLASSAPI_TXINT, (uint16_t)enable);
/* Sanity checks */
@@ -2117,7 +2117,7 @@ static bool usbser_txempty(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv = (FAR struct pl2303_dev_s*)dev->priv;
- usbtrace(PL2303_CLASSASPI_TXEMPTY, 0);
+ usbtrace(PL2303_CLASSAPI_TXEMPTY, 0);
#if CONFIG_DEBUG
if (!priv)
diff --git a/nuttx/drivers/usbhost/Kconfig b/nuttx/drivers/usbhost/Kconfig
index 35695d750..531e94442 100644
--- a/nuttx/drivers/usbhost/Kconfig
+++ b/nuttx/drivers/usbhost/Kconfig
@@ -2,6 +2,7 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
+
config USBHOST_NPREALLOC
int "Number of pre-allocated class instances"
default 4
@@ -29,64 +30,85 @@ config USBHOST_ISOC_DISABLE
On some architectures, selecting this setting will reduce driver size
by disabling isochronous endpoint support
+config USBHOST_MSC
+ bool "Mass Storage Class Support"
+ default n
+ depends on !BULK_DISABLE
+ ---help---
+ Enable support for the keyboard class driver. This also depends on
+ NFILE_DESCRIPTORS > 0 && SCHED_WORKQUEUE=y
+
config USBHOST_HIDKBD
- bool "HID keyboad class support"
+ bool "HID Keyboard Class Support"
default n
- depends on !USBHOST_INT_DISABLE && SCHED_WORKQUEUE && !DISABLE_SIGNALS
+ depends on !INT_DISABLE
+ ---help---
+ Enable support for the keyboard class driver. This also depends on
+ SCHED_WORKQUEUE && !DISABLE_SIGNALS
if USBHOST_HIDKBD
config HIDKBD_POLLUSEC
- bool ""
- default n
+ int "Keyboard Poll Rate (MSEC)"
+ default 100000
---help---
- Device poll rate in microseconds. Default: 100 milliseconds.
+ Device poll rate in microseconds. Default: 100,000 microseconds.
config HIDKBD_DEFPRIO
- bool ""
- default n
+ int "Polling Thread Priority"
+ default 50
---help---
Priority of the polling thread. Default: 50.
config HIDKBD_STACKSIZE
- bool ""
- default n
+ int "Polling thread stack size"
+ default 1024
---help---
Stack size for polling thread. Default: 1024
config HIDKBD_BUFSIZE
- bool ""
- default n
+ int "Scancode Buffer Size"
+ default 64
---help---
Scancode buffer size. Default: 64.
config HIDKBD_NPOLLWAITERS
- bool ""
- default n
+ int "Max Number of Waiters for Poll Event"
+ default 2
+ depends on !DISABLE_POLL
---help---
If the poll() method is enabled, this defines the maximum number
of threads that can be waiting for keyboard events. Default: 2.
config HIDKBD_RAWSCANCODES
- bool ""
+ bool "Use Raw Scan Codes"
+ default n
+ ---help---
+ If set to y no conversions will be made on the raw keyboard scan
+ codes. This option is useful during testing. Default: ASCII conversion.
+
+config HIDKBD_ENCODED
+ bool "Enocode Special Keys"
default n
+ depends on !HIDKBD_RAWSCANCODES && LIB_KBDCODEC
---help---
- If set to y no conversion will be made on the raw keyboard scan
- codes. Default: ASCII conversion.
+ Encode special key press events in the user buffer. In this case,
+ the user end must decode the encoded special key values using the
+ interfaces defined in include/nuttx/input/kbd_codec.h. These
+ special keys include such things as up/down arrows, home and end
+ keys, etc. If this not defined, only 7-bit print-able and control
+ ASCII characters will be provided to the user.
config HIDKBD_ALLSCANCODES
- bool ""
+ bool "Use All Scancodes"
default n
---help---
If set to y all 231 possible scancodes will be converted to
something. Default: 104 key US keyboard.
config HIDKBD_NODEBOUNCE
- bool ""
+ bool "Disable Debounce"
default n
---help---
If set to y normal debouncing is disabled. Default:
Debounce enabled (No repeat keys).
- USB host mass storage class driver. Requires USBHOST=y,
- config USBHOST_BULK_DISABLE=n, NFILE_DESCRIPTORS > 0,
- and SCHED_WORKQUEUE=y
endif
diff --git a/nuttx/drivers/usbhost/usbhost_hidkbd.c b/nuttx/drivers/usbhost/usbhost_hidkbd.c
index e69d68e7b..d6a9ceda3 100644
--- a/nuttx/drivers/usbhost/usbhost_hidkbd.c
+++ b/nuttx/drivers/usbhost/usbhost_hidkbd.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/usbhost/usbhost_hidkbd.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,11 @@
#include <nuttx/usb/usbhost.h>
#include <nuttx/usb/hid.h>
+#ifdef CONFIG_HIDKBD_ENCODED
+# include <nuttx/streams.h>
+# include <nuttx/input/kbd_codec.h>
+#endif
+
/* Don't compile if prerequisites are not met */
#if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_INT_DISABLE) && CONFIG_NFILE_DESCRIPTORS > 0
@@ -126,6 +131,22 @@
# endif
#endif
+/* We cant support encoding of special characters of unless the Keyboard
+ * CODEC is enabled.
+ */
+
+#ifndef CONFIG_LIB_KBDCODEC
+# undef CONFIG_HIDKBD_ENCODED
+#endif
+
+/* If we are using raw scancodes, then we cannot support encoding of
+ * special characters either.
+ */
+
+#ifdef CONFIG_HIDKBD_RAWSCANCODES
+# undef CONFIG_HIDKBD_ENCODED
+#endif
+
/* Driver support ***********************************************************/
/* This format is used to construct the /dev/kbd[n] device driver path. It
* defined here so that it will be used consistently in all places.
@@ -144,6 +165,23 @@
#define USBHOST_MAX_CREFS 0x7fff
+/* Debug ********************************************************************/
+/* Both CONFIG_DEBUG_INPUT and CONFIG_DEBUG_USB could apply to this file.
+ * We assume here that CONFIG_DEBUG_INPUT might be enabled separately, but
+ * CONFIG_DEBUG_USB implies both.
+ */
+
+#ifndef CONFIG_DEBUG_INPUT
+# undef idbg
+# define idbg udbg
+# undef illdbg
+# define illdbg ulldbg
+# undef ivdbg
+# define ivdbg uvdbg
+# undef illvdbg
+# define illvdbg ullvdbg
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -209,6 +247,16 @@ struct usbhost_state_s
uint8_t kbdbuffer[CONFIG_HIDKBD_BUFSIZE];
};
+/* This type is used for encoding special characters */
+
+#ifdef CONFIG_HIDKBD_ENCODED
+struct usbhost_outstream_s
+{
+ struct lib_outstream_s stream;
+ FAR struct usbhost_state_s *priv;
+};
+#endif
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -240,7 +288,15 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *dev
/* Keyboard polling thread */
static void usbhost_destroy(FAR void *arg);
+static void usbhost_putbuffer(FAR struct usbhost_state_s *priv, uint8_t keycode);
+#ifdef CONFIG_HIDKBD_ENCODED
+static void usbhost_putstream(FAR struct lib_outstream_s *this, int ch);
+#endif
static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier);
+#ifdef CONFIG_HIDKBD_ENCODED
+static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
+ uint8_t scancode, uint8_t modifier);
+#endif
static int usbhost_kbdpoll(int argc, char *argv[]);
/* Helpers for usbhost_connect() */
@@ -346,6 +402,121 @@ static struct usbhost_state_s *g_priv; /* Data passed to thread */
*/
#ifndef CONFIG_HIDKBD_RAWSCANCODES
+#ifdef CONFIG_HIDKBD_ENCODED
+
+/* The first and last scancode values with encode-able values */
+
+#define FIRST_ENCODING USBHID_KBDUSE_ENTER /* 0x28 Keyboard Return (ENTER) */
+#ifndef CONFIG_HIDKBD_ALLSCANCODES
+# define LAST_ENCODING USBHID_KBDUSE_POWER /* 0x66 Keyboard Power */
+#else
+# define LAST_ENCODING USBHID_KBDUSE_KPDHEXADECIMAL /* 0xdd Keypad Hexadecimal */
+#endif
+
+#define USBHID_NUMENCODINGS (LAST_ENCODING - FIRST_ENCODING + 1)
+
+static const uint8_t encoding[USBHID_NUMENCODINGS] =
+{
+ /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
+
+ KEYCODE_ENTER, 0, KEYCODE_FWDDEL, KEYCODE_BACKDEL, 0, 0, 0, 0,
+
+ /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
+
+ 0, KEYCODE_CAPSLOCK, KEYCODE_F1, KEYCODE_F2, KEYCODE_F3, KEYCODE_F4, KEYCODE_F5, KEYCODE_F6,
+
+ /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
+
+ KEYCODE_F7, KEYCODE_F8, KEYCODE_F9, KEYCODE_F10, KEYCODE_F11, KEYCODE_F12, KEYCODE_PRTSCRN, KEYCODE_SCROLLLOCK,
+
+ /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
+
+ KEYCODE_PAUSE, KEYCODE_INSERT, KEYCODE_HOME, KEYCODE_PAGEUP, KEYCODE_FWDDEL, KEYCODE_END, KEYCODE_PAGEDOWN, KEYCODE_RIGHT,
+
+ /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
+
+ KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_UP, KEYCODE_NUMLOCK, 0, 0, 0, 0,
+
+ /* 0x58-0x5f: Enter,1-7 */
+
+ KEYCODE_ENTER, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x60-0x66: 8-9,0,.,Non-US \,Application,Power */
+
+ 0, 0, 0, 0, 0, 0, KEYCODE_POWER,
+
+#ifdef CONFIG_HIDKBD_ALLSCANCODES
+
+ 0, /* 0x67 = */
+
+ /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
+
+ KEYCODE_F13, KEYCODE_F14, KEYCODE_F15, KEYCODE_F16, KEYCODE_F17, KEYCODE_F18, KEYCODE_F19, KEYCODE_F20,
+
+ /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
+
+ KEYCODE_F21, KEYCODE_F22, KEYCODE_F23, KEYCODE_F24, KEYCODE_EXECUTE, KEYCODE_HELP, KEYCODE_MENU, KEYCODE_SELECT,
+
+ /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
+
+ KEYCODE_STOP, KEYCODE_AGAIN, KEYCODE_UNDO, KEYCODE_CUT, KEYCODE_COPY, KEYCODE_PASTE, KEYCODE_FIND, KEYCODE_MUTE,
+
+ /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
+
+ KEYCODE_VOLUP, KEYCODE_VOLDOWN, KEYCODE_LCAPSLOCK, KEYCODE_LNUMLOCK, KEYCODE_LSCROLLLOCK, 0, 0, 0,
+
+ /* 0x88-0x8f: International 2-9 */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x90-0x97: LAN 1-8 */
+
+ KEYCODE_LANG1, KEYCODE_LANG2, KEYCODE_LANG3, KEYCODE_LANG4, KEYCODE_LANG5, KEYCODE_LANG6, KEYCODE_LANG7, KEYCODE_LANG8,
+
+ /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
+
+ 0, 0, KEYCODE_SYSREQ, KEYCODE_CANCEL, KEYCODE_CLEAR, 0, KEYCODE_ENTER, 0,
+
+ /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xa8-0xaf: (reserved) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xb8-0xbf: {,},tab,backspace,A-D */
+
+ 0, 0, 0, KEYCODE_BACKDEL, 0, 0, 0, 0,
+
+ /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
+
+ KEYCODE_MEMSTORE, KEYCODE_MEMRECALL, KEYCODE_MEMCLEAR, KEYCODE_MEMADD, KEYCODE_MEMSUB, KEYCODE_MEMMUL, KEYCODE_MEMDIV, KEYCODE_NEGATE,
+
+ /* 0xd8-0xdd: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
+
+ KEYCODE_CLEAR, KEYCODE_CLEARENTRY, KEYCODE_BINARY, KEYCODE_OCTAL, KEYCODE_DECIMAL, KEYCODE_HEXADECIMAL
+#endif
+};
+
+#endif
+
static const uint8_t ucmap[USBHID_NUMSCANCODES] =
{
0, 0, 0, 0, 'A', 'B', 'C', 'D', /* 0x00-0x07: Reserved, errors, A-D */
@@ -354,12 +525,12 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x18-0x1f: U-Z,!,@ */
'#', '$', '%', '^', '&', '*', '(', ')', /* 0x20-0x27: #,$,%,^,&,*,(,) */
'\n', '\033', '\177', 0, ' ', '_', '+', '{', /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
- '}', '|', 0, ':', '"', 0, '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tidle,<,> */
+ '}', '|', 0, ':', '"', '~', '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
'?', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,sScrollLock */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
- '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */
+ '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
'8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
#ifdef CONFIG_HIDKBD_ALLSCANCODES
0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
@@ -368,7 +539,7 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
- 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
+ 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@@ -389,12 +560,12 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
'u', 'v', 'w', 'x', 'y', 'z', '1', '2', /* 0x18-0x1f: u-z,1-2 */
'3', '4', '5', '6', '7', '8', '9', '0', /* 0x20-0x27: 3-9,0 */
'\n', '\033', '\177', '\t', ' ', '-', '=', '[', /* 0x28-0x2f: Enter,escape,del,tab,space,-,=,[ */
- ']', '\\', '\234', ';', '\'', 0, ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */
+ ']', '\\', '\234', ';', '\'', '`', ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */
'/', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
- '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */
+ '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
'8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
#ifdef CONFIG_HIDKBD_ALLSCANCODES
0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
@@ -403,7 +574,7 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
- 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
+ 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@@ -638,6 +809,88 @@ static void usbhost_destroy(FAR void *arg)
}
/****************************************************************************
+ * Name: usbhost_putbuffer
+ *
+ * Description:
+ * Add one character to the user buffer.
+ *
+ * Input Parameters:
+ * priv - Driver internal state
+ * keycode - The value to add to the user buffer
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
+ uint8_t keycode)
+{
+ register unsigned int head;
+ register unsigned int tail;
+
+ /* Copy the next keyboard character into the user buffer. */
+
+ head = priv->headndx;
+ priv->kbdbuffer[head] = keycode;
+
+ /* Increment the head index */
+
+ if (++head >= CONFIG_HIDKBD_BUFSIZE)
+ {
+ head = 0;
+ }
+
+ /* If the buffer is full, then increment the tail index to make space. Is
+ * it better to lose old keystrokes or new?
+ */
+
+ tail = priv->tailndx;
+ if (tail == head)
+ {
+ if (++tail >= CONFIG_HIDKBD_BUFSIZE)
+ {
+ tail = 0;
+ }
+
+ /* Save the updated tail index */
+
+ priv->tailndx = tail;
+ }
+
+ /* Save the updated head index */
+
+ priv->headndx = head;
+}
+
+/****************************************************************************
+ * Name: usbhost_putstream
+ *
+ * Description:
+ * A wrapper for usbhost_putc that is compatibile with the lib_outstream_s
+ * putc methos.
+ *
+ * Input Parameters:
+ * stream - The struct lib_outstream_s reference
+ * ch - The character to add to the user buffer
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_HIDKBD_ENCODED
+static void usbhost_putstream(FAR struct lib_outstream_s *stream, int ch)
+{
+ FAR struct usbhost_outstream_s *privstream = (FAR struct usbhost_outstream_s *)stream;
+
+ DEBUGASSERT(privstream && privstream->priv);
+ usbhost_putbuffer(privstream->priv, (uint8_t)ch);
+ stream->nput++;
+}
+#endif
+
+/****************************************************************************
* Name: usbhost_mapscancode
*
* Description:
@@ -680,6 +933,58 @@ static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier)
}
/****************************************************************************
+ * Name: usbhost_encodescancode
+ *
+ * Description:
+ * Check if the key has a special function encoding and, if it does, add
+ * the encoded value to the user buffer.
+ *
+ * Input Parameters:
+ * priv - Driver internal state
+ * scancode - Scan code to be mapped.
+ * modifier - Ctrl,Alt,Shift,GUI modifier bits
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_HIDKBD_ENCODED
+static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
+ uint8_t scancode, uint8_t modifier)
+{
+ uint8_t encoded;
+
+ /* Check if the raw scancode is in a valid range */
+
+ if (scancode >= FIRST_ENCODING && scancode <= LAST_ENCODING)
+ {
+ /* Yes the value is within range */
+
+ encoded = encoding[scancode - FIRST_ENCODING];
+ ivdbg(" scancode: %02x modifier: %02x encoded: %d\n",
+ scancode, modifier, encoded);
+
+ if (encoded)
+ {
+ struct usbhost_outstream_s usbstream;
+
+ /* And it does correspond to a special function key */
+
+ usbstream.stream.put = usbhost_putstream;
+ usbstream.stream.nput = 0;
+ usbstream.priv = priv;
+
+ /* Add the special function value to the user buffer */
+
+ kbd_specpress((enum kbd_keycode_e)encoded,
+ (FAR struct lib_outstream_s *)&usbstream);
+ }
+ }
+}
+#endif
+
+/****************************************************************************
* Name: usbhost_kbdpoll
*
* Description:
@@ -704,6 +1009,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
unsigned int npolls = 0;
#endif
unsigned int nerrors = 0;
+ bool empty = true;
+ bool newstate;
int ret;
uvdbg("Started\n");
@@ -717,17 +1024,18 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* running.
*/
- priv = g_priv;
- DEBUGASSERT(priv != NULL);
+ priv = g_priv;
+ DEBUGASSERT(priv != NULL);
- priv->polling = true;
- priv->crefs++;
- usbhost_givesem(&g_syncsem);
- sleep(1);
+ priv->polling = true;
+ priv->crefs++;
+ usbhost_givesem(&g_syncsem);
+ sleep(1);
/* Loop here until the device is disconnected */
uvdbg("Entering poll loop\n");
+
while (!priv->disconnected)
{
/* Make sure that we have exclusive access to the private data
@@ -784,17 +1092,12 @@ static int usbhost_kbdpoll(int argc, char *argv[])
else if (priv->open)
{
struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer;
- unsigned int head;
- unsigned int tail;
- uint8_t ascii;
+ uint8_t keycode;
int i;
/* Add the newly received keystrokes to our internal buffer */
usbhost_takesem(&priv->exclsem);
- head = priv->headndx;
- tail = priv->tailndx;
-
for (i = 0; i < 6; i++)
{
/* Is this key pressed? But not pressed last time?
@@ -828,15 +1131,15 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* or cursor controls in this version of the driver.
*/
- ascii = usbhost_mapscancode(rpt->key[i], rpt->modifier);
- uvdbg("Key %d: %02x ASCII:%c modifier: %02x\n",
- i, rpt->key[i], ascii ? ascii : ' ', rpt->modifier);
+ keycode = usbhost_mapscancode(rpt->key[i], rpt->modifier);
+ ivdbg("Key %d: %02x keycode:%c modifier: %02x\n",
+ i, rpt->key[i], keycode ? keycode : ' ', rpt->modifier);
/* Zero at this point means that the key does not map to a
* printable character.
*/
- if (ascii != 0)
+ if (keycode != 0)
{
/* Handle control characters. Zero after this means
* a valid, NUL character.
@@ -844,36 +1147,28 @@ static int usbhost_kbdpoll(int argc, char *argv[])
if ((rpt->modifier & (USBHID_MODIFER_LCTRL|USBHID_MODIFER_RCTRL)) != 0)
{
- ascii &= 0x1f;
+ keycode &= 0x1f;
}
/* Copy the next keyboard character into the user
* buffer.
*/
- priv->kbdbuffer[head] = ascii;
-
- /* Increment the head index */
-
- if (++head >= CONFIG_HIDKBD_BUFSIZE)
- {
- head = 0;
- }
+ usbhost_putbuffer(priv, keycode);
+ }
- /* If the buffer is full, then increment the tail
- * index to make space. Is it better to lose old
- * keystrokes or new?
- */
+ /* The zero might, however, map to a special keyboard action (such as a
+ * cursor movement or function key). Attempt to encode the special key.
+ */
- if (tail == head)
- {
- if (++tail >= CONFIG_HIDKBD_BUFSIZE)
- {
- tail = 0;
- }
- }
+#ifdef CONFIG_HIDKBD_ENCODED
+ else
+ {
+ usbhost_encodescancode(priv, rpt->key[i], rpt->modifier);
}
+#endif
}
+
/* Save the scancode (or lack thereof) for key debouncing on
* next keyboard report.
*/
@@ -883,9 +1178,10 @@ static int usbhost_kbdpoll(int argc, char *argv[])
#endif
}
- /* Did we just transition from no data available to data available? */
+ /* Is there data available? */
- if (head != tail && priv->headndx == priv->tailndx)
+ newstate = (priv->headndx == priv->tailndx);
+ if (!newstate)
{
/* Yes.. Is there a thread waiting for keyboard data now? */
@@ -897,15 +1193,18 @@ static int usbhost_kbdpoll(int argc, char *argv[])
priv->waiting = false;
}
- /* And wake up any threads waiting for the POLLIN event */
+ /* Did we just transition from no data available to data
+ * available? If so, wake up any threads waiting for the
+ * POLLIN event.
+ */
- usbhost_pollnotify(priv);
+ if (empty)
+ {
+ usbhost_pollnotify(priv);
+ }
}
- /* Update the head/tail indices */
-
- priv->headndx = head;
- priv->tailndx = tail;
+ empty = newstate;
usbhost_givesem(&priv->exclsem);
}
@@ -958,6 +1257,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
usbhost_givesem(&priv->exclsem);
}
+
return 0;
}
@@ -1861,6 +2161,7 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
/* Wait for data to be available */
uvdbg("Waiting...\n");
+
priv->waiting = true;
usbhost_givesem(&priv->exclsem);
usbhost_takesem(&priv->waitsem);
diff --git a/nuttx/fs/Kconfig b/nuttx/fs/Kconfig
index 1d1046735..dfbfda3fa 100644
--- a/nuttx/fs/Kconfig
+++ b/nuttx/fs/Kconfig
@@ -5,11 +5,12 @@
comment "File system configuration"
-source fs/fat/Kconfig
source fs/mmap/Kconfig
+source fs/fat/Kconfig
source fs/nfs/Kconfig
source fs/nxffs/Kconfig
source fs/romfs/Kconfig
+source fs/binfs/Kconfig
comment "System Logging"
diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile
index 6955c164b..2a1fd75a8 100644
--- a/nuttx/fs/Makefile
+++ b/nuttx/fs/Makefile
@@ -1,7 +1,7 @@
############################################################################
# fs/Makefile
#
-# Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007, 2008, 2011-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -72,6 +72,9 @@ CSRCS += fs_registerdriver.c fs_unregisterdriver.c
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c \
fs_findblockdriver.c fs_openblockdriver.c fs_closeblockdriver.c
+DEPPATH =
+VPATH = .
+
include mmap/Make.defs
# Stream support
@@ -91,13 +94,17 @@ endif
# Additional files required is mount-able file systems are supported
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
+
CSRCS += fs_fsync.c fs_mkdir.c fs_mount.c fs_rename.c fs_rmdir.c \
fs_umount.c fs_unlink.c
CSRCS += fs_foreachmountpoint.c
+
include fat/Make.defs
include romfs/Make.defs
include nxffs/Make.defs
include nfs/Make.defs
+include binfs/Make.defs
+
endif
endif
@@ -108,8 +115,7 @@ OBJS = $(AOBJS) $(COBJS)
BIN = libfs$(LIBEXT)
-SUBDIRS = mmap fat romfs nxffs:nfs
-VPATH = mmap:fat:romfs:nxffs:nfs
+SUBDIRS = mmap fat romfs nxffs nfs binfs
all: $(BIN)
@@ -123,8 +129,7 @@ $(BIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
.depend: Makefile $(SRCS)
- $(Q) $(MKDEP) --dep-path . $(MMAPDEPPATH) $(FATDEPPATH) $(ROMFSDEPPATH) $(NXFFSDEPPATH) $(NFSDEPPATH) \
- "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
+ $(Q) $(MKDEP) --dep-path . $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
diff --git a/nuttx/fs/binfs/Kconfig b/nuttx/fs/binfs/Kconfig
new file mode 100644
index 000000000..eedbe497d
--- /dev/null
+++ b/nuttx/fs/binfs/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config FS_BINFS
+ bool "BINFS File System"
+ default n
+ depends on BUILTIN
+ ---help---
+ The BINFS file system is provides access to builtin applications through
+ the NuttX file system. The BINFS may, for example, be mount at /bin.
+ Then all of the built-in applications will appear as executable files in
+ /bin. Then, for example, you list them from NSH like:
+
+ nsh> ls -l /bin
+
+ If the BINFS BINFMT loader is also enabled, then the builtin applications
+ can be executed through the normal mechanisms (posix_spawn(), exev(), etc.)
diff --git a/nuttx/fs/binfs/Make.defs b/nuttx/fs/binfs/Make.defs
new file mode 100644
index 000000000..a65b7367f
--- /dev/null
+++ b/nuttx/fs/binfs/Make.defs
@@ -0,0 +1,48 @@
+############################################################################
+# fs/binfs/Make.defs
+#
+# Copyright (C) 2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name Nuttx nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+ifeq ($(CONFIG_FS_BINFS),y)
+# Files required for BINFS file system support
+
+ASRCS +=
+CSRCS += fs_binfs.c
+
+# Include BINFS build support
+
+DEPPATH += --dep-path binfs
+VPATH += :binfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)binfs}
+
+endif
diff --git a/apps/namedapp/binfs.c b/nuttx/fs/binfs/fs_binfs.c
index 36e3ace92..56ea472af 100644
--- a/apps/namedapp/binfs.c
+++ b/nuttx/fs/binfs/fs_binfs.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * apps/namedapps/binfs.c
+ * fs/binfs/fs_binfs.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
@@ -53,49 +52,44 @@
#include <debug.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/fs/binfs.h>
#include <nuttx/fs/dirent.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/binfmt/builtin.h>
-#include "namedapp.h"
-
-#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_APPS_BINDIR)
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_BINFS)
/****************************************************************************
* Private Types
****************************************************************************/
-/* This structure represents the overall mountpoint state. An instance of this
- * structure is retained as inode private data on each mountpoint that is
- * mounted with a fat32 filesystem.
- */
-
-struct binfs_state_s
-{
- sem_t bm_sem; /* Used to assume thread-safe access */
-};
-
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-static void binfs_semtake(struct binfs_state_s *bm);
-static inline void binfs_semgive(struct binfs_state_s *bm);
static int binfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode);
+ int oflags, mode_t mode);
static int binfs_close(FAR struct file *filep);
static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp);
+
static int binfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
-static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
-static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int binfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
+static int binfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
-static int binfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle);
-static int binfs_unbind(void *handle, FAR struct inode **blkdriver);
-static int binfs_statfs(struct inode *mountpt, struct statfs *buf);
+static int binfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+static int binfs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+static int binfs_statfs(FAR struct inode *mountpt,
+ FAR struct statfs *buf);
-static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
+static int binfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
/****************************************************************************
* Private Variables
@@ -118,7 +112,9 @@ const struct mountpt_operations binfs_operations =
NULL, /* write */
NULL, /* seek */
binfs_ioctl, /* ioctl */
+
NULL, /* sync */
+ binfs_dup, /* dup */
binfs_opendir, /* opendir */
NULL, /* closedir */
@@ -141,70 +137,41 @@ const struct mountpt_operations binfs_operations =
****************************************************************************/
/****************************************************************************
- * Name: binfs_semtake
- ****************************************************************************/
-
-static void binfs_semtake(struct binfs_state_s *bm)
-{
- /* Take the semaphore (perhaps waiting) */
-
- while (sem_wait(&bm->bm_sem) != 0)
- {
- /* The only case that an error should occur here is if
- * the wait was awakened by a signal.
- */
-
- ASSERT(errno == EINTR);
- }
-}
-
-/****************************************************************************
- * Name: binfs_semgive
- ****************************************************************************/
-
-static inline void binfs_semgive(struct binfs_state_s *bm)
-{
- sem_post(&bm->bm_sem);
-}
-
-/****************************************************************************
* Name: binfs_open
****************************************************************************/
-static int binfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode)
+static int binfs_open(FAR struct file *filep, FAR const char *relpath,
+ int oflags, mode_t mode)
{
- struct binfs_state_s *bm;
- int ret = -ENOSYS;
+ int index;
fvdbg("Open '%s'\n", relpath);
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
-
- /* mountpoint private data from the inode reference from the file
- * structure
- */
-
- bm = (struct binfs_state_s*)filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
/* BINFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*/
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
{
- fdbg("Only O_RDONLY supported\n");
- ret = -EACCES;
+ fdbg("ERROR: Only O_RDONLY supported\n");
+ return -EACCES;
}
- /* Save open-specific state in filep->f_priv */
+ /* Check if the an entry exists with this name in the root directory.
+ * so the 'relpath' must be the name of the builtin function.
+ */
+
+ index = builtin_isavail(relpath);
+ if (index < 0)
+ {
+ fdbg("ERROR: Builting %s does not exist\n", relpath);
+ return -ENOENT;
+ }
- /* Opening of elements within the pseudo-file system is not yet supported */
+ /* Save the index as the open-specific state in filep->f_priv */
- return ret;
+ filep->f_priv = (FAR void *)index;
+ return OK;
}
/****************************************************************************
@@ -213,31 +180,8 @@ static int binfs_open(FAR struct file *filep, const char *relpath,
static int binfs_close(FAR struct file *filep)
{
- struct binfs_state_s *bm;
- int ret = -ENOSYS;
-
fvdbg("Closing\n");
-
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
-
- /* Recover the open file state from the struct file instance */
- /* bf = filep->f_priv; */
-
- /* Recover the file system state from the inode */
-
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
- /* Free the open file state */
- /* free(bf); */
-
- filep->f_priv = NULL;
-
- /* Since open() is not yet supported, neither is close(). */
-
- return ret;
+ return OK;
}
/****************************************************************************
@@ -246,25 +190,10 @@ static int binfs_close(FAR struct file *filep)
static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen)
{
- struct binfs_state_s *bm;
+ /* Reading is not supported. Just return end-of-file */
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
-
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
-
- /* Recover the open file state data from the struct file instance */
- /* bf = filep->f_priv; */
-
- /* Recover the file system state from the inode */
-
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
- /* Since open is not yet supported, neither is reading */
-
- return -ENOSYS;
+ return 0;
}
/****************************************************************************
@@ -273,25 +202,54 @@ static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen)
static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
- struct binfs_state_s *bm;
+ int ret;
fvdbg("cmd: %d arg: %08lx\n", cmd, arg);
- /* Sanity checks */
+ /* Only one IOCTL command is supported */
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
+ if (cmd == FIOC_FILENAME)
+ {
+ /* IN: FAR char const ** pointer
+ * OUT: Pointer to a persistent file name (Guaranteed to persist while
+ * the file is open).
+ */
- /* Recover the open file state from the struct file instance */
- /* bf = filep->f_priv; */
+ FAR const char **ptr = (FAR const char **)((uintptr_t)arg);
+ if (ptr == NULL)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ *ptr = builtin_getname((int)filep->f_priv);
+ ret = OK;
+ }
+ }
+ else
+ {
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
- /* Recover the file system state from the inode */
+/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
+static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ fvdbg("Dup %p->%p\n", oldp, newp);
- /* No ioctl commands yet supported */
+ /* Copy the index from the old to the new file structure */
- return -ENOTTY;
+ newp->f_priv = oldp->f_priv;
+ return OK;
}
/****************************************************************************
@@ -305,36 +263,19 @@ static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
static int binfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
- int ret;
-
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* The requested directory must be the volume-relative "root" directory */
if (relpath && relpath[0] != '\0')
{
- ret = -ENOENT;
- goto errout_with_semaphore;
+ return -ENOENT;
}
/* Set the index to the first entry */
dir->u.binfs.fb_index = 0;
- ret = OK;
-
-errout_with_semaphore:
- binfs_semgive(bm);
- return ret;
+ return OK;
}
/****************************************************************************
@@ -346,23 +287,15 @@ errout_with_semaphore:
static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
+ FAR const char *name;
unsigned int index;
int ret;
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* Have we reached the end of the directory */
index = dir->u.binfs.fb_index;
- if (namedapps[index].name == NULL)
+ name = builtin_getname(index);
+ if (name == NULL)
{
/* We signal the end of the directory by returning the
* special error -ENOENT
@@ -375,9 +308,9 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
/* Save the filename and file type */
- fvdbg("Entry %d: \"%s\"\n", index, namedapps[index].name);
+ fvdbg("Entry %d: \"%s\"\n", index, name);
dir->fd_dir.d_type = DTYPE_FILE;
- strncpy(dir->fd_dir.d_name, namedapps[index].name, NAME_MAX+1);
+ strncpy(dir->fd_dir.d_name, name, NAME_MAX+1);
/* The application list is terminated by an entry with a NULL name.
* Therefore, there is at least one more entry in the list.
@@ -389,11 +322,10 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
* standard f_pos instead of our own private fb_index.
*/
- dir->u.binfs.fb_index = index;
- ret = OK;
+ dir->u.binfs.fb_index = index;
+ ret = OK;
}
- binfs_semgive(bm);
return ret;
}
@@ -406,22 +338,9 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
- dir->u.binfs.fb_index = 0;
-
- binfs_semgive(bm);
+ dir->u.binfs.fb_index = 0;
return OK;
}
@@ -439,29 +358,7 @@ static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
static int binfs_bind(FAR struct inode *blkdriver, const void *data,
void **handle)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
-
- /* Create an instance of the mountpt state structure */
-
- bm = (struct binfs_state_s *)zalloc(sizeof(struct binfs_state_s));
- if (!bm)
- {
- fdbg("Failed to allocate mountpoint structure\n");
- return -ENOMEM;
- }
-
- /* Initialize the allocated mountpt state structure. The filesystem is
- * responsible for one reference ont the blkdriver inode and does not
- * have to addref() here (but does have to release in ubind().
- */
-
- sem_init(&bm->bm_sem, 0, 1); /* Initialize the semaphore that controls access */
-
- /* Mounted! */
-
- *handle = (void*)bm;
return OK;
}
@@ -475,22 +372,7 @@ static int binfs_bind(FAR struct inode *blkdriver, const void *data,
static int binfs_unbind(void *handle, FAR struct inode **blkdriver)
{
- struct binfs_state_s *bm = (struct binfs_state_s*)handle;
-
fvdbg("Entry\n");
-
-#ifdef CONFIG_DEBUG
- if (!bm)
- {
- return -EINVAL;
- }
-#endif
-
- /* Check if there are sill any files opened on the filesystem. */
-
- /* Release the mountpoint private data */
-
- sem_destroy(&bm->bm_sem);
return OK;
}
@@ -503,19 +385,8 @@ static int binfs_unbind(void *handle, FAR struct inode **blkdriver)
static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt && mountpt->i_private);
-
- /* Get the mountpoint private data from the inode structure */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* Fill in the statfs info */
memset(buf, 0, sizeof(struct statfs));
@@ -525,8 +396,6 @@ static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_namelen = NAME_MAX;
-
- binfs_semgive(bm);
return OK;
}
@@ -539,30 +408,17 @@ static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf)
{
- struct binfs_state_s *bm;
- int ret;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt && mountpt->i_private);
-
- /* Get the mountpoint private data from the inode structure */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* The requested directory must be the volume-relative "root" directory */
if (relpath && relpath[0] != '\0')
{
/* Check if there is a file with this name. */
- if (namedapp_isavail(relpath) < 0)
+ if (builtin_isavail(relpath) < 0)
{
- ret = -ENOENT;
- goto errout_with_semaphore;
+ return -ENOENT;
}
/* It's a execute-only file name */
@@ -578,19 +434,15 @@ static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *b
/* File/directory size, access block size */
- buf->st_size = 0;
- buf->st_blksize = 0;
- buf->st_blocks = 0;
- ret = OK;
-
-errout_with_semaphore:
- binfs_semgive(bm);
- return ret;
+ buf->st_size = 0;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
-#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_APPS_BINDIR */
+#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_BINFS */
diff --git a/nuttx/fs/fat/Make.defs b/nuttx/fs/fat/Make.defs
index 136302b86..2769ab602 100644
--- a/nuttx/fs/fat/Make.defs
+++ b/nuttx/fs/fat/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# Make.defs
#
-# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2008, 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,10 @@ CSRCS += fs_fat32.c fs_fat32dirent.c fs_fat32attrib.c fs_fat32util.c
ASRCS +=
CSRCS += fs_mkfatfs.c fs_configfat.c fs_writefat.c
-# Argument for dependency checking
+# Include FAT build support
+
+DEPPATH += --dep-path fat
+VPATH += :fat
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)fat}
-FATDEPPATH = --dep-path fat
endif
diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c
index 0c28cea67..c10c28a5c 100644
--- a/nuttx/fs/fat/fs_fat32.c
+++ b/nuttx/fs/fat/fs_fat32.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fat/fs_fat32.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@@ -86,7 +86,9 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer,
size_t buflen);
static off_t fat_seek(FAR struct file *filep, off_t offset, int whence);
static int fat_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+
static int fat_sync(FAR struct file *filep);
+static int fat_dup(FAR const struct file *oldp, FAR struct file *newp);
static int fat_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
@@ -121,28 +123,30 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat
const struct mountpt_operations fat_operations =
{
- fat_open,
- fat_close,
- fat_read,
- fat_write,
- fat_seek,
- fat_ioctl,
- fat_sync,
-
- fat_opendir,
- NULL,
- fat_readdir,
- fat_rewinddir,
-
- fat_bind,
- fat_unbind,
- fat_statfs,
-
- fat_unlink,
- fat_mkdir,
- fat_rmdir,
- fat_rename,
- fat_stat
+ fat_open, /* open */
+ fat_close, /* close */
+ fat_read, /* read */
+ fat_write, /* write */
+ fat_seek, /* seek */
+ fat_ioctl, /* ioctl */
+
+ fat_sync, /* sync */
+ fat_dup, /* dup */
+
+ fat_opendir, /* opendir */
+ NULL, /* closedir */
+ fat_readdir, /* readdir */
+ fat_rewinddir, /* rewinddir */
+
+ fat_bind, /* bind */
+ fat_unbind, /* unbind */
+ fat_statfs, /* statfs */
+
+ fat_unlink, /* unlinke */
+ fat_mkdir, /* mkdir */
+ fat_rmdir, /* rmdir */
+ fat_rename, /* rename */
+ fat_stat /* stat */
};
/****************************************************************************
@@ -311,7 +315,6 @@ static int fat_open(FAR struct file *filep, const char *relpath,
/* Initialize the file private data (only need to initialize non-zero elements) */
- ff->ff_open = true;
ff->ff_oflags = oflags;
/* Save information that can be used later to recover the directory entry */
@@ -896,6 +899,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence)
DEBUGASSERT(fs != NULL);
/* Map the offset according to the whence option */
+
switch (whence)
{
case SEEK_SET: /* The offset is set to offset bytes. */
@@ -969,6 +973,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence)
ret = cluster;
goto errout_with_semaphore;
}
+
ff->ff_startcluster = cluster;
}
@@ -1231,6 +1236,124 @@ errout_with_semaphore:
}
/****************************************************************************
+ * Name: fat_dup
+ *
+ * Description: Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int fat_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ FAR struct fat_mountpt_s *fs;
+ FAR struct fat_file_s *oldff;
+ FAR struct fat_file_s *newff;
+ int ret;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL &&
+ newp->f_priv == NULL &&
+ newp->f_inode != NULL);
+
+ /* Recover our private data from the struct file instance */
+
+ fs = (struct fat_mountpt_s *)oldp->f_inode->i_private;
+ DEBUGASSERT(fs != NULL);
+
+ /* Check if the mount is still healthy */
+
+ fat_semtake(fs);
+ ret = fat_checkmount(fs);
+ if (ret != OK)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Recover the old private data from the old struct file instance */
+
+ oldff = oldp->f_priv;
+
+ /* Create a new instance of the file private date to describe the
+ * dup'ed file.
+ */
+
+ newff = (struct fat_file_s *)kmalloc(sizeof(struct fat_file_s));
+ if (!newff)
+ {
+ ret = -ENOMEM;
+ goto errout_with_semaphore;
+ }
+
+ /* Create a file buffer to support partial sector accesses */
+
+ newff->ff_buffer = (uint8_t*)fat_io_alloc(fs->fs_hwsectorsize);
+ if (!newff->ff_buffer)
+ {
+ ret = -ENOMEM;
+ goto errout_with_struct;
+ }
+
+ /* Copy the rest of the open open file state from the old file structure.
+ * There are some assumptions and potential issues here:
+ *
+ * 1) We assume that the higher level logic has copied the elements of
+ * the file structure, in particular, the file position.
+ * 2) There is a problem with ff_size if there are multiple opened
+ * file structures, each believing they know the size of the file.
+ * If one instance modifies the file length, then the new size of
+ * the opened file will be unknown to the other. That is a lurking
+ * bug!
+ *
+ * One good solution to this might be to add a refernce count to the
+ * file structure. Then, instead of dup'ing the whole structure
+ * as is done here, just increment the reference count on the
+ * structure. The would have to be integrated with open logic as
+ * well, however, so that the same file structure is re-used if the
+ * file is re-opened.
+ */
+
+ newff->ff_bflags = 0; /* File buffer flags */
+ newff->ff_oflags = oldff->ff_oflags; /* File open flags */
+ newff->ff_sectorsincluster = oldff->ff_sectorsincluster; /* Sectors remaining in cluster */
+ newff->ff_dirindex = oldff->ff_dirindex; /* Index to directory entry */
+ newff->ff_currentcluster = oldff->ff_currentcluster; /* Current cluster */
+ newff->ff_dirsector = oldff->ff_dirsector; /* Sector containing directory entry */
+ newff->ff_size = oldff->ff_size; /* Size of the file */
+ newff->ff_startcluster = oldff->ff_startcluster; /* Start cluster of file on media */
+ newff->ff_currentsector = oldff->ff_currentsector; /* Current sector */
+ newff->ff_cachesector = 0; /* Sector in file buffer */
+
+ /* Attach the private date to the struct file instance */
+
+ newp->f_priv = newff;
+
+ /* Then insert the new instance into the mountpoint structure.
+ * It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy
+ * (but a simple reference count could have done that).
+ */
+
+ newff->ff_next = fs->fs_head;
+ fs->fs_head = newff->ff_next;
+
+ fat_semgive(fs);
+ return OK;
+
+ /* Error exits -- goto's are nasty things, but they sure can make error
+ * handling a lot simpler.
+ */
+
+errout_with_struct:
+ kfree(newff);
+
+errout_with_semaphore:
+ fat_semgive(fs);
+ return ret;
+}
+
+/****************************************************************************
* Name: fat_opendir
*
* Description: Open a directory for read access
diff --git a/nuttx/fs/fat/fs_fat32.h b/nuttx/fs/fat/fs_fat32.h
index 71a21333b..81f3f4675 100644
--- a/nuttx/fs/fat/fs_fat32.h
+++ b/nuttx/fs/fat/fs_fat32.h
@@ -752,7 +752,6 @@ struct fat_mountpt_s
struct fat_file_s
{
struct fat_file_s *ff_next; /* Retained in a singly linked list */
- bool ff_open; /* true: The file is (still) open */
uint8_t ff_bflags; /* The file buffer flags */
uint8_t ff_oflags; /* Flags provided when file was opened */
uint8_t ff_sectorsincluster; /* Sectors remaining in cluster */
diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c
index 7231456d7..9aa1d3992 100644
--- a/nuttx/fs/fat/fs_fat32util.c
+++ b/nuttx/fs/fat/fs_fat32util.c
@@ -692,8 +692,6 @@ int fat_checkmount(struct fat_mountpt_s *fs)
if (fs && fs->fs_mounted)
{
- struct fat_file_s *file;
-
/* We still think the mount is healthy. Check an see if this is
* still the case
*/
@@ -715,14 +713,8 @@ int fat_checkmount(struct fat_mountpt_s *fs)
/* If we get here, the mount is NOT healthy */
fs->fs_mounted = false;
-
- /* Make sure that this is flagged in every opened file */
-
- for (file = fs->fs_head; file; file = file->ff_next)
- {
- file->ff_open = false;
- }
}
+
return -ENODEV;
}
diff --git a/nuttx/fs/fs_files.c b/nuttx/fs/fs_files.c
index 4da2d28a5..06addb1ef 100644
--- a/nuttx/fs/fs_files.c
+++ b/nuttx/fs/fs_files.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_files.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -284,14 +284,6 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2)
goto errout;
}
-#ifndef CONFIG_DISABLE_MOUNTPOINT
- if (INODE_IS_MOUNTPT(filep1->f_inode))
- {
- err = ENOSYS; /* Not yet supported */
- goto errout;
- }
-#endif
-
list = sched_getfiles();
if (!list)
{
@@ -331,18 +323,16 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2)
if (inode->u.i_ops && inode->u.i_ops->open)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
-#if 0 /* Not implemented */
if (INODE_IS_MOUNTPT(inode))
{
- /* Open a file on the mountpoint */
+ /* Dup the open file on the in the new file structure */
- ret = inode->u.i_mops->open(filep2, ?, filep2->f_oflags, ?);
+ ret = inode->u.i_mops->dup(filep1, filep2);
}
else
#endif
-#endif
{
- /* Open the pseudo file or device driver */
+ /* (Re-)open the pseudo file or device driver */
ret = inode->u.i_ops->open(filep2);
}
diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c
index 228c1fc6e..a91e7d366 100644
--- a/nuttx/fs/fs_mount.c
+++ b/nuttx/fs/fs_mount.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_mount.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,10 +47,6 @@
#include <nuttx/fs/fs.h>
-#ifdef CONFIG_APPS_BINDIR
-# include <apps/apps.h>
-#endif
-
#include "fs_internal.h"
/* At least one filesystem must be defined, or this file will not compile.
@@ -78,7 +74,7 @@
/* These file systems do not require block drivers */
-#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS)
+#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_FS_BINFS) || defined(CONFIG_NFS)
# define NONBDFS_SUPPORT
#endif
@@ -123,6 +119,9 @@ extern const struct mountpt_operations nxffs_operations;
#ifdef CONFIG_NFS
extern const struct mountpt_operations nfs_operations;
#endif
+#ifdef CONFIG_FS_BINFS
+extern const struct mountpt_operations binfs_operations;
+#endif
static const struct fsmap_t g_nonbdfsmap[] =
{
@@ -132,7 +131,7 @@ static const struct fsmap_t g_nonbdfsmap[] =
#ifdef CONFIG_NFS
{ "nfs", &nfs_operations },
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
{ "binfs", &binfs_operations },
#endif
{ NULL, NULL },
@@ -222,7 +221,7 @@ int mount(FAR const char *source, FAR const char *target,
/* Find the specified filesystem. Try the block driver file systems first */
#ifdef BDFS_SUPPORT
- if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
+ if (source && (mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
{
/* Make sure that a block driver argument was provided */
diff --git a/nuttx/fs/mmap/Make.defs b/nuttx/fs/mmap/Make.defs
index 59857fe9c..b85d9f60f 100644
--- a/nuttx/fs/mmap/Make.defs
+++ b/nuttx/fs/mmap/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/mmap/Make.defs
#
-# Copyright (C) 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -40,4 +40,9 @@ ifeq ($(CONFIG_FS_RAMMAP),y)
CSRCS += fs_munmap.c fs_rammap.c
endif
-MMAPDEPPATH = --dep-path mmap
+# Include MMAP build support
+
+DEPPATH += --dep-path mmap
+VPATH += :mmap
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)mmap}
+
diff --git a/nuttx/fs/nfs/Make.defs b/nuttx/fs/nfs/Make.defs
index fc4682f85..ec2177fcf 100644
--- a/nuttx/fs/nfs/Make.defs
+++ b/nuttx/fs/nfs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# Make.defs
#
-# Copyright (C) 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,10 @@ CSRCS +=
ASRCS +=
CSRCS += rpc_clnt.c nfs_util.c nfs_vfsops.c
-# Argument for dependency checking
+# Include NFS build support
+
+DEPPATH += --dep-path nfs
+VPATH += :nfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)nfs}
-NFSDEPPATH = --dep-path nfs
endif
diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h
index 4ae9e162c..408bd1993 100644
--- a/nuttx/fs/nfs/nfs_node.h
+++ b/nuttx/fs/nfs/nfs_node.h
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_node.h
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -70,6 +70,7 @@
struct nfsnode
{
struct nfsnode *n_next; /* Retained in a singly linked list. */
+ uint8_t n_crefs; /* Reference count (for nfs_dup) */
uint8_t n_type; /* File type */
uint8_t n_fhsize; /* Size in bytes of the file handle */
uint8_t n_flags; /* Node flags */
diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c
index 73fda72a7..e7d28b3d7 100644
--- a/nuttx/fs/nfs/nfs_util.c
+++ b/nuttx/fs/nfs/nfs_util.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_util.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -213,7 +213,6 @@ int nfs_request(struct nfsmount *nmp, int procnum,
{
struct rpcclnt *clnt = nmp->nm_rpcclnt;
struct nfs_reply_header replyh;
- int trylater_delay;
int error;
tryagain:
@@ -250,12 +249,6 @@ tryagain:
if (error == EAGAIN)
{
error = 0;
- trylater_delay *= NFS_TIMEOUTMUL;
- if (trylater_delay > NFS_MAXTIMEO)
- {
- trylater_delay = NFS_MAXTIMEO;
- }
-
goto tryagain;
}
diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c
index 3cd5a47dc..2ff4ff9d3 100644
--- a/nuttx/fs/nfs/nfs_vfsops.c
+++ b/nuttx/fs/nfs/nfs_vfsops.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_vfsops.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -133,6 +133,7 @@ static int nfs_close(FAR struct file *filep);
static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
size_t buflen);
+static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int nfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
@@ -166,7 +167,9 @@ const struct mountpt_operations nfs_operations =
nfs_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
+
NULL, /* sync */
+ nfs_dup, /* dup */
nfs_opendir, /* opendir */
NULL, /* closedir */
@@ -357,7 +360,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
/* Save the attributes in the file data structure */
- tmp = *ptr++; /* handle_follows */
+ tmp = *ptr; /* handle_follows */
if (!tmp)
{
fdbg("WARNING: no file attributes\n");
@@ -367,7 +370,6 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
/* Initialize the file attributes */
nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr);
- ptr += uint32_increment(sizeof(struct nfs_fattr));
}
/* Any following dir_wcc data is ignored for now */
@@ -410,7 +412,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
reqlen += (int)np->n_fhsize;
ptr += uint32_increment(np->n_fhsize);
- /* Copy the variable-length attribtes */
+ /* Copy the variable-length attributes */
*ptr++ = nfs_false; /* Don't change mode */
*ptr++ = nfs_false; /* Don't change uid */
@@ -421,7 +423,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = nfs_false; /* No guard value */
- reqlen += 9*sizeof(uint32_t)
+ reqlen += 9 * sizeof(uint32_t);
/* Perform the SETATTR RPC */
@@ -551,9 +553,9 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np,
static int nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
- struct nfsmount *nmp;
- struct nfsnode *np = NULL;
- int error;
+ struct nfsmount *nmp;
+ struct nfsnode *np;
+ int error;
/* Sanity checks */
@@ -632,6 +634,8 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
* non-zero elements)
*/
+ np->n_crefs = 1;
+
/* Attach the private data to the struct file instance */
filep->f_priv = np;
@@ -654,6 +658,7 @@ errout_with_semaphore:
{
kfree(np);
}
+
nfs_semgive(nmp);
return -error;
}
@@ -675,6 +680,7 @@ static int nfs_close(FAR struct file *filep)
FAR struct nfsnode *np;
FAR struct nfsnode *prev;
FAR struct nfsnode *curr;
+ int ret;
/* Sanity checks */
@@ -691,42 +697,64 @@ static int nfs_close(FAR struct file *filep)
nfs_semtake(nmp);
- /* Find our file structure in the list of file structures containted in the
- * mount structure.
+ /* Decrement the reference count. If the reference count would not
+ * decrement to zero, then that is all we have to do.
*/
- for (prev = NULL, curr = nmp->nm_head; curr; prev = curr, curr = curr->n_next)
- {
- /* Check if this node is ours */
+ if (np->n_crefs > 1)
+ {
+ np->n_crefs--;
+ ret = OK;
+ }
- if (np == curr)
- {
- /* Yes.. remove it from the list of file structures */
+ /* There are no more references to the file structure. Now we need to
+ * free up all resources associated with the open file.
+ *
+ * First, find our file structure in the list of file structures
+ * containted in the mount structure.
+ */
+
+ else
+ {
+ /* Assume file structure will not be found. This should never happen. */
+
+ ret = -EINVAL;
+
+ for (prev = NULL, curr = nmp->nm_head;
+ curr;
+ prev = curr, curr = curr->n_next)
+ {
+ /* Check if this node is ours */
- if (prev)
- {
- /* Remove from mid-list */
+ if (np == curr)
+ {
+ /* Yes.. remove it from the list of file structures */
- prev->n_next = np->n_next;
- }
- else
- {
- /* Remove from the head of the list */
+ if (prev)
+ {
+ /* Remove from mid-list */
- nmp->nm_head = np->n_next;
- }
+ prev->n_next = np->n_next;
+ }
+ else
+ {
+ /* Remove from the head of the list */
- /* Then deallocate the file structure and return success */
+ nmp->nm_head = np->n_next;
+ }
- kfree(np);
- nfs_semgive(nmp);
- return OK;
- }
- }
+ /* Then deallocate the file structure and return success */
- fdbg("ERROR: file structure not found in list: %p\n", np);
+ kfree(np);
+ ret = OK;
+ break;
+ }
+ }
+ }
+
+ filep->f_priv = NULL;
nfs_semgive(nmp);
- return EINVAL;
+ return ret;
}
/****************************************************************************
@@ -757,8 +785,8 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
/* Recover our private data from the struct file instance */
- nmp = (struct nfsmount*) filep->f_inode->i_private;
- np = (struct nfsnode*) filep->f_priv;
+ nmp = (struct nfsmount*)filep->f_inode->i_private;
+ np = (struct nfsnode*)filep->f_priv;
DEBUGASSERT(nmp != NULL);
@@ -1092,6 +1120,66 @@ errout_with_semaphore:
}
/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ struct nfsmount *nmp;
+ FAR struct nfsnode *np;
+ int error;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL && oldp->f_inode != NULL);
+
+ /* Recover our private data from the struct file instance */
+
+ nmp = (struct nfsmount*)oldp->f_inode->i_private;
+ np = (struct nfsnode*)oldp->f_priv;
+
+ DEBUGASSERT(nmp != NULL);
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = nfs_checkmount(nmp);
+ if (error != OK)
+ {
+ fdbg("ERROR: nfs_checkmount failed: %d\n", error);
+ nfs_semgive(nmp);
+ return -error;
+ }
+
+ /* Increment the reference count on the NFS node structure */
+
+ DEBUGASSERT(np->n_crefs < 0xff);
+ np->n_crefs++;
+
+ /* And save this as the file data for the new node */
+
+ newp->f_priv = np;
+
+ /* Then insert the new instance at the head of the list in the mountpoint
+ * tructure. It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy. We
+ * cannot unmount the file system if this list is not empty!
+ */
+
+ np->n_next = nmp->nm_head;
+ nmp->nm_head = np;
+
+ nfs_semgive(nmp);
+ return OK;
+}
+
+/****************************************************************************
* Name: nfs_opendir
*
* Description:
@@ -1754,12 +1842,15 @@ bad:
{
kfree(nmp->nm_so);
}
+
if (nmp->nm_rpcclnt)
{
kfree(nmp->nm_rpcclnt);
}
+
kfree(nmp);
}
+
return error;
}
diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c
index 0e2a394ba..9c2ada4f2 100644
--- a/nuttx/fs/nfs/rpc_clnt.c
+++ b/nuttx/fs/nfs/rpc_clnt.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/rpc_clnt.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -224,8 +224,6 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
FAR void *reply, size_t resplen)
{
- FAR struct rpc_reply_header *replyheader;
- uint32_t rxid;
int error;
/* Get the next RPC reply from the socket */
@@ -235,22 +233,22 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
{
fdbg("ERROR: rpcclnt_receive returned: %d\n", error);
- /* If we failed because of a timeout, then try sending the CALL
- * message again.
- */
+ /* If we failed because of a timeout, then try sending the CALL
+ * message again.
+ */
- if (error == EAGAIN || error == ETIMEDOUT)
- {
- rpc->rc_timeout = true;
- }
- }
+ if (error == EAGAIN || error == ETIMEDOUT)
+ {
+ rpc->rc_timeout = true;
+ }
+ }
/* Get the xid and check that it is an RPC replysvr */
else
{
- replyheader = (FAR struct rpc_reply_header *)reply;
- rxid = replyheader->rp_xid;
+ FAR struct rpc_reply_header *replyheader =
+ (FAR struct rpc_reply_header *)reply;
if (replyheader->rp_direction != rpc_reply)
{
@@ -260,7 +258,7 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
}
}
- return OK;
+ return error;
}
/****************************************************************************
@@ -275,7 +273,6 @@ static uint32_t rpcclnt_newxid(void)
{
static uint32_t rpcclnt_xid = 0;
static uint32_t rpcclnt_xid_touched = 0;
- int xidp = 0;
srand(time(NULL));
if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0))
@@ -285,6 +282,7 @@ static uint32_t rpcclnt_newxid(void)
}
else
{
+ int xidp = 0;
do
{
xidp = rand();
diff --git a/nuttx/fs/nxffs/Make.defs b/nuttx/fs/nxffs/Make.defs
index b67ae4472..ccf1ba661 100644
--- a/nuttx/fs/nxffs/Make.defs
+++ b/nuttx/fs/nxffs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/nxffs/Make.defs
#
-# Copyright (C) 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,10 @@ CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c \
nxffs_open.c nxffs_pack.c nxffs_read.c nxffs_reformat.c \
nxffs_stat.c nxffs_unlink.c nxffs_util.c nxffs_write.c
-# Argument for dependency checking
+# Include NXFFS build support
+
+DEPPATH += --dep-path nxffs
+VPATH += :nxffs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)nxffs}
-NXFFSDEPPATH = --dep-path nxffs
endif
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h
index 616dc7197..083e00fa7 100644
--- a/nuttx/fs/nxffs/nxffs.h
+++ b/nuttx/fs/nxffs/nxffs.h
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs.h
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -1044,6 +1044,7 @@ extern int nxffs_pack(FAR struct nxffs_volume_s *volume);
* - nxffs_read() is defined in nxffs_read.c
* - nxffs_write() is defined in nxffs_write.c
* - nxffs_ioctl() is defined in nxffs_ioctl.c
+ * - nxffs_dup() is defined in nxffs_open.c
* - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in
* nxffs_dirent.c
* - nxffs_bind() and nxffs_unbind() are defined in nxffs_initialize.c
@@ -1058,25 +1059,25 @@ struct fs_dirent_s;
struct statfs;
struct stat;
-extern int nxffs_open(FAR struct file *filep, FAR const char *relpath,
- int oflags, mode_t mode);
-extern int nxffs_close(FAR struct file *filep);
-extern ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer,
- size_t buflen);
-extern ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
- size_t buflen);
-extern int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
-extern int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
- FAR struct fs_dirent_s *dir);
-extern int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
-extern int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
-extern int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data,
- FAR void **handle);
-extern int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver);
-extern int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
-extern int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
- FAR struct stat *buf);
-extern int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
+int nxffs_open(FAR struct file *filep, FAR const char *relpath, int oflags,
+ mode_t mode);
+int nxffs_close(FAR struct file *filep);
+ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
+ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
+ size_t buflen);
+int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp);
+int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
+int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
+int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
+int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
+int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
#endif /* __FS_NXFFS_NXFFS_H */
diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c
index 6d93a318a..4e7428c73 100644
--- a/nuttx/fs/nxffs/nxffs_initialize.c
+++ b/nuttx/fs/nxffs/nxffs_initialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_initialize.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -82,7 +82,9 @@ const struct mountpt_operations nxffs_operations =
nxffs_write, /* write */
NULL, /* seek -- Use f_pos in struct file */
nxffs_ioctl, /* ioctl */
+
NULL, /* sync -- No buffered data */
+ nxffs_dup, /* dup */
nxffs_opendir, /* opendir */
NULL, /* closedir */
diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c
index eb7817c57..9fa4ef2e0 100644
--- a/nuttx/fs/nxffs/nxffs_open.c
+++ b/nuttx/fs/nxffs/nxffs_open.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_open.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -1023,7 +1023,7 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath,
#endif
/* Limitation: A file must be opened for reading or writing, but not both.
- * There is no general for extending the size of of a file. Extending the
+ * There is no general way of extending the size of a file. Extending the
* file size of possible if the file to be extended is the last in the
* sequence on FLASH, but since that case is not the general case, no file
* extension is supported.
@@ -1059,6 +1059,64 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath,
}
/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+#ifdef CONFIG_DEBUG
+ FAR struct nxffs_volume_s *volume;
+#endif
+ FAR struct nxffs_ofile_s *ofile;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+#ifdef CONFIG_DEBUG
+ DEBUGASSERT(oldp->f_priv == NULL && oldp->f_inode != NULL);
+
+ /* Get the mountpoint private data from the NuttX inode reference in the
+ * file structure
+ */
+
+ volume = (FAR struct nxffs_volume_s*)oldp->f_inode->i_private;
+ DEBUGASSERT(volume != NULL);
+#endif
+
+ /* Recover the open file state from the struct file instance */
+
+ ofile = (FAR struct nxffs_ofile_s *)oldp->f_priv;
+
+ /* I do not think we need exclusive access to the volume to do this.
+ * The volume exclsem protects the open file list and, hence, would
+ * assure that the ofile is stable. However, it is assumed that the
+ * caller holds a value file descriptor associated with this ofile,
+ * so it should be stable throughout the life of this function.
+ */
+
+ /* Limitations: I do not think we have to be concerned about the
+ * usual NXFFS file limitations here: dup'ing cannot resulting
+ * in mixed reading and writing to the same file, or multiple
+ * writer to different file.
+ *
+ * I notice that nxffs_wropen will prohibit multiple opens for
+ * writing. But I do not thing that dup'ing a file already opened
+ * for writing suffers from any of these issues.
+ */
+
+ /* Just increment the reference count on the ofile */
+
+ ofile->crefs++;
+ newp->f_priv = (FAR void *)ofile;
+ return OK;
+}
+
+/****************************************************************************
* Name: nxffs_close
*
* Description:
@@ -1130,9 +1188,10 @@ int nxffs_close(FAR struct file *filep)
ofile->crefs--;
}
- filep->f_priv = NULL;
+ filep->f_priv = NULL;
sem_post(&volume->exclsem);
+
errout:
return ret;
}
diff --git a/nuttx/fs/romfs/Make.defs b/nuttx/fs/romfs/Make.defs
index 77de93c05..e87cbdf9e 100644
--- a/nuttx/fs/romfs/Make.defs
+++ b/nuttx/fs/romfs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/romfs/Make.defs
#
-# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2008, 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,10 @@ ifeq ($(CONFIG_FS_ROMFS),y)
ASRCS +=
CSRCS += fs_romfs.c fs_romfsutil.c
-# Argument for dependency checking
+# Include ROMFS build support
+
+DEPPATH += --dep-path romfs
+VPATH += :romfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)romfs}
-ROMFSDEPPATH = --dep-path romfs
endif
diff --git a/nuttx/fs/romfs/fs_romfs.c b/nuttx/fs/romfs/fs_romfs.c
index b95619d75..6a6fca355 100644
--- a/nuttx/fs/romfs/fs_romfs.c
+++ b/nuttx/fs/romfs/fs_romfs.c
@@ -56,6 +56,7 @@
#include <errno.h>
#include <debug.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/fs/dirent.h>
@@ -70,24 +71,33 @@
* Private Function Prototypes
****************************************************************************/
-static int romfs_open(FAR struct file *filep, const char *relpath,
+static int romfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int romfs_close(FAR struct file *filep);
-static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen);
+static ssize_t romfs_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence);
-static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int romfs_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
-static int romfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir);
-static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
-static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp);
-static int romfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle);
-static int romfs_unbind(void *handle, FAR struct inode **blkdriver);
-static int romfs_statfs(struct inode *mountpt, struct statfs *buf);
+static int romfs_opendir(FAR struct inode *mountpt,
+ FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+static int romfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
+static int romfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
-static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
+static int romfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+static int romfs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+static int romfs_statfs(FAR struct inode *mountpt,
+ FAR struct statfs *buf);
+
+static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
/****************************************************************************
* Private Variables
@@ -110,7 +120,9 @@ const struct mountpt_operations romfs_operations =
NULL, /* write */
romfs_seek, /* seek */
romfs_ioctl, /* ioctl */
+
NULL, /* sync */
+ romfs_dup, /* dup */
romfs_opendir, /* opendir */
NULL, /* closedir */
@@ -136,13 +148,13 @@ const struct mountpt_operations romfs_operations =
* Name: romfs_open
****************************************************************************/
-static int romfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode)
+static int romfs_open(FAR struct file *filep, FAR const char *relpath,
+ int oflags, mode_t mode)
{
- struct romfs_dirinfo_s dirinfo;
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- int ret;
+ struct romfs_dirinfo_s dirinfo;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ int ret;
fvdbg("Open '%s'\n", relpath);
@@ -150,11 +162,11 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
- /* mountpoint private data from the inode reference from the file
+ /* Get mountpoint private data from the inode reference from the file
* structure
*/
- rm = (struct romfs_mountpt_s*)filep->f_inode->i_private;
+ rm = (FAR struct romfs_mountpt_s*)filep->f_inode->i_private;
DEBUGASSERT(rm != NULL);
@@ -214,7 +226,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
* file.
*/
- rf = (struct romfs_file_s *)zalloc(sizeof(struct romfs_file_s));
+ rf = (FAR struct romfs_file_s *)kzalloc(sizeof(struct romfs_file_s));
if (!rf)
{
fdbg("Failed to allocate private data\n", ret);
@@ -226,8 +238,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
* non-zero elements)
*/
- rf->rf_open = true;
- rf->rf_size = dirinfo.rd_size;
+ rf->rf_size = dirinfo.rd_size;
/* Get the start of the file data */
@@ -277,9 +288,9 @@ errout_with_semaphore:
static int romfs_close(FAR struct file *filep)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- int ret = OK;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ int ret = OK;
fvdbg("Closing\n");
@@ -307,12 +318,12 @@ static int romfs_close(FAR struct file *filep)
if (!rm->rm_xipbase && rf->rf_buffer)
{
- free(rf->rf_buffer);
+ kfree(rf->rf_buffer);
}
/* Then free the file structure itself. */
- free(rf);
+ kfree(rf);
filep->f_priv = NULL;
return ret;
}
@@ -321,19 +332,20 @@ static int romfs_close(FAR struct file *filep)
* Name: romfs_read
****************************************************************************/
-static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen)
+static ssize_t romfs_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- unsigned int bytesread;
- unsigned int readsize;
- unsigned int nsectors;
- uint32_t offset;
- size_t bytesleft;
- off_t sector;
- uint8_t *userbuffer = (uint8_t*)buffer;
- int sectorndx;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ unsigned int bytesread;
+ unsigned int readsize;
+ unsigned int nsectors;
+ uint32_t offset;
+ size_t bytesleft;
+ off_t sector;
+ FAR uint8_t *userbuffer = (FAR uint8_t*)buffer;
+ int sectorndx;
+ int ret;
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
@@ -467,10 +479,10 @@ errout_with_semaphore:
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- off_t position;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ off_t position;
+ int ret;
fvdbg("Seek to offset: %d whence: %d\n", offset, whence);
@@ -548,9 +560,9 @@ errout_with_semaphore:
static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- FAR void **ppv = (FAR void**)arg;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ FAR void **ppv = (FAR void**)arg;
fvdbg("cmd: %d arg: %08lx\n", cmd, arg);
@@ -582,6 +594,95 @@ static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
/****************************************************************************
+ * Name: romfs_dup
+ ****************************************************************************/
+
+static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *oldrf;
+ FAR struct romfs_file_s *newrf;
+ int ret;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL &&
+ newp->f_priv == NULL &&
+ newp->f_inode != NULL);
+
+ /* Get mountpoint private data from the inode reference from the file
+ * structure
+ */
+
+ rm = (FAR struct romfs_mountpt_s*)newp->f_inode->i_private;
+ DEBUGASSERT(rm != NULL);
+
+ /* Check if the mount is still healthy */
+
+ romfs_semtake(rm);
+ ret = romfs_checkmount(rm);
+ if (ret != OK)
+ {
+ fdbg("romfs_checkmount failed: %d\n", ret);
+ goto errout_with_semaphore;
+ }
+
+ /* Recover the old private data from the old struct file instance */
+
+ oldrf = oldp->f_priv;
+
+ /* Create an new instance of the file private data to describe the new
+ * dup'ed file.
+ */
+
+ newrf = (FAR struct romfs_file_s *)kmalloc(sizeof(struct romfs_file_s));
+ if (!newrf)
+ {
+ fdbg("Failed to allocate private data\n", ret);
+ ret = -ENOMEM;
+ goto errout_with_semaphore;
+ }
+
+ /* Copy all file private data (except for the buffer) */
+
+ newrf->rf_startoffset = oldrf->rf_startoffset;
+ newrf->rf_size = oldrf->rf_size;
+
+ /* Configure buffering to support access to this file */
+
+ ret = romfs_fileconfigure(rm, newrf);
+ if (ret < 0)
+ {
+ fdbg("Failed configure buffering: %d\n", ret);
+ goto errout_with_semaphore;
+ }
+
+ /* Attach the new private date to the new struct file instance */
+
+ newp->f_priv = newrf;
+
+ /* Then insert the new instance into the mountpoint structure.
+ * It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy
+ * (but a simple reference count could have done that).
+ */
+
+ newrf->rf_next = rm->rm_head;
+ rm->rm_head = newrf->rf_next;
+
+ romfs_semgive(rm);
+ return OK;
+
+ /* Error exits */
+
+errout_with_semaphore:
+ romfs_semgive(rm);
+ return ret;
+}
+
+/****************************************************************************
* Name: romfs_opendir
*
* Description:
@@ -589,12 +690,12 @@ static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
*
****************************************************************************/
-static int romfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir)
+static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
- struct romfs_dirinfo_s dirinfo;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_dirinfo_s dirinfo;
+ int ret;
fvdbg("relpath: '%s'\n", relpath);
@@ -654,14 +755,15 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int romfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
- uint32_t linkoffset;
- uint32_t next;
- uint32_t info;
- uint32_t size;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ uint32_t linkoffset;
+ uint32_t next;
+ uint32_t info;
+ uint32_t size;
+ int ret;
fvdbg("Entry\n");
@@ -749,9 +851,10 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int romfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
+ FAR struct romfs_mountpt_s *rm;
int ret;
fvdbg("Entry\n");
@@ -788,8 +891,8 @@ static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
*
****************************************************************************/
-static int romfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle)
+static int romfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle)
{
struct romfs_mountpt_s *rm;
int ret;
@@ -813,7 +916,7 @@ static int romfs_bind(FAR struct inode *blkdriver, const void *data,
/* Create an instance of the mountpt state structure */
- rm = (struct romfs_mountpt_s *)zalloc(sizeof(struct romfs_mountpt_s));
+ rm = (FAR struct romfs_mountpt_s *)kzalloc(sizeof(struct romfs_mountpt_s));
if (!rm)
{
fdbg("Failed to allocate mountpoint structure\n");
@@ -857,12 +960,12 @@ static int romfs_bind(FAR struct inode *blkdriver, const void *data,
errout_with_buffer:
if (!rm->rm_xipbase)
{
- free(rm->rm_buffer);
+ kfree(rm->rm_buffer);
}
errout_with_sem:
sem_destroy(&rm->rm_sem);
- free(rm);
+ kfree(rm);
return ret;
}
@@ -874,9 +977,9 @@ errout_with_sem:
*
****************************************************************************/
-static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
+static int romfs_unbind(FAR void *handle, FAR struct inode **blkdriver)
{
- struct romfs_mountpt_s *rm = (struct romfs_mountpt_s*)handle;
+ FAR struct romfs_mountpt_s *rm = (FAR struct romfs_mountpt_s*)handle;
int ret;
fvdbg("Entry\n");
@@ -929,11 +1032,11 @@ static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
if (!rm->rm_xipbase && rm->rm_buffer)
{
- free(rm->rm_buffer);
+ kfree(rm->rm_buffer);
}
sem_destroy(&rm->rm_sem);
- free(rm);
+ kfree(rm);
return OK;
}
@@ -948,10 +1051,10 @@ static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
*
****************************************************************************/
-static int romfs_statfs(struct inode *mountpt, struct statfs *buf)
+static int romfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
{
- struct romfs_mountpt_s *rm;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ int ret;
fvdbg("Entry\n");
@@ -1004,11 +1107,12 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf)
+static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf)
{
- struct romfs_mountpt_s *rm;
- struct romfs_dirinfo_s dirinfo;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_dirinfo_s dirinfo;
+ int ret;
fvdbg("Entry\n");
diff --git a/nuttx/fs/romfs/fs_romfs.h b/nuttx/fs/romfs/fs_romfs.h
index 4081517fb..6a337d2c5 100644
--- a/nuttx/fs/romfs/fs_romfs.h
+++ b/nuttx/fs/romfs/fs_romfs.h
@@ -159,7 +159,6 @@ struct romfs_mountpt_s
struct romfs_file_s
{
struct romfs_file_s *rf_next; /* Retained in a singly linked list */
- bool rf_open; /* true: The file is (still) open */
uint32_t rf_startoffset; /* Offset to the start of the file data */
uint32_t rf_size; /* Size of the file in bytes */
uint32_t rf_cachesector; /* Current sector in the rf_buffer */
diff --git a/nuttx/fs/romfs/fs_romfsutil.c b/nuttx/fs/romfs/fs_romfsutil.c
index 6ea114b5e..4857fb6d3 100644
--- a/nuttx/fs/romfs/fs_romfsutil.c
+++ b/nuttx/fs/romfs/fs_romfsutil.c
@@ -613,7 +613,7 @@ int romfs_fsconfigure(struct romfs_mountpt_s *rm)
}
/****************************************************************************
- * Name: romfs_ffileconfigure
+ * Name: romfs_fileconfigure
*
* Desciption:
* This function is called as part of the ROMFS file open operation It
@@ -649,6 +649,7 @@ int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf)
return -ENOMEM;
}
}
+
return OK;
}
@@ -663,7 +664,6 @@ int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf)
int romfs_checkmount(struct romfs_mountpt_s *rm)
{
- struct romfs_file_s *file;
struct inode *inode;
struct geometry geo;
int ret;
@@ -692,14 +692,8 @@ int romfs_checkmount(struct romfs_mountpt_s *rm)
/* If we get here, the mount is NOT healthy */
rm->rm_mounted = false;
-
- /* Make sure that this is flagged in every opened file */
-
- for (file = rm->rm_head; file; file = file->rf_next)
- {
- file->rf_open = false;
- }
}
+
return -ENODEV;
}
diff --git a/nuttx/graphics/Kconfig b/nuttx/graphics/Kconfig
index 18b1e1ab9..b56a6cb5c 100644
--- a/nuttx/graphics/Kconfig
+++ b/nuttx/graphics/Kconfig
@@ -178,6 +178,12 @@ config NXFONTS_CHARBITS
The number of bits in the character set. Current options are only 7 and 8.
The default is 7.
+config NXFONT_MONO5X8
+ bool "Mono 5x8"
+ default n
+ ---help---
+ Tiny mono-spaced 5x8 font (font ID FONTID_MONO5X8 = 18)
+
config NXFONT_SANS17X22
bool "Sans 17x22"
default n
diff --git a/nuttx/graphics/Makefile b/nuttx/graphics/Makefile
index 238e14df4..aa402bfa4 100644
--- a/nuttx/graphics/Makefile
+++ b/nuttx/graphics/Makefile
@@ -124,6 +124,9 @@ gen32bppsources:
$(Q) $(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=32 EXTRADEFINES=$(EXTRADEFINES)
genfontsources:
+ifeq ($(CONFIG_NXFONT_MONO5X8),y)
+ @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=18 EXTRADEFINES=$(EXTRADEFINES)
+endif
ifeq ($(CONFIG_NXFONT_SANS23X27),y)
$(Q) $(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRADEFINES=$(EXTRADEFINES)
endif
diff --git a/nuttx/graphics/nxfonts/Make.defs b/nuttx/graphics/nxfonts/Make.defs
index bc65d7ad7..def092825 100644
--- a/nuttx/graphics/nxfonts/Make.defs
+++ b/nuttx/graphics/nxfonts/Make.defs
@@ -42,6 +42,12 @@ NXFCONV_CSRCS = nxfonts_convert_1bpp.c nxfonts_convert_2bpp.c \
NXFSET_ASRCS =
NXFSET_CSRCS =
+# Monospace fonts
+
+ifeq ($(CONFIG_NXFONT_MONO5X8),y)
+NXFSET_CSRCS += nxfonts_bitmaps_mono5x8.c
+endif
+
# Sans serif fonts
ifeq ($(CONFIG_NXFONT_SANS17X22),y)
diff --git a/nuttx/graphics/nxfonts/Makefile.sources b/nuttx/graphics/nxfonts/Makefile.sources
index 76a099dcb..2e41fc704 100644
--- a/nuttx/graphics/nxfonts/Makefile.sources
+++ b/nuttx/graphics/nxfonts/Makefile.sources
@@ -72,6 +72,13 @@ endif
ifdef NXFONTS_FONTID
+# MONO
+
+ifeq ($(NXFONTS_FONTID),18)
+NXFONTS_PREFIX := g_mono5x8_
+GEN_CSRC = nxfonts_bitmaps_mono5x8.c
+endif
+
# SANS
ifeq ($(NXFONTS_FONTID),14)
diff --git a/nuttx/graphics/nxfonts/nxfonts_bitmaps.c b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
index 2efc34b87..b089ec038 100644
--- a/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
+++ b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
@@ -80,6 +80,8 @@
# include "nxfonts_sans17x23b.h"
#elif NXFONTS_FONTID == 17
# include "nxfonts_sans20x27b.h"
+#elif NXFONTS_FONTID == 18
+# include "nxfonts_mono5x8.h"
#else
# error "No font ID specified"
#endif
diff --git a/nuttx/graphics/nxfonts/nxfonts_getfont.c b/nuttx/graphics/nxfonts/nxfonts_getfont.c
index 23e5c4474..c2af977f2 100644
--- a/nuttx/graphics/nxfonts/nxfonts_getfont.c
+++ b/nuttx/graphics/nxfonts/nxfonts_getfont.c
@@ -60,6 +60,12 @@
* Private Data
****************************************************************************/
+/* MONO */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+extern const struct nx_fontpackage_s g_mono5x8_package;
+#endif
+
/* SANS */
#ifdef CONFIG_NXFONT_SANS17X22
@@ -139,6 +145,12 @@ extern const struct nx_fontpackage_s g_serif38x49b_package;
static FAR const struct nx_fontpackage_s *g_fontpackages[] =
{
+/* MONO */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+ &g_mono5x8_package,
+#endif
+
/* SANS */
#ifdef CONFIG_NXFONT_SANS17X22
diff --git a/nuttx/graphics/nxfonts/nxfonts_mono5x8.h b/nuttx/graphics/nxfonts/nxfonts_mono5x8.h
new file mode 100644
index 000000000..739437e62
--- /dev/null
+++ b/nuttx/graphics/nxfonts/nxfonts_mono5x8.h
@@ -0,0 +1,815 @@
+/****************************************************************************
+ * graphics/nxfonts/nxfonts_mono5x8.h
+ *
+ * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved.
+ * Author: Petteri Aimonen <jpa@nx.mail.kapsi.fi>
+ *
+ * Based on 5x8.pcf.gz from xfonts-base. The file is marked as
+ * COPYRIGHT "Public domain font. Share and enjoy."
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT}
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING}
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __GRAPHICS_NXFONTS_NXFONTS_MONO5X8_H
+#define __GRAPHICS_NXFONTS_NXFONTS_MONO5X8_H
+
+#define NXFONT_ID FONTID_MONO5X8
+
+#define NXFONT_MIN7BIT 33
+#define NXFONT_MAX7BIT 126
+
+#define NXFONT_MIN8BIT 161
+#define NXFONT_MAX8BIT 255
+
+/* Maximum height and width of any glyph in the set */
+
+#define NXFONT_MAXHEIGHT 8
+#define NXFONT_MAXWIDTH 5
+
+/* The width of a space */
+
+#define NXFONT_SPACEWIDTH 5
+
+/* exclam (33) */
+#define NXFONT_METRICS_33 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_33 {0x0, 0x20, 0x20, 0x20, 0x20, 0x0, 0x20, 0x0}
+
+/* quotedbl (34) */
+#define NXFONT_METRICS_34 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_34 {0x0, 0x50, 0x50, 0x50, 0x0, 0x0, 0x0, 0x0}
+
+/* numbersign (35) */
+#define NXFONT_METRICS_35 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_35 {0x50, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x50, 0x0}
+
+/* dollar (36) */
+#define NXFONT_METRICS_36 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_36 {0x20, 0x70, 0xa0, 0x70, 0x28, 0x70, 0x20, 0x0}
+
+/* percent (37) */
+#define NXFONT_METRICS_37 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_37 {0x0, 0x40, 0x50, 0x20, 0x50, 0x10, 0x0, 0x0}
+
+/* ampersand (38) */
+#define NXFONT_METRICS_38 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_38 {0x40, 0xa0, 0xa0, 0x40, 0xa0, 0xa0, 0x50, 0x0}
+
+/* quotesingle (39) */
+#define NXFONT_METRICS_39 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_39 {0x0, 0x20, 0x20, 0x20, 0x0, 0x0, 0x0, 0x0}
+
+/* parenleft (40) */
+#define NXFONT_METRICS_40 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_40 {0x0, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x0}
+
+/* parenright (41) */
+#define NXFONT_METRICS_41 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_41 {0x0, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x0}
+
+/* asterisk (42) */
+#define NXFONT_METRICS_42 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_42 {0x0, 0x0, 0x90, 0x60, 0xf0, 0x60, 0x90, 0x0}
+
+/* plus (43) */
+#define NXFONT_METRICS_43 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_43 {0x0, 0x0, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x0}
+
+/* comma (44) */
+#define NXFONT_METRICS_44 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_44 {0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x20, 0x40}
+
+/* hyphen (45) */
+#define NXFONT_METRICS_45 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_45 {0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0}
+
+/* period (46) */
+#define NXFONT_METRICS_46 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_46 {0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x70, 0x20}
+
+/* slash (47) */
+#define NXFONT_METRICS_47 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_47 {0x0, 0x10, 0x10, 0x20, 0x40, 0x80, 0x80, 0x0}
+
+/* zero (48) */
+#define NXFONT_METRICS_48 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_48 {0x0, 0x20, 0x50, 0x50, 0x50, 0x50, 0x20, 0x0}
+
+/* one (49) */
+#define NXFONT_METRICS_49 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_49 {0x0, 0x20, 0x60, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* two (50) */
+#define NXFONT_METRICS_50 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_50 {0x0, 0x60, 0x90, 0x10, 0x60, 0x80, 0xf0, 0x0}
+
+/* three (51) */
+#define NXFONT_METRICS_51 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_51 {0x0, 0xf0, 0x20, 0x60, 0x10, 0x90, 0x60, 0x0}
+
+/* four (52) */
+#define NXFONT_METRICS_52 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_52 {0x0, 0x20, 0x60, 0xa0, 0xf0, 0x20, 0x20, 0x0}
+
+/* five (53) */
+#define NXFONT_METRICS_53 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_53 {0x0, 0xf0, 0x80, 0xe0, 0x10, 0x90, 0x60, 0x0}
+
+/* six (54) */
+#define NXFONT_METRICS_54 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_54 {0x0, 0x60, 0x80, 0xe0, 0x90, 0x90, 0x60, 0x0}
+
+/* seven (55) */
+#define NXFONT_METRICS_55 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_55 {0x0, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x0}
+
+/* eight (56) */
+#define NXFONT_METRICS_56 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_56 {0x0, 0x60, 0x90, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* nine (57) */
+#define NXFONT_METRICS_57 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_57 {0x0, 0x60, 0x90, 0x90, 0x70, 0x10, 0x60, 0x0}
+
+/* colon (58) */
+#define NXFONT_METRICS_58 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_58 {0x0, 0x0, 0x60, 0x60, 0x0, 0x60, 0x60, 0x0}
+
+/* semicolon (59) */
+#define NXFONT_METRICS_59 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_59 {0x0, 0x0, 0x30, 0x30, 0x0, 0x30, 0x20, 0x40}
+
+/* less (60) */
+#define NXFONT_METRICS_60 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_60 {0x0, 0x10, 0x20, 0x40, 0x40, 0x20, 0x10, 0x0}
+
+/* equal (61) */
+#define NXFONT_METRICS_61 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_61 {0x0, 0x0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x0}
+
+/* greater (62) */
+#define NXFONT_METRICS_62 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_62 {0x0, 0x40, 0x20, 0x10, 0x10, 0x20, 0x40, 0x0}
+
+/* question (63) */
+#define NXFONT_METRICS_63 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_63 {0x0, 0x20, 0x50, 0x10, 0x20, 0x0, 0x20, 0x0}
+
+/* at (64) */
+#define NXFONT_METRICS_64 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_64 {0x30, 0x48, 0x98, 0xa8, 0xa8, 0x90, 0x40, 0x30}
+
+/* A (65) */
+#define NXFONT_METRICS_65 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_65 {0x0, 0x60, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* B (66) */
+#define NXFONT_METRICS_66 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_66 {0x0, 0xe0, 0x90, 0xe0, 0x90, 0x90, 0xe0, 0x0}
+
+/* C (67) */
+#define NXFONT_METRICS_67 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_67 {0x0, 0x60, 0x90, 0x80, 0x80, 0x90, 0x60, 0x0}
+
+/* D (68) */
+#define NXFONT_METRICS_68 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_68 {0x0, 0xe0, 0x90, 0x90, 0x90, 0x90, 0xe0, 0x0}
+
+/* E (69) */
+#define NXFONT_METRICS_69 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_69 {0x0, 0xf0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x0}
+
+/* F (70) */
+#define NXFONT_METRICS_70 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_70 {0x0, 0xf0, 0x80, 0xe0, 0x80, 0x80, 0x80, 0x0}
+
+/* G (71) */
+#define NXFONT_METRICS_71 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_71 {0x0, 0x60, 0x90, 0x80, 0xb0, 0x90, 0x60, 0x0}
+
+/* H (72) */
+#define NXFONT_METRICS_72 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_72 {0x0, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x90, 0x0}
+
+/* I (73) */
+#define NXFONT_METRICS_73 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_73 {0x0, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* J (74) */
+#define NXFONT_METRICS_74 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_74 {0x0, 0x70, 0x20, 0x20, 0x20, 0xa0, 0x40, 0x0}
+
+/* K (75) */
+#define NXFONT_METRICS_75 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_75 {0x0, 0x90, 0xa0, 0xc0, 0xa0, 0xa0, 0x90, 0x0}
+
+/* L (76) */
+#define NXFONT_METRICS_76 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_76 {0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x0}
+
+/* M (77) */
+#define NXFONT_METRICS_77 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_77 {0x0, 0x90, 0xf0, 0xf0, 0x90, 0x90, 0x90, 0x0}
+
+/* N (78) */
+#define NXFONT_METRICS_78 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_78 {0x0, 0x90, 0xd0, 0xf0, 0xb0, 0xb0, 0x90, 0x0}
+
+/* O (79) */
+#define NXFONT_METRICS_79 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_79 {0x0, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* P (80) */
+#define NXFONT_METRICS_80 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_80 {0x0, 0xe0, 0x90, 0x90, 0xe0, 0x80, 0x80, 0x0}
+
+/* Q (81) */
+#define NXFONT_METRICS_81 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_81 {0x0, 0x60, 0x90, 0x90, 0xd0, 0xb0, 0x60, 0x10}
+
+/* R (82) */
+#define NXFONT_METRICS_82 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_82 {0x0, 0xe0, 0x90, 0x90, 0xe0, 0x90, 0x90, 0x0}
+
+/* S (83) */
+#define NXFONT_METRICS_83 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_83 {0x0, 0x60, 0x90, 0x40, 0x20, 0x90, 0x60, 0x0}
+
+/* T (84) */
+#define NXFONT_METRICS_84 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_84 {0x0, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* U (85) */
+#define NXFONT_METRICS_85 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_85 {0x0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* V (86) */
+#define NXFONT_METRICS_86 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_86 {0x0, 0x90, 0x90, 0x90, 0x90, 0x60, 0x60, 0x0}
+
+/* W (87) */
+#define NXFONT_METRICS_87 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_87 {0x0, 0x90, 0x90, 0x90, 0xf0, 0xf0, 0x90, 0x0}
+
+/* X (88) */
+#define NXFONT_METRICS_88 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_88 {0x0, 0x90, 0x90, 0x60, 0x60, 0x90, 0x90, 0x0}
+
+/* Y (89) */
+#define NXFONT_METRICS_89 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_89 {0x0, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x0}
+
+/* Z (90) */
+#define NXFONT_METRICS_90 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_90 {0x0, 0xf0, 0x10, 0x20, 0x40, 0x80, 0xf0, 0x0}
+
+/* bracketleft (91) */
+#define NXFONT_METRICS_91 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_91 {0x0, 0x70, 0x40, 0x40, 0x40, 0x40, 0x70, 0x0}
+
+/* backslash (92) */
+#define NXFONT_METRICS_92 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_92 {0x0, 0x80, 0x80, 0x40, 0x20, 0x10, 0x10, 0x0}
+
+/* bracketright (93) */
+#define NXFONT_METRICS_93 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_93 {0x0, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x0}
+
+/* asciicircum (94) */
+#define NXFONT_METRICS_94 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_94 {0x0, 0x20, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* underscore (95) */
+#define NXFONT_METRICS_95 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_95 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0}
+
+/* grave (96) */
+#define NXFONT_METRICS_96 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_96 {0x0, 0x40, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* a (97) */
+#define NXFONT_METRICS_97 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_97 {0x0, 0x0, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* b (98) */
+#define NXFONT_METRICS_98 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_98 {0x0, 0x80, 0x80, 0xe0, 0x90, 0x90, 0xe0, 0x0}
+
+/* c (99) */
+#define NXFONT_METRICS_99 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_99 {0x0, 0x0, 0x0, 0x30, 0x40, 0x40, 0x30, 0x0}
+
+/* d (100) */
+#define NXFONT_METRICS_100 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_100 {0x0, 0x10, 0x10, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* e (101) */
+#define NXFONT_METRICS_101 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_101 {0x0, 0x0, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* f (102) */
+#define NXFONT_METRICS_102 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_102 {0x0, 0x20, 0x50, 0x40, 0xe0, 0x40, 0x40, 0x0}
+
+/* g (103) */
+#define NXFONT_METRICS_103 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_103 {0x0, 0x0, 0x0, 0x60, 0x90, 0x70, 0x10, 0x60}
+
+/* h (104) */
+#define NXFONT_METRICS_104 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_104 {0x0, 0x80, 0x80, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* i (105) */
+#define NXFONT_METRICS_105 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_105 {0x0, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* j (106) */
+#define NXFONT_METRICS_106 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_106 {0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x50, 0x20}
+
+/* k (107) */
+#define NXFONT_METRICS_107 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_107 {0x0, 0x80, 0x80, 0x90, 0xe0, 0x90, 0x90, 0x0}
+
+/* l (108) */
+#define NXFONT_METRICS_108 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_108 {0x0, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* m (109) */
+#define NXFONT_METRICS_109 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_109 {0x0, 0x0, 0x0, 0xd0, 0xa8, 0xa8, 0xa8, 0x0}
+
+/* n (110) */
+#define NXFONT_METRICS_110 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_110 {0x0, 0x0, 0x0, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* o (111) */
+#define NXFONT_METRICS_111 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_111 {0x0, 0x0, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* p (112) */
+#define NXFONT_METRICS_112 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_112 {0x0, 0x0, 0x0, 0xe0, 0x90, 0xe0, 0x80, 0x80}
+
+/* q (113) */
+#define NXFONT_METRICS_113 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_113 {0x0, 0x0, 0x0, 0x70, 0x90, 0x70, 0x10, 0x10}
+
+/* r (114) */
+#define NXFONT_METRICS_114 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_114 {0x0, 0x0, 0x0, 0xa0, 0xd0, 0x80, 0x80, 0x0}
+
+/* s (115) */
+#define NXFONT_METRICS_115 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_115 {0x0, 0x0, 0x0, 0x30, 0x60, 0x10, 0x60, 0x0}
+
+/* t (116) */
+#define NXFONT_METRICS_116 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_116 {0x0, 0x40, 0x40, 0xe0, 0x40, 0x50, 0x20, 0x0}
+
+/* u (117) */
+#define NXFONT_METRICS_117 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_117 {0x0, 0x0, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* v (118) */
+#define NXFONT_METRICS_118 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_118 {0x0, 0x0, 0x0, 0x50, 0x50, 0x50, 0x20, 0x0}
+
+/* w (119) */
+#define NXFONT_METRICS_119 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_119 {0x0, 0x0, 0x0, 0x88, 0xa8, 0xa8, 0x50, 0x0}
+
+/* x (120) */
+#define NXFONT_METRICS_120 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_120 {0x0, 0x0, 0x0, 0x90, 0x60, 0x60, 0x90, 0x0}
+
+/* y (121) */
+#define NXFONT_METRICS_121 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_121 {0x0, 0x0, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+/* z (122) */
+#define NXFONT_METRICS_122 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_122 {0x0, 0x0, 0x0, 0xf0, 0x20, 0x40, 0xf0, 0x0}
+
+/* braceleft (123) */
+#define NXFONT_METRICS_123 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_123 {0x30, 0x40, 0x20, 0xc0, 0x20, 0x40, 0x30, 0x0}
+
+/* bar (124) */
+#define NXFONT_METRICS_124 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_124 {0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* braceright (125) */
+#define NXFONT_METRICS_125 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_125 {0xc0, 0x20, 0x40, 0x30, 0x40, 0x20, 0xc0, 0x0}
+
+/* asciitilde (126) */
+#define NXFONT_METRICS_126 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_126 {0x0, 0x50, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* exclamdown (161) */
+#define NXFONT_METRICS_161 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_161 {0x0, 0x20, 0x0, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* cent (162) */
+#define NXFONT_METRICS_162 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_162 {0x0, 0x0, 0x20, 0x70, 0xa0, 0xa0, 0x70, 0x20}
+
+/* sterling (163) */
+#define NXFONT_METRICS_163 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_163 {0x0, 0x20, 0x50, 0xe0, 0x40, 0x50, 0xa0, 0x0}
+
+/* currency (164) */
+#define NXFONT_METRICS_164 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_164 {0x0, 0x0, 0x88, 0x70, 0x50, 0x70, 0x88, 0x0}
+
+/* yen (165) */
+#define NXFONT_METRICS_165 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_165 {0x0, 0x88, 0x50, 0xf8, 0x20, 0xf8, 0x20, 0x0}
+
+/* brokenbar (166) */
+#define NXFONT_METRICS_166 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_166 {0x20, 0x20, 0x20, 0x0, 0x20, 0x20, 0x20, 0x0}
+
+/* section (167) */
+#define NXFONT_METRICS_167 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_167 {0x70, 0x80, 0xe0, 0x90, 0x70, 0x10, 0xe0, 0x0}
+
+/* dieresis (168) */
+#define NXFONT_METRICS_168 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_168 {0x0, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* copyright (169) */
+#define NXFONT_METRICS_169 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_169 {0x0, 0x70, 0xa8, 0xc8, 0xc8, 0xa8, 0x70, 0x0}
+
+/* ordfeminine (170) */
+#define NXFONT_METRICS_170 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_170 {0x30, 0x50, 0x30, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* guillemotleft (171) */
+#define NXFONT_METRICS_171 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_171 {0x0, 0x0, 0x0, 0x50, 0xa0, 0x50, 0x0, 0x0}
+
+/* logicalnot (172) */
+#define NXFONT_METRICS_172 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_172 {0x0, 0x0, 0x0, 0x0, 0x70, 0x10, 0x10, 0x0}
+
+/* hyphen (173) */
+#define NXFONT_METRICS_173 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_173 {0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* registered (174) */
+#define NXFONT_METRICS_174 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_174 {0x0, 0x70, 0xe8, 0xd8, 0xe8, 0xd8, 0x70, 0x0}
+
+/* macron (175) */
+#define NXFONT_METRICS_175 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_175 {0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* degree (176) */
+#define NXFONT_METRICS_176 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_176 {0x0, 0x20, 0x50, 0x20, 0x0, 0x0, 0x0, 0x0}
+
+/* plusminus (177) */
+#define NXFONT_METRICS_177 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_177 {0x0, 0x0, 0x20, 0x70, 0x20, 0x0, 0x70, 0x0}
+
+/* twosuperior (178) */
+#define NXFONT_METRICS_178 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_178 {0x20, 0x50, 0x10, 0x20, 0x70, 0x0, 0x0, 0x0}
+
+/* threesuperior (179) */
+#define NXFONT_METRICS_179 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_179 {0x60, 0x10, 0x60, 0x10, 0x60, 0x0, 0x0, 0x0}
+
+/* acute (180) */
+#define NXFONT_METRICS_180 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_180 {0x0, 0x20, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* mu (181) */
+#define NXFONT_METRICS_181 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_181 {0x0, 0x0, 0x0, 0x90, 0x90, 0x90, 0xe0, 0x80}
+
+/* paragraph (182) */
+#define NXFONT_METRICS_182 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_182 {0x0, 0x78, 0xe8, 0xe8, 0x68, 0x28, 0x28, 0x0}
+
+/* periodcentered (183) */
+#define NXFONT_METRICS_183 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_183 {0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0}
+
+/* cedilla (184) */
+#define NXFONT_METRICS_184 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_184 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40}
+
+/* onesuperior (185) */
+#define NXFONT_METRICS_185 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_185 {0x20, 0x60, 0x20, 0x20, 0x70, 0x0, 0x0, 0x0}
+
+/* ordmasculine (186) */
+#define NXFONT_METRICS_186 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_186 {0x20, 0x50, 0x20, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* guillemotright (187) */
+#define NXFONT_METRICS_187 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_187 {0x0, 0x0, 0x0, 0xa0, 0x50, 0xa0, 0x0, 0x0}
+
+/* onequarter (188) */
+#define NXFONT_METRICS_188 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_188 {0x80, 0x80, 0x80, 0xa0, 0x60, 0xf0, 0x20, 0x0}
+
+/* onehalf (189) */
+#define NXFONT_METRICS_189 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_189 {0x80, 0x80, 0xa0, 0xd0, 0x10, 0x20, 0x70, 0x0}
+
+/* threequarters (190) */
+#define NXFONT_METRICS_190 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_190 {0x80, 0x40, 0x80, 0x60, 0xa0, 0xf0, 0x20, 0x0}
+
+/* questiondown (191) */
+#define NXFONT_METRICS_191 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_191 {0x0, 0x20, 0x0, 0x20, 0x40, 0x50, 0x20, 0x0}
+
+/* Agrave (192) */
+#define NXFONT_METRICS_192 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_192 {0x40, 0x20, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Aacute (193) */
+#define NXFONT_METRICS_193 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_193 {0x20, 0x40, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Acircumflex (194) */
+#define NXFONT_METRICS_194 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_194 {0x60, 0x90, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Atilde (195) */
+#define NXFONT_METRICS_195 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_195 {0x50, 0xa0, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Adieresis (196) */
+#define NXFONT_METRICS_196 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_196 {0x90, 0x0, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Aring (197) */
+#define NXFONT_METRICS_197 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_197 {0x60, 0x90, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* AE (198) */
+#define NXFONT_METRICS_198 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_198 {0x0, 0x70, 0xa0, 0xa0, 0xf0, 0xa0, 0xb0, 0x0}
+
+/* Ccedilla (199) */
+#define NXFONT_METRICS_199 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_199 {0x0, 0x60, 0x90, 0x80, 0x80, 0x90, 0x60, 0x40}
+
+/* Egrave (200) */
+#define NXFONT_METRICS_200 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_200 {0x40, 0x20, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Eacute (201) */
+#define NXFONT_METRICS_201 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_201 {0x20, 0x40, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Ecircumflex (202) */
+#define NXFONT_METRICS_202 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_202 {0x60, 0x90, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Edieresis (203) */
+#define NXFONT_METRICS_203 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_203 {0x90, 0x0, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Igrave (204) */
+#define NXFONT_METRICS_204 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_204 {0x40, 0x20, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Iacute (205) */
+#define NXFONT_METRICS_205 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_205 {0x10, 0x20, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Icircumflex (206) */
+#define NXFONT_METRICS_206 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_206 {0x20, 0x50, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Idieresis (207) */
+#define NXFONT_METRICS_207 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_207 {0x50, 0x0, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Eth (208) */
+#define NXFONT_METRICS_208 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_208 {0x0, 0x70, 0x48, 0xe8, 0x48, 0x48, 0x70, 0x0}
+
+/* Ntilde (209) */
+#define NXFONT_METRICS_209 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_209 {0x50, 0xa0, 0x90, 0xd0, 0xb0, 0x90, 0x90, 0x0}
+
+/* Ograve (210) */
+#define NXFONT_METRICS_210 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_210 {0x40, 0x20, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Oacute (211) */
+#define NXFONT_METRICS_211 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_211 {0x20, 0x40, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Ocircumflex (212) */
+#define NXFONT_METRICS_212 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_212 {0x60, 0x90, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Otilde (213) */
+#define NXFONT_METRICS_213 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_213 {0x50, 0xa0, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Odieresis (214) */
+#define NXFONT_METRICS_214 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_214 {0x90, 0x0, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* multiply (215) */
+#define NXFONT_METRICS_215 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_215 {0x0, 0x0, 0x0, 0x0, 0x50, 0x20, 0x50, 0x0}
+
+/* Oslash (216) */
+#define NXFONT_METRICS_216 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_216 {0x0, 0x70, 0xb0, 0xb0, 0xd0, 0xd0, 0xe0, 0x0}
+
+/* Ugrave (217) */
+#define NXFONT_METRICS_217 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_217 {0x40, 0x20, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Uacute (218) */
+#define NXFONT_METRICS_218 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_218 {0x20, 0x40, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Ucircumflex (219) */
+#define NXFONT_METRICS_219 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_219 {0x60, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Udieresis (220) */
+#define NXFONT_METRICS_220 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_220 {0x90, 0x0, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Yacute (221) */
+#define NXFONT_METRICS_221 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_221 {0x10, 0x20, 0x88, 0x50, 0x20, 0x20, 0x20, 0x0}
+
+/* Thorn (222) */
+#define NXFONT_METRICS_222 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_222 {0x0, 0x80, 0xe0, 0x90, 0x90, 0xe0, 0x80, 0x0}
+
+/* germandbls (223) */
+#define NXFONT_METRICS_223 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_223 {0x0, 0x60, 0x90, 0xa0, 0xa0, 0x90, 0xa0, 0x0}
+
+/* agrave (224) */
+#define NXFONT_METRICS_224 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_224 {0x40, 0x20, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* aacute (225) */
+#define NXFONT_METRICS_225 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_225 {0x20, 0x40, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* acircumflex (226) */
+#define NXFONT_METRICS_226 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_226 {0x20, 0x50, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* atilde (227) */
+#define NXFONT_METRICS_227 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_227 {0x50, 0xa0, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* adieresis (228) */
+#define NXFONT_METRICS_228 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_228 {0x0, 0x50, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* aring (229) */
+#define NXFONT_METRICS_229 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_229 {0x60, 0x90, 0x60, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* ae (230) */
+#define NXFONT_METRICS_230 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_230 {0x0, 0x0, 0x0, 0xf0, 0x68, 0xb0, 0x78, 0x0}
+
+/* ccedilla (231) */
+#define NXFONT_METRICS_231 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_231 {0x0, 0x0, 0x0, 0x30, 0x40, 0x40, 0x30, 0x20}
+
+/* egrave (232) */
+#define NXFONT_METRICS_232 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_232 {0x40, 0x20, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* eacute (233) */
+#define NXFONT_METRICS_233 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_233 {0x20, 0x40, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* ecircumflex (234) */
+#define NXFONT_METRICS_234 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_234 {0x60, 0x90, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* edieresis (235) */
+#define NXFONT_METRICS_235 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_235 {0x0, 0x50, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* igrave (236) */
+#define NXFONT_METRICS_236 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_236 {0x40, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* iacute (237) */
+#define NXFONT_METRICS_237 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_237 {0x10, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* icircumflex (238) */
+#define NXFONT_METRICS_238 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_238 {0x20, 0x50, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* idieresis (239) */
+#define NXFONT_METRICS_239 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_239 {0x0, 0x50, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* eth (240) */
+#define NXFONT_METRICS_240 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_240 {0xa0, 0x40, 0xa0, 0x10, 0x70, 0x90, 0x60, 0x0}
+
+/* ntilde (241) */
+#define NXFONT_METRICS_241 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_241 {0x50, 0xa0, 0x0, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* ograve (242) */
+#define NXFONT_METRICS_242 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_242 {0x40, 0x20, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* oacute (243) */
+#define NXFONT_METRICS_243 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_243 {0x20, 0x40, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* ocircumflex (244) */
+#define NXFONT_METRICS_244 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_244 {0x60, 0x90, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* otilde (245) */
+#define NXFONT_METRICS_245 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_245 {0x50, 0xa0, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* odieresis (246) */
+#define NXFONT_METRICS_246 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_246 {0x0, 0x90, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* divide (247) */
+#define NXFONT_METRICS_247 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_247 {0x0, 0x0, 0x20, 0x0, 0x70, 0x0, 0x20, 0x0}
+
+/* oslash (248) */
+#define NXFONT_METRICS_248 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_248 {0x0, 0x0, 0x0, 0x70, 0xb0, 0xd0, 0xe0, 0x0}
+
+/* ugrave (249) */
+#define NXFONT_METRICS_249 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_249 {0x40, 0x20, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* uacute (250) */
+#define NXFONT_METRICS_250 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_250 {0x20, 0x40, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* ucircumflex (251) */
+#define NXFONT_METRICS_251 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_251 {0x60, 0x90, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* udieresis (252) */
+#define NXFONT_METRICS_252 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_252 {0x0, 0x90, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* yacute (253) */
+#define NXFONT_METRICS_253 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_253 {0x20, 0x40, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+/* thorn (254) */
+#define NXFONT_METRICS_254 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_254 {0x0, 0x80, 0x80, 0xe0, 0x90, 0xe0, 0x80, 0x80}
+
+/* ydieresis (255) */
+#define NXFONT_METRICS_255 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_255 {0x0, 0x90, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+#endif
diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h
index 8b4b10ade..958986472 100644
--- a/nuttx/include/nuttx/arch.h
+++ b/nuttx/include/nuttx/arch.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/arch.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h
index 6df5190d2..590d88402 100644
--- a/nuttx/include/nuttx/binfmt/binfmt.h
+++ b/nuttx/include/nuttx/binfmt/binfmt.h
@@ -82,6 +82,18 @@ typedef FAR void (*binfmt_dtor_t)(void);
struct symtab_s;
struct binary_s
{
+ /* If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will
+ * manage instances of struct binary_s allocated with kmalloc. It
+ * will keep the binary data in a link list and when SIGCHLD is received
+ * (meaning that the task has exit'ed, schedul_unload() will find the
+ * data, unload the module, and free the structure.
+ */
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR struct binary_s *flink; /* Supports a singly linked list */
+ pid_t pid; /* Task ID of the child task */
+#endif
+
/* Information provided to the loader to load and bind a module */
FAR const char *filename; /* Full path to the binary to be loaded (See NOTE 1 above) */
@@ -117,6 +129,12 @@ struct binary_s
#endif
size_t mapsize; /* Size of the mapped address region (needed for munmap) */
+
+ /* Start-up information that is provided by the loader, but may be modified
+ * by the caller between load_module() and exec_module() calls.
+ */
+
+ uint8_t priority; /* Task execution priority */
size_t stacksize; /* Size of the stack in bytes (unallocated) */
};
@@ -216,19 +234,48 @@ int unload_module(FAR const struct binary_s *bin);
*
* Returned Value:
* This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
+ * Returns the PID of the exec'ed module. On failure, it returns
* -1 (ERROR) and sets errno appropriately.
*
****************************************************************************/
-int exec_module(FAR const struct binary_s *bin, int priority);
+int exec_module(FAR const struct binary_s *bin);
+
+/****************************************************************************
+ * Name: schedule_unload
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called by
+ * the parent of the the newly created task to automatically unload the
+ * module when the task exits. This assumes that (1) the caller is the
+ * parent of the created task, (2) that bin was allocated with kmalloc()
+ * or friends. It will also automatically free the structure with kfree()
+ * after unloading the module.
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ * bin - This structure must have been allocated with kmalloc() and must
+ * persist until the task unloads
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * It returns 0 (OK) if the callback was successfully scheduled. On
+ * failure, it returns -1 (ERROR) and sets errno appropriately.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+int schedule_unload(pid_t pid, FAR struct binary_s *bin);
+#endif
/****************************************************************************
* Name: exec
*
* Description:
* This is a convenience function that wraps load_ and exec_module into
- * one call.
+ * one call. If CONFIG_SCHED_ONEXIT is also defined, this function will
+ * automatically call schedule_unload() to unload the module when task
+ * exits.
*
* Input Parameter:
* filename - Fulll path to the binary to be loaded
@@ -238,7 +285,7 @@ int exec_module(FAR const struct binary_s *bin, int priority);
*
* Returned Value:
* This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
+ * It returns the PID of the exec'ed module. On failure, it returns
* -1 (ERROR) and sets errno appropriately.
*
****************************************************************************/
diff --git a/apps/include/apps.h b/nuttx/include/nuttx/binfmt/builtin.h
index 520128203..6ff565395 100644
--- a/apps/include/apps.h
+++ b/nuttx/include/nuttx/binfmt/builtin.h
@@ -1,9 +1,16 @@
/****************************************************************************
- * apps/include/apps.h
+ * include/nuttx/binfmt/builtin.h
*
- * Copyright(C) 2011 Uros Platise. All rights reserved.
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -23,18 +30,18 @@
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
-#ifndef __APPS_INCLUDE_APPS_H
-#define __APPS_INCLUDE_APPS_H
+#ifndef __INCLUDE_NUTTX_BINFMT_BUILTIN_H
+#define __INCLUDE_NUTTX_BINFMT_BUILTIN_H
/****************************************************************************
* Included Files
@@ -42,17 +49,12 @@
#include <nuttx/config.h>
#include <sys/types.h>
-#include <stdint.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
-struct namedapp_s
+struct builtin_s
{
const char *name; /* Invocation name and as seen under /sbin/ */
int priority; /* Use: SCHED_PRIORITY_DEFAULT */
@@ -64,20 +66,6 @@ struct namedapp_s
* Public Data
****************************************************************************/
-/* The "bindir" is file system that supports access to the named applications.
- * It is typically mounted under /bin.
- */
-
-#ifdef CONFIG_APPS_BINDIR
-struct mountpt_operations;
-extern const struct mountpt_operations binfs_operations;
-#endif
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C" {
@@ -86,7 +74,44 @@ extern "C" {
#endif
/****************************************************************************
- * Name: namedapp_isavail
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_initialize
+ *
+ * Description:
+ * Builtin support is built unconditionally. However, it order to
+ * use this binary format, this function must be called during system
+ * format in order to register the builtin binary format.
+ *
+ * Returned Value:
+ * This is a NuttX internal function so it follows the convention that
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int builtin_initialize(void);
+
+/****************************************************************************
+ * Name: builtin_uninitialize
+ *
+ * Description:
+ * Unregister the builtin binary loader
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void builtin_uninitialize(void);
+
+/****************************************************************************
+ * Utility Functions Provided to Applications by binfmt/libbuiltin
+ ****************************************************************************/
+/****************************************************************************
+ * Name: builtin_isavail
*
* Description:
* Checks for availabiliy of application registerred during compile time.
@@ -101,10 +126,10 @@ extern "C" {
*
****************************************************************************/
-EXTERN int namedapp_isavail(FAR const char *appname);
+int builtin_isavail(FAR const char *appname);
/****************************************************************************
- * Name: namedapp_getname
+ * Name: builtin_getname
*
* Description:
* Returns pointer to a name of built-in application pointed by the
@@ -119,31 +144,35 @@ EXTERN int namedapp_isavail(FAR const char *appname);
*
****************************************************************************/
-EXTERN const char *namedapp_getname(int index);
+FAR const char *builtin_getname(int index);
/****************************************************************************
- * Name: exec_namedapp
+ * Data Set Access Functions Provided to Applications by binfmt/libbuiltin
+ ****************************************************************************/
+/****************************************************************************
+ * Name: builtin_for_index
*
* Description:
- * Executes builtin named application registered during compile time.
- * New application is run in a separate task context (and thread).
+ * Returns the builtin_s structure for the selected builtin.
+ * If support for builtin functions is enabled in the NuttX configuration,
+ * then this function must be provided by the application code.
*
* Input Parameter:
- * filename - Name of the linked-in binary to be started.
- * argv - Argument list
+ * index, from 0 and on...
*
* Returned Value:
- * This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
- * -1 (ERROR) and sets errno appropriately.
+ * Returns valid pointer pointing to the builtin_s structure if index is
+ * valid.
+ * Otherwise, NULL is returned.
*
****************************************************************************/
-EXTERN int exec_namedapp(FAR const char *appname, FAR const char **argv);
+EXTERN FAR const struct builtin_s *builtin_for_index(int index);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
-#endif /* __APPS_INCLUDE_APPS_H */
+#endif /* __INCLUDE_NUTTX_BINFMT_BUILTIN_H */
+
diff --git a/nuttx/include/nuttx/clock.h b/nuttx/include/nuttx/clock.h
index 952e0e5ef..e640ecd2e 100644
--- a/nuttx/include/nuttx/clock.h
+++ b/nuttx/include/nuttx/clock.h
@@ -113,7 +113,7 @@
#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK) /* Rounds */
#define MSEC2TICK(msec) (((msec)+(MSEC_PER_TICK/2))/MSEC_PER_TICK) /* Rounds */
#define DSEC2TICK(dsec) MSEC2TICK((dsec)*MSEC_PER_DSEC)
-#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC)
+#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC) /* Exact */
#define TICK2NSEC(tick) ((tick)*NSEC_PER_TICK) /* Exact */
#define TICK2USEC(tick) ((tick)*USEC_PER_TICK) /* Exact */
diff --git a/nuttx/include/nuttx/fs/binfs.h b/nuttx/include/nuttx/fs/binfs.h
new file mode 100644
index 000000000..d967506d8
--- /dev/null
+++ b/nuttx/include/nuttx/fs/binfs.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * include/nuttx/fs/binfs.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_FS_BINFS_H
+#define __INCLUDE_NUTTX_FS_BINFS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_FS_BINFS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* The "bindir" is file system that supports access to the builtin applications.
+ * It is typically mounted under /bin.
+ */
+
+EXTERN mountpt_operations;
+EXTERN const struct mountpt_operations binfs_operations;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_FS_BINFS */
+#endif /* __INCLUDE_NUTTX_FS_BINFS_H */
diff --git a/nuttx/include/nuttx/fs/dirent.h b/nuttx/include/nuttx/fs/dirent.h
index 75867c87a..f8d356850 100644
--- a/nuttx/include/nuttx/fs/dirent.h
+++ b/nuttx/include/nuttx/fs/dirent.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/dirent.h
*
- * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,7 @@ struct fs_romfsdir_s
};
#endif /* CONFIG_FS_ROMFS */
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
/* The apps/ pseudo bin/ directory. The state value is simply an index */
struct fs_binfsdir_s
@@ -179,7 +179,7 @@ struct fs_dirent_s
#ifdef CONFIG_FS_ROMFS
struct fs_romfsdir_s romfs;
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
struct fs_binfsdir_s binfs;
#endif
#ifdef CONFIG_FS_NXFFS
diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h
index 1759310bc..327bf37ca 100644
--- a/nuttx/include/nuttx/fs/fs.h
+++ b/nuttx/include/nuttx/fs/fs.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/fs.h
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -161,6 +161,7 @@ struct mountpt_operations
*/
int (*sync)(FAR struct file *filp);
+ int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
/* Directory operations */
diff --git a/nuttx/include/nuttx/fs/ioctl.h b/nuttx/include/nuttx/fs/ioctl.h
index 6d60c2ee9..a15de03b9 100644
--- a/nuttx/include/nuttx/fs/ioctl.h
+++ b/nuttx/include/nuttx/fs/ioctl.h
@@ -105,6 +105,11 @@
#define FIOC_OPTIMIZE _FIOC(0x0003) /* IN: None
* OUT: None
*/
+#define FIOC_FILENAME _FIOC(0x0004) /* IN: FAR const char ** pointer
+ * OUT: Pointer to a persistent file name
+ * (Guaranteed to persist while the file
+ * is open).
+ */
#define FIONREAD _FIOC(0x0004) /* IN: Location to return value (int *)
* OUT: Bytes readable from this fd
diff --git a/nuttx/include/nuttx/input/kbd_codec.h b/nuttx/include/nuttx/input/kbd_codec.h
new file mode 100644
index 000000000..9a7c7c8e6
--- /dev/null
+++ b/nuttx/include/nuttx/input/kbd_codec.h
@@ -0,0 +1,347 @@
+/************************************************************************************
+ * include/nuttx/input/kbd_codec.h
+ * Serialize and marshaling keyboard data and events
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_INPUT_KBD_CODEC_H
+#define __INCLUDE_NUTTX_INPUT_KBD_CODEC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/streams.h>
+
+#ifdef CONFIG_LIB_KBDCODEC
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* These are the special keyboard commands recognized by the CODEC. */
+
+enum kbd_keycode_e
+{
+ KEYCODE_NORMAL = 0, /* Not a special keycode */
+
+ /* Delete and Backspace keycodes (in case they may be different than the
+ * ASCII BKSP and DEL values.
+ */
+
+ KEYCODE_FWDDEL, /* DELete (forward delete) */
+ KEYCODE_BACKDEL, /* Backspace (backward delete) */
+
+ /* Cursor movement */
+
+ KEYCODE_HOME, /* Home */
+ KEYCODE_END, /* End */
+ KEYCODE_LEFT, /* Left arrow */
+ KEYCODE_RIGHT, /* Right arrow */
+ KEYCODE_UP, /* Up arrow */
+ KEYCODE_DOWN, /* Down arrow */
+ KEYCODE_PAGEUP, /* Page up */
+ KEYCODE_PAGEDOWN, /* Page down */
+
+ /* Edit commands */
+
+ KEYCODE_INSERT, /* Insert */
+ KEYCODE_AGAIN, /* Again */
+ KEYCODE_UNDO, /* Undo */
+ KEYCODE_REDO, /* Redo */
+ KEYCODE_CUT, /* Cut */
+ KEYCODE_COPY, /* Copy */
+ KEYCODE_PASTE, /* Paste */
+ KEYCODE_FIND, /* Find */
+
+ /* Selection codes */
+
+ KEYCODE_ENTER, /* Enter */
+ KEYCODE_SELECT, /* Select */
+ KEYCODE_EXECUTE, /* Execute */
+
+ /* Keyboard modes */
+
+ KEYCODE_CAPSLOCK, /* Caps Lock */
+ KEYCODE_SCROLLLOCK, /* Scroll Lock */
+ KEYCODE_NUMLOCK, /* Keypad Num Lock and Clear */
+ KEYCODE_LCAPSLOCK, /* Locking Caps Lock */
+ KEYCODE_LNUMLOCK, /* Locking Num Lock */
+ KEYCODE_LSCROLLLOCK, /* Locking Scroll Lock */
+
+ /* Misc control codes */
+
+ KEYCODE_POWER, /* Power */
+ KEYCODE_HELP, /* Help */
+ KEYCODE_MENU, /* Menu */
+ KEYCODE_STOP, /* Stop */
+ KEYCODE_PAUSE, /* Pause */
+ KEYCODE_BREAK, /* Break */
+ KEYCODE_CANCEL, /* Cancel */
+ KEYCODE_PRTSCRN, /* PrintScreen */
+ KEYCODE_SYSREQ, /* SysReq/Attention */
+
+ /* Audio */
+
+ KEYCODE_MUTE, /* Mute */
+ KEYCODE_VOLUP, /* Volume Up */
+ KEYCODE_VOLDOWN, /* Volume Down */
+
+ /* Telephone */
+
+ KEYCODE_ANSWER, /* Answer (phone) */
+ KEYCODE_HANGUP, /* Hang-up (phone) */
+
+ /* Calculator */
+
+ KEYCODE_CLEAR, /* Clear */
+ KEYCODE_CLEARENTRY, /* Clear entry */
+ KEYCODE_NEGATE, /* +/- */
+
+ KEYCODE_MEMSTORE, /* Memory store */
+ KEYCODE_MEMCLEAR, /* Memory clear */
+ KEYCODE_MEMRECALL, /* Memory recall */
+ KEYCODE_MEMADD, /* Memory add */
+ KEYCODE_MEMSUB, /* Memory substract */
+ KEYCODE_MEMMUL, /* Memory multiply */
+ KEYCODE_MEMDIV, /* Memory divide */
+
+ KEYCODE_BINARY, /* Binary mode */
+ KEYCODE_OCTAL, /* Octal mode */
+ KEYCODE_DECIMAL, /* Decimal mode */
+ KEYCODE_HEXADECIMAL, /* Hexadecimal mode */
+
+ /* Languages */
+
+ KEYCODE_LANG1, /* LANG1 */
+ KEYCODE_LANG2, /* LANG2 */
+ KEYCODE_LANG3, /* LANG3 */
+ KEYCODE_LANG4, /* LANG4 */
+ KEYCODE_LANG5, /* LANG5 */
+ KEYCODE_LANG6, /* LANG6 */
+ KEYCODE_LANG7, /* LANG7 */
+ KEYCODE_LANG8, /* LANG8 */
+
+ /* Context-specific function keys */
+
+ KEYCODE_F1, /* Function key 1 */
+ KEYCODE_F2, /* Function key 2 */
+ KEYCODE_F3, /* Function key 3 */
+ KEYCODE_F4, /* Function key 4 */
+ KEYCODE_F5, /* Function key 5 */
+ KEYCODE_F6, /* Function key 6 */
+ KEYCODE_F7, /* Function key 7 */
+ KEYCODE_F8, /* Function key 8 */
+ KEYCODE_F9, /* Function key 9 */
+ KEYCODE_F10, /* Function key 10 */
+ KEYCODE_F11, /* Function key 11 */
+ KEYCODE_F12, /* Function key 12 */
+ KEYCODE_F13, /* Function key 13 */
+ KEYCODE_F14, /* Function key 14 */
+ KEYCODE_F15, /* Function key 15 */
+ KEYCODE_F16, /* Function key 16 */
+ KEYCODE_F17, /* Function key 17 */
+ KEYCODE_F18, /* Function key 18 */
+ KEYCODE_F19, /* Function key 19 */
+ KEYCODE_F20, /* Function key 20 */
+ KEYCODE_F21, /* Function key 21 */
+ KEYCODE_F22, /* Function key 22 */
+ KEYCODE_F23, /* Function key 23 */
+ KEYCODE_F24 /* Function key 24 */
+};
+
+#define FIRST_KEYCODE KEYCODE_FWDDEL
+#define LAST_KEYCODE KEYCODE_F24
+
+/* kbd_decode() return values */
+
+#define KBD_PRESS 0 /* Key press event */
+#define KBD_RELEASE 1 /* Key release event */
+#define KBD_SPECPRESS 2 /* Special key press event */
+#define KBD_SPECREL 3 /* Special key release event */
+#define KBD_ERROR EOF /* Error or end-of-file */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct kbd_getstate_s
+{
+ uint8_t nch; /* Number of characters in the buffer */
+ uint8_t ndx; /* Index to next character in the buffer */
+ uint8_t buf[4]; /* Buffer of ungotten data */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * The following functions are intended for use by "producer", keyboard
+ * or keypad drivers to encode information into driver buffers.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_press
+ *
+ * Description:
+ * Indicates a normal key press event. Put one byte of normal keyboard
+ * data into the output stream.
+ *
+ * Input Parameters:
+ * ch - The character to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#define kbd_press(ch, stream) (stream)->put((stream), (int)(ch))
+
+/****************************************************************************
+ * Name: kbd_release
+ *
+ * Description:
+ * Encode the release of a normal key.
+ *
+ * Input Parameters:
+ * ch - The character associated with the key that was releared.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_release(uint8_t ch, FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * Name: kbd_specpress
+ *
+ * Description:
+ * Denotes a special key press event. Put one special keyboard command
+ * into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specpress(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * Name: kbd_specrel
+ *
+ * Description:
+ * Denotes a special key release event. Put one special keyboard
+ * command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specrel(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * The following functions are intended for use by "consumer" applications
+ * to remove and decode information from the driver provided buffer.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the driver provided input
+ * buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that kbd_decode is called.
+ *
+ * Returned Value:
+ *
+ * KBD_PRESS - Indicates the successful receipt of normal, keyboard data.
+ * This corresponds to a keypress event. The returned value in pch is a
+ * simple byte of text or control data corresponding to the pressed key.
+ * KBD_RELEASE - Indicates a key release event. The returned value in pch
+ * is the byte of text or control data corresponding to the released key.
+ * KBD_SPECPRESS - Indicates the successful receipt of a special keyboard
+ * command. The returned value in pch is a value from enum kbd_getstate_s.
+ * KBD_SPECREL - Indicates a special key release event. The returned value
+ * in pch is a value from enum kbd_getstate_s.
+ * EOF - An error has getting the next character (reported by the stream).
+ * Normally indicates the end of file.
+ *
+ ****************************************************************************/
+
+int kbd_decode(FAR struct lib_instream_s *stream,
+ FAR struct kbd_getstate_s *state, FAR uint8_t *pch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LIB_KBDCODEC */
+#endif /* __INCLUDE_NUTTX_INPUT_KBD_CODEC_H */
+
diff --git a/nuttx/include/nuttx/lcd/hd4478ou.h b/nuttx/include/nuttx/lcd/hd4478ou.h
new file mode 100644
index 000000000..4bb93fca9
--- /dev/null
+++ b/nuttx/include/nuttx/lcd/hd4478ou.h
@@ -0,0 +1,118 @@
+/********************************************************************************************
+ * include/nuttx/lcd/hd4478ou.h
+ *
+ * Definitions for the Hitachi HD44780U LCD controller (as used in the
+ * LCD1602).
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_HD4478OU_H
+#define __INCLUDE_NUTTX_HD4478OU_H
+
+/********************************************************************************************
+ * Included Files
+ ********************************************************************************************/
+/* Command set:
+ *
+ * RS=0 R/W=0 : Command
+ * RS=0 R/W=1 : Busy/AD, Read CT (see below)
+ * RS=1 R/W=0 : Write data to CGRAM or DDRAM
+ * RS=1 R/W=0 : Read data from CGRAM or DDRAM
+ */
+
+#define HD4478OU_CLEAR (0x01) /* Screen Clear, Set AC to 0 */
+#define HD4478OU_RETURN (0x02) /* DDRAM AD=0, return */
+#define HD4478OU_INPUT (0x04) /* Set moving direction of cursor */
+# define HD4478OU_INPUT_SHIFT (1 << 0) /* Shift */
+# define HD4478OU_INPUT_INCR (1 << 1) /* Increment mode */
+# define HD4478OU_INPUT_DECR (0x00) /* Decrement mode */
+#define HD4478OU_DISPLAY (0x08) /* Set display, cursor, blink on/off */
+# define HD4478OU_DISPLAY_BLINK (1 << 0) /* Blink on/off */
+# define HD4478OU_DISPLAY_CURSOR (1 << 1) /* Cursor on/off */
+# define HD4478OU_DISPLAY_ON (1 << 2) /* Display on/off */
+#define HD4478OU_SHIFT (0x10) /* Remove cursor and whole diplay */
+# define HD4478OU_SHIFT_RIGHT (1 << 2) /* Shift right */
+# define HD4478OU_SHIFT_LEFT (0x00) /* Shift right */
+# define HD4478OU_SHIFT_DISPLAY (1 << 3) /* Display shift */
+# define HD4478OU_SHIFT_CURSOR (0x00) /* Cursor shift */
+#define HD4478OU_FUNC (0x20) /* Set DL, display line, font */
+# define HD4478OU_FUNC_F5x10 (1 << 2) /* 5x10 Style */
+# define HD4478OU_FUNC_F5x7 (0x00) /* 5x7 Style */
+# define HD4478OU_FUNC_N1 (1 << 3) /* N=2R */
+# define HD4478OU_FUNC_N0 (0x00) /* N=1R */
+# define HD4478OU_FUNC_DL8D (1 << 4) /* DL=8D, 8-bit interface */
+# define HD4478OU_FUNC_DL4D (0x00) /* DL=4D, 4-bit interface */
+#define HD4478OU_CGRAM_AD(a) (0x40|(a)) /* Set CGRAM AD, send receive data */
+#define HD4478OU_DDRAM_AD(a) (0x80|(a)) /* Set DDRAM AD, send receive data */
+
+/* RS=0 R/W=1 : Execute internal function, read AD of CT */
+
+#define HD4478OU_BUSY(bf,ac) ((bf) << 7 | (ac))
+
+/********************************************************************************************
+ * Pre-processor Definitions
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Types
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Data
+ ********************************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/********************************************************************************************
+ * Public Function Prototypes
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Name: up_lcd1602_initialize
+ *
+ * Description:
+ * the LCD1602 is an HD4478OU-based LCD from Wave share. This function initializes the
+ * LCD1602 hardware and registers the character driver as /dev/lcd1602.
+ *
+ ********************************************************************************************/
+
+int up_lcd1602_initialize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_HD4478OU_H */
diff --git a/nuttx/include/nuttx/lcd/ug-2864ambag01.h b/nuttx/include/nuttx/lcd/ug-2864ambag01.h
index deb568981..86362d773 100644
--- a/nuttx/include/nuttx/lcd/ug-2864ambag01.h
+++ b/nuttx/include/nuttx/lcd/ug-2864ambag01.h
@@ -1,5 +1,6 @@
/**************************************************************************************
* include/nuttx/lcd/ug-2864ambag01.h
+ *
* Driver for Univision UG-2864AMBAG01 OLED display (wih SH1101A controller) in SPI
* mode
*
diff --git a/nuttx/include/nuttx/lcd/ug-2864hsweg01.h b/nuttx/include/nuttx/lcd/ug-2864hsweg01.h
new file mode 100644
index 000000000..e38741967
--- /dev/null
+++ b/nuttx/include/nuttx/lcd/ug-2864hsweg01.h
@@ -0,0 +1,246 @@
+/**************************************************************************************
+ * include/nuttx/lcd/ug-2864hsweg01.h
+ *
+ * Driver for Univision UG-2864HSWEG01 OLED display (wih SSD1306 controller) in SPI
+ * mode
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * References:
+ * 1. Product Specification (Preliminary), Part Name: OEL Display Module, Part ID:
+ * UG-2864HSWEG01, Doc No: SAS1-9046-B, Univision Technology Inc.
+ * 2. SSD1306, 128 X 64 Dot Matrix OLED/PLED, Preliminary Segment/Common Driver with
+ * Controller, Solomon Systech
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_UG_8264HSWEG01_H
+#define __INCLUDE_NUTTX_UG_8264HSWEG01_H
+
+/**************************************************************************************
+ * Included Files
+ **************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#include <nuttx/arch.h>
+
+#ifdef CONFIG_LCD_UG2864HSWEG01
+
+/**************************************************************************************
+ * Pre-processor Definitions
+ **************************************************************************************/
+/* Configuration **********************************************************************/
+/* UG-2864HSWEG01 Configuration Settings:
+ *
+ * CONFIG_UG2864HSWEG01_SPIMODE - Controls the SPI mode
+ * CONFIG_UG2864HSWEG01_FREQUENCY - Define to use a different bus frequency
+ * CONFIG_UG2864HSWEG01_NINTERFACES - Specifies the number of physical UG-2864HSWEG01
+ * devices that will be supported.
+ *
+ * Required LCD driver settings:
+ *
+ * CONFIG_LCD_UG28HSWEG01 - Enable UG-2864HSWEG01 support
+ * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted.
+ * CONFIG_LCD_MAXPOWER must be 1
+ *
+ * Option LCD driver settings:
+ * CONFIG_LCD_LANDSCAPE, CONFIG_LCD_PORTRAIT, CONFIG_LCD_RLANDSCAPE, and
+ * CONFIG_LCD_RPORTRAIT - Display orientation.
+ *
+ * Required SPI driver settings:
+ * CONFIG_SPI_CMDDATA - Include support for cmd/data selection.
+ */
+
+/* SPI Interface
+ *
+ * "The serial interface consists of serial clock SCL, serial data SI, A0 and
+ * CS . SI is shifted into an 8-bit shift register on every rising edge of
+ * SCL in the order of D7, D6, … and D0. A0 is sampled on every eighth clock
+ * and the data byte in the shift register is written to the display data RAM
+ * or command register in the same clock."
+ *
+ * MODE 3:
+ * Clock polarity: High (CPOL=1)
+ * Clock phase: Sample on trailing (rising edge) (CPHA 1)
+ */
+
+#ifndef CONFIG_UG2864HSWEG01_SPIMODE
+# define CONFIG_UG2864HSWEG01_SPIMODE SPIDEV_MODE3
+#endif
+
+/* "This module determines whether the input data is interpreted as data or
+ * command. When A0 = “H”, the inputs at D7 - D0 are interpreted as data and be
+ * written to display RAM. When A0 = “L”, the inputs at D7 - D0 are interpreted
+ * as command, they will be decoded and be written to the corresponding command
+ * registers.
+ */
+
+#ifndef CONFIG_SPI_CMDDATA
+# error "CONFIG_SPI_CMDDATA must be defined in your NuttX configuration"
+#endif
+
+/* CONFIG_UG2864HSWEG01_NINTERFACES determines the number of physical interfaces
+ * that will be supported.
+ */
+
+#ifndef CONFIG_UG2864HSWEG01_NINTERFACES
+# define CONFIG_UG2864HSWEG01_NINTERFACES 1
+#endif
+
+/* Check contrast selection */
+
+#if !defined(CONFIG_LCD_MAXCONTRAST)
+# define CONFIG_LCD_MAXCONTRAST 255
+#endif
+
+#if CONFIG_LCD_MAXCONTRAST <= 0|| CONFIG_LCD_MAXCONTRAST > 255
+# error "CONFIG_LCD_MAXCONTRAST exceeds supported maximum"
+#endif
+
+#if CONFIG_LCD_MAXCONTRAST < 255
+# warning "Optimal setting of CONFIG_LCD_MAXCONTRAST is 255"
+#endif
+
+/* Check power setting */
+
+#if !defined(CONFIG_LCD_MAXPOWER)
+# define CONFIG_LCD_MAXPOWER 1
+#endif
+
+#if CONFIG_LCD_MAXPOWER != 1
+# warning "CONFIG_LCD_MAXPOWER exceeds supported maximum"
+# undef CONFIG_LCD_MAXPOWER
+# define CONFIG_LCD_MAXPOWER 1
+#endif
+
+/* Color is 1bpp monochrome with leftmost column contained in bits 0 */
+
+#ifdef CONFIG_NX_DISABLE_1BPP
+# warning "1 bit-per-pixel support needed"
+#endif
+
+/* Orientation */
+
+#if defined(CONFIG_LCD_LANDSCAPE)
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_PORTRAIT)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RLANDSCAPE)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RPORTRAIT)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+#else
+# define CONFIG_LCD_LANDSCAPE 1
+# warning "Assuming landscape orientation"
+#endif
+
+/* Some important "colors" */
+
+#define UG_Y1_BLACK 0
+#define UG_Y1_WHITE 1
+
+/**************************************************************************************
+ * Public Types
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Public Data
+ **************************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************************************************************************
+ * Public Function Prototypes
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_initialize
+ *
+ * Description:
+ * Initialize the UG-2864HSWEG01 video hardware. The initial state of the
+ * OLED is fully initialized, display memory cleared, and the OLED ready
+ * to use, but with the power setting at 0 (full off == sleep mode).
+ *
+ * Input Parameters:
+ *
+ * spi - A reference to the SPI driver instance.
+ * devno - A value in the range of 0 through CONFIG_UG2864HSWEG01_NINTERFACES-1.
+ * This allows support for multiple OLED devices.
+ *
+ * Returned Value:
+ *
+ * On success, this function returns a reference to the LCD object for
+ * the specified OLED. NULL is returned on any failure.
+ *
+ **************************************************************************************/
+
+struct lcd_dev_s; /* See include/nuttx/lcd/lcd.h */
+struct spi_dev_s; /* See include/nuttx/spi.h */
+FAR struct lcd_dev_s *ug2864hsweg01_initialize(FAR struct spi_dev_s *spi,
+ unsigned int devno);
+
+/************************************************************************************************
+ * Name: ug2864hsweg01_fill
+ *
+ * Description:
+ * This non-standard method can be used to clear the entire display by writing one
+ * color to the display. This is much faster than writing a series of runs.
+ *
+ * Input Parameters:
+ * priv - Reference to private driver structure
+ *
+ * Assumptions:
+ * Caller has selected the OLED section.
+ *
+ **************************************************************************************/
+
+void ug2864hsweg01_fill(FAR struct lcd_dev_s *dev, uint8_t color);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LCD_UG2864HSWEG01 */
+#endif /* __INCLUDE_NUTTX_UG_8264HSWEG01_H */
diff --git a/nuttx/include/nuttx/lcd/ug-9664hswag01.h b/nuttx/include/nuttx/lcd/ug-9664hswag01.h
index b470e0895..a60b5ed67 100644
--- a/nuttx/include/nuttx/lcd/ug-9664hswag01.h
+++ b/nuttx/include/nuttx/lcd/ug-9664hswag01.h
@@ -1,5 +1,6 @@
/****************************************************************************
* include/nuttx/lcd/ug-9664hswag01.h
+ *
* Driver for the Univision UG-9664HSWAG01 Display with the Solomon Systech
* SSD1305 LCD controller.
*
diff --git a/nuttx/include/nuttx/net/mii.h b/nuttx/include/nuttx/net/mii.h
index 6a5fc6e89..de4dcdfd7 100644
--- a/nuttx/include/nuttx/net/mii.h
+++ b/nuttx/include/nuttx/net/mii.h
@@ -112,12 +112,12 @@
/* Luminary LM3S6918 built-in PHY: 0x07-0x0f, 0x14-0x16, 0x19-0x1f reserved */
-#define MII_LM3S_VSPECIFIC 0x10 /* Vendor-Specific */
-#define MII_LM3S_INTCS 0x11 /* Interrupt control/status */
-#define MII_LM3S_DIAGNOSTIC 0x12 /* Diagnostic */
-#define MII_LM3S_XCVRCONTROL 0x13 /* Transceiver Control */
-#define MII_LM3S_LEDCONFIG 0x17 /* LED Configuration */
-#define MII_LM3S_MDICONTROL 0x18 /* Ethernet PHY Management MDI/MDIX Control */
+#define MII_LM_VSPECIFIC 0x10 /* Vendor-Specific */
+#define MII_LM_INTCS 0x11 /* Interrupt control/status */
+#define MII_LM_DIAGNOSTIC 0x12 /* Diagnostic */
+#define MII_LM_XCVRCONTROL 0x13 /* Transceiver Control */
+#define MII_LM_LEDCONFIG 0x17 /* LED Configuration */
+#define MII_LM_MDICONTROL 0x18 /* Ethernet PHY Management MDI/MDIX Control */
/* Micrel KS8721: 0x15, 0x1b, and 0x1f */
@@ -323,79 +323,79 @@
/* LM3S6918-specific register bit settings **********************************/
/* LM3S6918 Vendor-Specific, address 0x10 */
-#define LM3S_VSPECIFIC_RXCC (1 << 0) /* Bit 0: Receive Clock Control*/
-#define LM3S_VSPECIFIC_PCSBP (1 << 1) /* Bit 1: PCS Bypass */
-#define LM3S_VSPECIFIC_RVSPOL (1 << 4) /* Bit 4: Receive Data Polarity */
-#define LM3S_VSPECIFIC_APOL (1 << 5) /* Bit 5: Auto-Polarity Disable */
-#define LM3S_VSPECIFIC_NL10 (1 << 10) /* Bit 10: Natural Loopback Mode */
-#define LM3S_VSPECIFIC_SQEI (1 << 11) /* Bit 11: SQE Inhibit Testing */
-#define LM3S_VSPECIFIC_TXHIM (1 << 12) /* Bit 12: Transmit High Impedance Mode */
-#define LM3S_VSPECIFIC_INPOL (1 << 14) /* Bit 14: Interrupt Polarity Value*/
-#define LM3S_VSPECIFIC_RPTR (1 << 15) /* Bit 15: Repeater mode*/
+#define LM_VSPECIFIC_RXCC (1 << 0) /* Bit 0: Receive Clock Control*/
+#define LM_VSPECIFIC_PCSBP (1 << 1) /* Bit 1: PCS Bypass */
+#define LM_VSPECIFIC_RVSPOL (1 << 4) /* Bit 4: Receive Data Polarity */
+#define LM_VSPECIFIC_APOL (1 << 5) /* Bit 5: Auto-Polarity Disable */
+#define LM_VSPECIFIC_NL10 (1 << 10) /* Bit 10: Natural Loopback Mode */
+#define LM_VSPECIFIC_SQEI (1 << 11) /* Bit 11: SQE Inhibit Testing */
+#define LM_VSPECIFIC_TXHIM (1 << 12) /* Bit 12: Transmit High Impedance Mode */
+#define LM_VSPECIFIC_INPOL (1 << 14) /* Bit 14: Interrupt Polarity Value*/
+#define LM_VSPECIFIC_RPTR (1 << 15) /* Bit 15: Repeater mode*/
/* LM3S6918 Interrupt Control/Status, address 0x11 */
-#define LM3S_INTCS_ANEGCOMPINT (1 << 0) /* Bit 0: Auto-Negotiation Complete Interrupt */
-#define LM3S_INTCS_RFAULTINT (1 << 1) /* Bit 1: Remote Fault Interrupt */
-#define LM3S_INTCS_LSCHGINT (1 << 2) /* Bit 2: Link Status Change Interrupt */
-#define LM3S_INTCS_LPACKINT (1 << 3) /* Bit 3: LP Acknowledge Interrupt */
-#define LM3S_INTCS_PDFINT (1 << 4) /* Bit 4: Parallel Detection Fault Interrupt */
-#define LM3S_INTCS_PRXINT (1 << 5) /* Bit 5: Page Receive Interrupt */
-#define LM3S_INTCS_RXERINT (1 << 6) /* Bit 6: Receive Error Interrupt */
-#define LM3S_INTCS_JABBERINT (1 << 7) /* Bit 7: Jabber Event Interrupt */
-#define LM3S_INTCS_ANEGCOMPIE (1 << 8) /* Bit 8: Auto-Negotiation Complete Interrupt Enable */
-#define LM3S_INTCS_RFAULTIE (1 << 9) /* Bit 9: Remote Fault Interrupt Enable */
-#define LM3S_INTCS_LSCHGIE (1 << 10) /* Bit 10: Link Status Change Interrupt Enable */
-#define LM3S_INTCS_LPACKIE (1 << 11) /* Bit 11: LP Acknowledge Interrupt Enable */
-#define LM3S_INTCS_PDFIE (1 << 12) /* Bit 12: Parallel Detection Fault Interrupt Enable */
-#define LM3S_INTCS_PRXIE (1 << 13) /* Bit 13: Page Received Interrupt Enable */
-#define LM3S_INTCS_RXERIE (1 << 14) /* Bit 14: Receive Error Interrupt Enable */
-#define LM3S_INTCS_JABBERIE (1 << 15) /* Bit 15: Jabber Interrupt Enable */
+#define LM_INTCS_ANEGCOMPINT (1 << 0) /* Bit 0: Auto-Negotiation Complete Interrupt */
+#define LM_INTCS_RFAULTINT (1 << 1) /* Bit 1: Remote Fault Interrupt */
+#define LM_INTCS_LSCHGINT (1 << 2) /* Bit 2: Link Status Change Interrupt */
+#define LM_INTCS_LPACKINT (1 << 3) /* Bit 3: LP Acknowledge Interrupt */
+#define LM_INTCS_PDFINT (1 << 4) /* Bit 4: Parallel Detection Fault Interrupt */
+#define LM_INTCS_PRXINT (1 << 5) /* Bit 5: Page Receive Interrupt */
+#define LM_INTCS_RXERINT (1 << 6) /* Bit 6: Receive Error Interrupt */
+#define LM_INTCS_JABBERINT (1 << 7) /* Bit 7: Jabber Event Interrupt */
+#define LM_INTCS_ANEGCOMPIE (1 << 8) /* Bit 8: Auto-Negotiation Complete Interrupt Enable */
+#define LM_INTCS_RFAULTIE (1 << 9) /* Bit 9: Remote Fault Interrupt Enable */
+#define LM_INTCS_LSCHGIE (1 << 10) /* Bit 10: Link Status Change Interrupt Enable */
+#define LM_INTCS_LPACKIE (1 << 11) /* Bit 11: LP Acknowledge Interrupt Enable */
+#define LM_INTCS_PDFIE (1 << 12) /* Bit 12: Parallel Detection Fault Interrupt Enable */
+#define LM_INTCS_PRXIE (1 << 13) /* Bit 13: Page Received Interrupt Enable */
+#define LM_INTCS_RXERIE (1 << 14) /* Bit 14: Receive Error Interrupt Enable */
+#define LM_INTCS_JABBERIE (1 << 15) /* Bit 15: Jabber Interrupt Enable */
/* LM3S6918 Diagnostic, address 0x12 */
-#define LM3S_DIAGNOSTIC_RX_LOCK (1 << 8) /* Bit 8: Receive PLL Lock */
-#define LM3S_DIAGNOSTIC_RXSD (1 << 9) /* Bit 9: Receive Detection */
-#define LM3S_DIAGNOSTIC_RATE (1 << 10) /* Bit 10: Rate */
-#define LM3S_DIAGNOSTIC_DPLX (1 << 11) /* Bit 11: Duplex Mode */
-#define LM3S_DIAGNOSTIC_ANEGF (1 << 12) /* Bit 12: Auto-Negotiation Failure */
+#define LM_DIAGNOSTIC_RX_LOCK (1 << 8) /* Bit 8: Receive PLL Lock */
+#define LM_DIAGNOSTIC_RXSD (1 << 9) /* Bit 9: Receive Detection */
+#define LM_DIAGNOSTIC_RATE (1 << 10) /* Bit 10: Rate */
+#define LM_DIAGNOSTIC_DPLX (1 << 11) /* Bit 11: Duplex Mode */
+#define LM_DIAGNOSTIC_ANEGF (1 << 12) /* Bit 12: Auto-Negotiation Failure */
/* LM3S6918 Transceiver Control, address 0x13 */
-#define LM3S_XCVRCONTROL_TXO_SHIFT 14 /* Bits 15-14: Transmit Amplitude Selection */
-#define LM3S_XCVRCONTROL_TXO_MASK (3 << LM3S_XCVRCONTROL_TXO_SHIFT)
-#define LM3S_XCVRCONTROL_TXO_00DB (0 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.0dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_04DB (1 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.4dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_08DB (2 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.8dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_12DB (3 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 1.2dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_SHIFT 14 /* Bits 15-14: Transmit Amplitude Selection */
+#define LM_XCVRCONTROL_TXO_MASK (3 << LM_XCVRCONTROL_TXO_SHIFT)
+#define LM_XCVRCONTROL_TXO_00DB (0 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.0dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_04DB (1 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.4dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_08DB (2 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.8dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_12DB (3 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 1.2dB of insertion loss */
/* LM3S6918 LED Configuration, address 0x17 */
-#define LM3S_LEDCONFIG_LED0_SHIFT (0) /* Bits 3-0: LED0 Source */
-#define LM3S_LEDCONFIG_LED0_MASK (0x0f << LM3S_LEDCONFIG_LED0_SHIFT)
-#define LM3S_LEDCONFIG_LED0_LINKOK (0 << LM3S_LEDCONFIG_LED0_SHIFT) /* Link OK */
-#define LM3S_LEDCONFIG_LED0_RXTX (1 << LM3S_LEDCONFIG_LED0_SHIFT) /* RX or TX activity */
-#define LM3S_LEDCONFIG_LED0_100BASET (5 << LM3S_LEDCONFIG_LED0_SHIFT) /* 100BASE-TX mode */
-#define LM3S_LEDCONFIG_LED0_10BASET (6 << LM3S_LEDCONFIG_LED0_SHIFT) /* 10BASE-T mode */
-#define LM3S_LEDCONFIG_LED0_FDUPLEX (7 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED0_OKRXTX (8 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED1_SHIFT (4) /* Bits 7-4: LED1 Source */
-#define LM3S_LEDCONFIG_LED1_MASK (0x0f << LM3S_LEDCONFIG_LED1_SHIFT)
-#define LM3S_LEDCONFIG_LED1_LINKOK (0 << LM3S_LEDCONFIG_LED1_SHIFT) /* Link OK */
-#define LM3S_LEDCONFIG_LED1_RXTX (1 << LM3S_LEDCONFIG_LED1_SHIFT) /* RX or TX activity */
-#define LM3S_LEDCONFIG_LED1_100BASET (5 << LM3S_LEDCONFIG_LED1_SHIFT) /* 100BASE-TX mode */
-#define LM3S_LEDCONFIG_LED1_10BASET (6 << LM3S_LEDCONFIG_LED1_SHIFT) /* 10BASE-T mode */
-#define LM3S_LEDCONFIG_LED1_FDUPLEX (7 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED1_OKRXTX (8 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED0_SHIFT (0) /* Bits 3-0: LED0 Source */
+#define LM_LEDCONFIG_LED0_MASK (0x0f << LM_LEDCONFIG_LED0_SHIFT)
+#define LM_LEDCONFIG_LED0_LINKOK (0 << LM_LEDCONFIG_LED0_SHIFT) /* Link OK */
+#define LM_LEDCONFIG_LED0_RXTX (1 << LM_LEDCONFIG_LED0_SHIFT) /* RX or TX activity */
+#define LM_LEDCONFIG_LED0_100BASET (5 << LM_LEDCONFIG_LED0_SHIFT) /* 100BASE-TX mode */
+#define LM_LEDCONFIG_LED0_10BASET (6 << LM_LEDCONFIG_LED0_SHIFT) /* 10BASE-T mode */
+#define LM_LEDCONFIG_LED0_FDUPLEX (7 << LM_LEDCONFIG_LED0_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED0_OKRXTX (8 << LM_LEDCONFIG_LED0_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED1_SHIFT (4) /* Bits 7-4: LED1 Source */
+#define LM_LEDCONFIG_LED1_MASK (0x0f << LM_LEDCONFIG_LED1_SHIFT)
+#define LM_LEDCONFIG_LED1_LINKOK (0 << LM_LEDCONFIG_LED1_SHIFT) /* Link OK */
+#define LM_LEDCONFIG_LED1_RXTX (1 << LM_LEDCONFIG_LED1_SHIFT) /* RX or TX activity */
+#define LM_LEDCONFIG_LED1_100BASET (5 << LM_LEDCONFIG_LED1_SHIFT) /* 100BASE-TX mode */
+#define LM_LEDCONFIG_LED1_10BASET (6 << LM_LEDCONFIG_LED1_SHIFT) /* 10BASE-T mode */
+#define LM_LEDCONFIG_LED1_FDUPLEX (7 << LM_LEDCONFIG_LED1_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED1_OKRXTX (8 << LM_LEDCONFIG_LED1_SHIFT) /* Full duplex */
/* LM3S6918 MDI/MDIX Control, address 0x18 */
-#define LM3S_MDICONTROL_MDIXSD_SHIFT (0) /* Bits 3-0: Auto-Switching Seed */
-#define LM3S_MDICONTROL_MDIXSD_MASK (0x0f << LM3S_MDICONTROL_MDIXSD_SHIFT)
-#define LM3S_MDICONTROL_MDIXCM (1 << 4) /* Bit 4: Auto-Switching Complete */
-#define LM3S_MDICONTROL_MDIX (1 << 5) /* Bit 5: Auto-Switching Configuration */
-#define LM3S_MDICONTROL_AUTOSW (1 << 6) /* Bit 6: Auto-Switching Enable */
-#define LM3S_MDICONTROL_PDMODE (1 << 7) /* Bit 7: Parallel Detection Mode */
+#define LM_MDICONTROL_MDIXSD_SHIFT (0) /* Bits 3-0: Auto-Switching Seed */
+#define LM_MDICONTROL_MDIXSD_MASK (0x0f << LM_MDICONTROL_MDIXSD_SHIFT)
+#define LM_MDICONTROL_MDIXCM (1 << 4) /* Bit 4: Auto-Switching Complete */
+#define LM_MDICONTROL_MDIX (1 << 5) /* Bit 5: Auto-Switching Configuration */
+#define LM_MDICONTROL_AUTOSW (1 << 6) /* Bit 6: Auto-Switching Enable */
+#define LM_MDICONTROL_PDMODE (1 << 7) /* Bit 7: Parallel Detection Mode */
/* KS8921-specific register bit settings ************************************/
/* KS8921 MII Control register bit definitions (not in 802.3) */
@@ -430,26 +430,26 @@
/* KS8921 10BASE-TX PHY control register */
-#define KS8721_10BTCR_BIT0 (1 << 0) /* Bit 0: xxx */
-#define KS8721_10BTCR_BIT1 (1 << 1) /* Bit 1: xxx */
-#define KS8721_10BTCR_MODE_SHIFT (2) /* Bits 2-4: Operation Mode Indication */
-#define KS8721_10BTCR_MODE_MASK (7 << KS8721_10BTCR_MODE_SHIFT)
-# define KS8721_10BTCR_MODE_ANEG (0 << KS8721_10BTCR_MODE_SHIFT) /* Still in auto-negotiation */
-# define KS8721_10BTCR_MODE_10BTHD (1 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T half-duplex */
-# define KS8721_10BTCR_MODE_100BTHD (2 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE_t half-duplex */
-# define KS8721_10BTCR_MODE_DEFAULT (3 << KS8721_10BTCR_MODE_SHIFT) /* Default */
-# define KS8721_10BTCR_MODE_10BTFD (5 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T full duplex */
-# define KS8721_10BTCR_MODE_100BTFD (6 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE-T full duplex */
-# define KS8721_10BTCR_MODE_ISOLATE (7 << KS8721_10BTCR_MODE_SHIFT) /* PHY/MII isolate */
-#define KS8721_10BTCR_ISOLATE (1 << 5) /* Bit 5: PHY isolate */
-#define KS8721_10BTCR_PAUSE (1 << 6) /* Bit 6: Enable pause */
-#define KS8721_10BTCR_ANEGCOMP (1 << 7) /* Bit 7: Auto-negotiation complete */
-#define KS8721_10BTCR_JABBERE (1 << 8) /* Bit 8: Enable Jabber */
-#define KS8721_10BTCR_INTLVL (1 << 9) /* Bit 9: Interrupt level */
-#define KS8721_10BTCR_POWER (1 << 10) /* Bit 10: Power saving */
-#define KS8721_10BTCR_FORCE (1 << 11) /* Bit 11: Force link */
-#define KS8721_10BTCR_ENERGY (1 << 12) /* Bit 12: Energy detect */
-#define KS8721_10BTCR_PAIRSWAPD (1 << 13) /* Bit 13: Pairswap disable */
+#define KS8721_10BTCR_BIT0 (1 << 0) /* Bit 0: xxx */
+#define KS8721_10BTCR_BIT1 (1 << 1) /* Bit 1: xxx */
+#define KS8721_10BTCR_MODE_SHIFT (2) /* Bits 2-4: Operation Mode Indication */
+#define KS8721_10BTCR_MODE_MASK (7 << KS8721_10BTCR_MODE_SHIFT)
+# define KS8721_10BTCR_MODE_ANEG (0 << KS8721_10BTCR_MODE_SHIFT) /* Still in auto-negotiation */
+# define KS8721_10BTCR_MODE_10BTHD (1 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T half-duplex */
+# define KS8721_10BTCR_MODE_100BTHD (2 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE_t half-duplex */
+# define KS8721_10BTCR_MODE_DEFAULT (3 << KS8721_10BTCR_MODE_SHIFT) /* Default */
+# define KS8721_10BTCR_MODE_10BTFD (5 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T full duplex */
+# define KS8721_10BTCR_MODE_100BTFD (6 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE-T full duplex */
+# define KS8721_10BTCR_MODE_ISOLATE (7 << KS8721_10BTCR_MODE_SHIFT) /* PHY/MII isolate */
+#define KS8721_10BTCR_ISOLATE (1 << 5) /* Bit 5: PHY isolate */
+#define KS8721_10BTCR_PAUSE (1 << 6) /* Bit 6: Enable pause */
+#define KS8721_10BTCR_ANEGCOMP (1 << 7) /* Bit 7: Auto-negotiation complete */
+#define KS8721_10BTCR_JABBERE (1 << 8) /* Bit 8: Enable Jabber */
+#define KS8721_10BTCR_INTLVL (1 << 9) /* Bit 9: Interrupt level */
+#define KS8721_10BTCR_POWER (1 << 10) /* Bit 10: Power saving */
+#define KS8721_10BTCR_FORCE (1 << 11) /* Bit 11: Force link */
+#define KS8721_10BTCR_ENERGY (1 << 12) /* Bit 12: Energy detect */
+#define KS8721_10BTCR_PAIRSWAPD (1 << 13) /* Bit 13: Pairswap disable */
/****************************************************************************
* Type Definitions
diff --git a/nuttx/include/nuttx/nx/nxfonts.h b/nuttx/include/nuttx/nx/nxfonts.h
index f1aecb9e5..91bce0036 100644
--- a/nuttx/include/nuttx/nx/nxfonts.h
+++ b/nuttx/include/nuttx/nx/nxfonts.h
@@ -113,6 +113,11 @@
#elif defined(CONFIG_NXFONT_SERIF38X49B)
# define NXFONT_DEFAULT FONTID_SERIF38X49B
+/* Mono-space fonts */
+
+#elif defined(CONFIG_NXFONT_MONO5X8)
+# define NXFONT_DEFAULT FONTID_MONO5X8
+
#endif
/****************************************************************************
@@ -125,6 +130,12 @@ enum nx_fontid_e
{
FONTID_DEFAULT = 0 /* The default font */
+/* Monospace fonts */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+ , FONTID_MONO5X8 = 18 /* The 5x8 monospace font */
+#endif
+
/* Sans Serif fonts */
#ifdef CONFIG_NXFONT_SANS17X22
diff --git a/nuttx/include/nuttx/progmem.h b/nuttx/include/nuttx/progmem.h
index ac5a65940..2da59eab1 100644
--- a/nuttx/include/nuttx/progmem.h
+++ b/nuttx/include/nuttx/progmem.h
@@ -99,7 +99,7 @@ uint16_t up_progmem_pagesize(uint16_t page);
* Address to page conversion
*
* Input Parameters:
- * addr - Address without flash offet (aligned to page0)
+ * addr - Address with of without flash offset (absolute or aligned to page0)
*
* Returned Value:
* Page or negative value on error. The following errors are reported
@@ -165,7 +165,7 @@ int up_progmem_ispageerased(uint16_t page);
* the address be aligned inside the page boundaries.
*
* Input Parameters:
- * addr - Address without flash offet (aligned to page0)
+ * addr - Address with or without flash offset (absolute or aligned to page0)
* buf - Pointer to buffer
* count - Number of bytes to write *
*
diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h
index 6eaba6e9c..1e75b5020 100644
--- a/nuttx/include/nuttx/sched.h
+++ b/nuttx/include/nuttx/sched.h
@@ -1,7 +1,7 @@
/********************************************************************************
* include/nuttx/sched.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -62,21 +62,31 @@
/* This is the maximum number of times that a lock can be set */
-#define MAX_LOCK_COUNT 127
+#define MAX_LOCK_COUNT 127
/* Values for the _TCB flags flag bits */
-#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */
-#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT)
-# define TCB_FLAG_TTYPE_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */
-# define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */
-# define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */
-#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
-#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
-#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
+#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */
+#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT)
+# define TCB_FLAG_TTYPE_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */
+# define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */
+# define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */
+#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
+#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
+#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
+#define TCB_FLAG_NOCLDWAIT (1 << 5) /* Bit 5: Do not retain child exit status */
+
+/* Values for struct child_status_s ch_flags */
+
+#define CHILD_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: child thread type */
+#define CHILD_FLAG_TTYPE_MASK (3 << CHILD_FLAG_TTYPE_SHIFT)
+# define CHILD_FLAG_TTYPE_TASK (0 << CHILD_FLAG_TTYPE_SHIFT) /* Normal user task */
+# define CHILD_FLAG_TTYPE_PTHREAD (1 << CHILD_FLAG_TTYPE_SHIFT) /* User pthread */
+# define CHILD_FLAG_TTYPE_KERNEL (2 << CHILD_FLAG_TTYPE_SHIFT) /* Kernel thread */
+#define CHILD_FLAG_EXITED (1 << 0) /* Bit 2: The child thread has exit'ed */
/********************************************************************************
- * Global Type Definitions
+ * Public Type Definitions
********************************************************************************/
#ifndef __ASSEMBLY__
@@ -163,6 +173,22 @@ typedef struct environ_s environ_t;
# define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1)
#endif
+/* This structure is used to maintin information about child tasks.
+ * pthreads work differently, they have join information. This is
+ * only for child tasks.
+ */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+struct child_status_s
+{
+ FAR struct child_status_s *flink;
+
+ uint8_t ch_flags; /* Child status: See CHILD_FLAG_* definitions */
+ pid_t ch_pid; /* Child task ID */
+ int ch_status; /* Child exit status */
+};
+#endif
+
/* This structure describes a reference counted D-Space region. This must be a
* separately allocated "break-away" structure that can be owned by a task and
* any pthreads created by the task.
@@ -202,6 +228,14 @@ struct _TCB
/* Task Management Fields *****************************************************/
pid_t pid; /* This is the ID of the thread */
+#ifdef CONFIG_SCHED_HAVE_PARENT /* Support parent-child relationship */
+ pid_t parent; /* This is the ID of the parent thread */
+#ifdef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
+ FAR struct child_status_s *children; /* Head of a list of child status */
+#else
+ uint16_t nchildren; /* This is the number active children */
+#endif
+#endif
start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */
@@ -223,7 +257,7 @@ struct _TCB
# endif
#endif
-#ifdef CONFIG_SCHED_WAITPID
+#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
sem_t exitsem; /* Support for waitpid */
int *stat_loc; /* Location to return exit status */
#endif
@@ -353,41 +387,72 @@ typedef void (*sched_foreach_t)(FAR _TCB *tcb, FAR void *arg);
#endif /* __ASSEMBLY__ */
/********************************************************************************
- * Global Function Prototypes
+ * Public Data
********************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
+/********************************************************************************
+ * Public Function Prototypes
+ ********************************************************************************/
+
/* TCB helpers */
-EXTERN FAR _TCB *sched_self(void);
+FAR _TCB *sched_self(void);
/* File system helpers */
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN FAR struct filelist *sched_getfiles(void);
+FAR struct filelist *sched_getfiles(void);
#if CONFIG_NFILE_STREAMS > 0
-EXTERN FAR struct streamlist *sched_getstreams(void);
+FAR struct streamlist *sched_getstreams(void);
#endif /* CONFIG_NFILE_STREAMS */
#endif /* CONFIG_NFILE_DESCRIPTORS */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN FAR struct socketlist *sched_getsockets(void);
+FAR struct socketlist *sched_getsockets(void);
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
+/* Internal vfork support.The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() is provided in architecture-specific
+ * code.
+ * 2) vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) vfork() provides any additional operating context. vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * task_vforkabort() may be called if an error occurs between steps 3 and 6.
+ */
+
+FAR _TCB *task_vforksetup(start_t retaddr);
+pid_t task_vforkstart(FAR _TCB *child);
+void task_vforkabort(FAR _TCB *child, int errcode);
+
/* sched_foreach will enumerate over each task and provide the
* TCB of each task to a user callback functions. Interrupts
* will be disabled throughout this enumeration!
*/
-EXTERN void sched_foreach(sched_foreach_t handler, FAR void *arg);
+void sched_foreach(sched_foreach_t handler, FAR void *arg);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/nuttx/serial/tioctl.h b/nuttx/include/nuttx/serial/tioctl.h
index b309ff37c..a98b487a6 100644
--- a/nuttx/include/nuttx/serial/tioctl.h
+++ b/nuttx/include/nuttx/serial/tioctl.h
@@ -1,7 +1,7 @@
/********************************************************************************************
* include/nuttx/serial/tioctl.h
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -165,16 +165,23 @@
#define TIOCSRS485 _TIOC(0x002a) /* Set RS485 mode, arg: pointer to struct serial_rs485 */
#define TIOCGRS485 _TIOC(0x002b) /* Get RS485 mode, arg: pointer to struct serial_rs485 */
-/* Debugging */
+/* Definitions for flags used in struct serial_rs485 (Linux compatible) */
+
+# define SER_RS485_ENABLED (1 << 0) /* Enable/disble RS-485 support */
+# define SER_RS485_RTS_ON_SEND (1 << 1) /* Logic level for RTS pin when sending */
+# define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logic level for RTS pin after sent */
+# define SER_RS485_RX_DURING_TX (1 << 4)
+
+/* Single-wire UART support */
-#define TIOCSERGSTRUCT _TIOC(0x002c) /* Get device TTY structure */
+#define TIOCSSINGLEWIRE _TIOC(0x002c) /* Set single-wire mode */
+#define TIOCGSINGLEWIRE _TIOC(0x002d) /* Get single-wire mode */
-/* Definitions used in struct serial_rs485 (Linux compatible) */
+# define SER_SINGLEWIRE_ENABLED (1 << 0) /* Enable/disable single-wire support */
+
+/* Debugging */
-#define SER_RS485_ENABLED (1 << 0) /* Enable/disble RS-485 support */
-#define SER_RS485_RTS_ON_SEND (1 << 1) /* Logic level for RTS pin when sending */
-#define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logic level for RTS pin after sent */
-#define SER_RS485_RX_DURING_TX (1 << 4)
+#define TIOCSERGSTRUCT _TIOC(0x002e) /* Get device TTY structure */
/********************************************************************************************
* Public Type Definitions
diff --git a/nuttx/include/nuttx/spawn.h b/nuttx/include/nuttx/spawn.h
new file mode 100644
index 000000000..f84ae8355
--- /dev/null
+++ b/nuttx/include/nuttx/spawn.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * include/nuttx/spawn.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_SPAWN_H
+#define __INCLUDE_NUTTX_SPAWN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+/* This enumerator identifies a file action */
+
+enum spawn_file_actions_e
+{
+ SPAWN_FILE_ACTION_NONE = 0,
+ SPAWN_FILE_ACTION_CLOSE,
+ SPAWN_FILE_ACTION_DUP2,
+ SPAWN_FILE_ACTION_OPEN
+};
+
+/* posix_spawn_file_actions_addclose(), posix_spawn_file_actions_adddup2(),
+ * and posix_spawn_file_actions_addopen() will allocate memory and append
+ * a new file action to an instance of posix_spawn_file_actions_t. The
+ * internal representation of these structures are defined below:
+ */
+
+struct spawn_general_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* A member of enum spawn_file_actions_e */
+};
+
+struct spawn_close_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_CLOSE */
+ int fd; /* The file descriptor to close */
+};
+
+struct spawn_dup2_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_DUP2 */
+ int fd1; /* The first file descriptor for dup2() */
+ int fd2; /* The second file descriptor for dup2() */
+};
+
+struct spawn_open_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_OPEN */
+ int fd; /* The file descriptor after opening */
+ int oflags; /* Open flags */
+ mode_t mode; /* File creation mode */
+ char path[1]; /* Start of the path to be
+ * opened */
+};
+
+#define SIZEOF_OPEN_FILE_ACTION_S(n) \
+ (sizeof(struct spawn_open_file_action_s) + (n))
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void add_file_action(FAR posix_spawn_file_actions_t *file_action,
+ FAR struct spawn_general_file_action_s *entry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_SPAWN_H */
diff --git a/nuttx/include/nuttx/usb/hid.h b/nuttx/include/nuttx/usb/hid.h
index 5b83f08fc..877203a9c 100644
--- a/nuttx/include/nuttx/usb/hid.h
+++ b/nuttx/include/nuttx/usb/hid.h
@@ -619,7 +619,7 @@
#define USBHID_KBDUSE_RCTRL 0xe4 /* Keyboard RightControl */
#define USBHID_KBDUSE_RSHIFT 0xe5 /* Keyboard RightShift */
#define USBHID_KBDUSE_RALT 0xe6 /* Keyboard RightAlt */
-#define USBHID_KBDUSE_RGUI 0xe7 /* Keyboard Right GUI*/
+#define USBHID_KBDUSE_RGUI 0xe7 /* Keyboard Right GUI */
#define USBHID_KBDUSE_MAX 0xe7
diff --git a/nuttx/include/nuttx/wqueue.h b/nuttx/include/nuttx/wqueue.h
index c509bf197..d56901d89 100644
--- a/nuttx/include/nuttx/wqueue.h
+++ b/nuttx/include/nuttx/wqueue.h
@@ -68,7 +68,7 @@
* CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
* thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
* CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
- * the worker thread. Default: 4
+ * the worker thread. Default: 17
*
* CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
* work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
diff --git a/nuttx/include/pthread.h b/nuttx/include/pthread.h
index 5a08f13b6..a98b9aaaa 100644
--- a/nuttx/include/pthread.h
+++ b/nuttx/include/pthread.h
@@ -41,15 +41,17 @@
********************************************************************************/
#include <nuttx/config.h> /* Default settings */
-#include <nuttx/compiler.h> /* Compiler settings */
+#include <nuttx/compiler.h> /* Compiler settings, noreturn_function */
#include <sys/types.h> /* Needed for general types */
+#include <sys/prctl.h> /* Needed by pthread_[set|get]name_np */
+
#include <stdint.h> /* C99 fixed width integer types */
#include <stdbool.h> /* C99 boolean types */
+#include <unistd.h> /* For getpid */
#include <semaphore.h> /* Needed for sem_t */
#include <signal.h> /* Needed for sigset_t */
#include <time.h> /* Needed for struct timespec */
-#include <nuttx/compiler.h> /* For noreturn_function */
/********************************************************************************
* Compilation Switches
@@ -58,10 +60,11 @@
/* Standard POSIX switches */
#ifndef _POSIX_THREADS
-#define _POSIX_THREADS
+# define _POSIX_THREADS
#endif
+
#ifndef _POSIX_THREAD_ATTR_STACKSIZE
-#define _POSIX_THREAD_ATTR_STACKSIZE
+# define _POSIX_THREAD_ATTR_STACKSIZE
#endif
/********************************************************************************
@@ -153,10 +156,8 @@
********************************************************************************/
#ifdef __cplusplus
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
+extern "C"
+{
#endif
/* pthread-specific types */
@@ -245,28 +246,29 @@ struct sched_param; /* Defined in sched.h */
* the individual attributes used by a given implementation.
*/
-EXTERN int pthread_attr_init(FAR pthread_attr_t *attr);
+int pthread_attr_init(FAR pthread_attr_t *attr);
/* An attributes object can be deleted when it is no longer needed. */
-EXTERN int pthread_attr_destroy(pthread_attr_t *attr);
+int pthread_attr_destroy(pthread_attr_t *attr);
/* Set or obtain the default scheduling algorithm */
-EXTERN int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy);
-EXTERN int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy);
-EXTERN int pthread_attr_setschedparam(FAR pthread_attr_t *attr,
- FAR const struct sched_param *param);
-EXTERN int pthread_attr_getschedparam(FAR pthread_attr_t *attr,
- FAR struct sched_param *param);
-EXTERN int pthread_attr_setinheritsched(FAR pthread_attr_t *attr, int inheritsched);
-EXTERN int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr,
- FAR int *inheritsched);
+int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy);
+int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy);
+int pthread_attr_setschedparam(FAR pthread_attr_t *attr,
+ FAR const struct sched_param *param);
+int pthread_attr_getschedparam(FAR pthread_attr_t *attr,
+ FAR struct sched_param *param);
+int pthread_attr_setinheritsched(FAR pthread_attr_t *attr,
+ int inheritsched);
+int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr,
+ FAR int *inheritsched);
/* Set or obtain the default stack size */
-EXTERN int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize);
-EXTERN int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
+int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize);
+int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
/* To create a thread object and runnable thread, a routine must be specified
* as the new thread's start routine. An argument may be passed to this
@@ -275,34 +277,33 @@ EXTERN int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
* about the kind of thread being created.
*/
-EXTERN int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
- pthread_startroutine_t startroutine,
- pthread_addr_t arg);
+int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
+ pthread_startroutine_t startroutine, pthread_addr_t arg);
/* A thread object may be "detached" to specify that the return value and
* completion status will not be requested.
*/
-EXTERN int pthread_detach(pthread_t thread);
+int pthread_detach(pthread_t thread);
/* A thread may terminate it's own execution or the execution of another
* thread.
*/
-EXTERN void pthread_exit(pthread_addr_t value) noreturn_function;
-EXTERN int pthread_cancel(pthread_t thread);
-EXTERN int pthread_setcancelstate(int state, FAR int *oldstate);
-EXTERN void pthread_testcancel(void);
+void pthread_exit(pthread_addr_t value) noreturn_function;
+int pthread_cancel(pthread_t thread);
+int pthread_setcancelstate(int state, FAR int *oldstate);
+void pthread_testcancel(void);
/* A thread can await termination of another thread and retrieve the return
* value of the thread.
*/
-EXTERN int pthread_join(pthread_t thread, FAR pthread_addr_t *value);
+int pthread_join(pthread_t thread, FAR pthread_addr_t *value);
/* A thread may tell the scheduler that its processor can be made available. */
-EXTERN void pthread_yield(void);
+void pthread_yield(void);
/* A thread may obtain a copy of its own thread handle. */
@@ -314,91 +315,94 @@ EXTERN void pthread_yield(void);
/* Thread scheduling parameters */
-EXTERN int pthread_getschedparam(pthread_t thread, FAR int *policy,
- FAR struct sched_param *param);
-EXTERN int pthread_setschedparam(pthread_t thread, int policy,
- FAR const struct sched_param *param);
-EXTERN int pthread_setschedprio(pthread_t thread, int prio);
+int pthread_getschedparam(pthread_t thread, FAR int *policy,
+ FAR struct sched_param *param);
+int pthread_setschedparam(pthread_t thread, int policy,
+ FAR const struct sched_param *param);
+int pthread_setschedprio(pthread_t thread, int prio);
/* Thread-specific Data Interfaces */
-EXTERN int pthread_key_create(FAR pthread_key_t *key,
- CODE void (*destructor)(FAR void*));
-EXTERN int pthread_setspecific(pthread_key_t key, FAR void *value);
-EXTERN FAR void *pthread_getspecific(pthread_key_t key);
-EXTERN int pthread_key_delete(pthread_key_t key);
+int pthread_key_create(FAR pthread_key_t *key,
+ CODE void (*destructor)(FAR void*));
+int pthread_setspecific(pthread_key_t key, FAR void *value);
+FAR void *pthread_getspecific(pthread_key_t key);
+int pthread_key_delete(pthread_key_t key);
/* Create, operate on, and destroy mutex attributes. */
-EXTERN int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr, FAR int *pshared);
-EXTERN int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr, int pshared);
+int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr);
+int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr);
+int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr,
+ FAR int *pshared);
+int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr,
+ int pshared);
#ifdef CONFIG_MUTEX_TYPES
-EXTERN int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
-EXTERN int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
+int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
#endif
/* The following routines create, delete, lock and unlock mutexes. */
-EXTERN int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutex_destroy(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_lock(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_trylock(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_unlock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_init(FAR pthread_mutex_t *mutex,
+ FAR pthread_mutexattr_t *attr);
+int pthread_mutex_destroy(FAR pthread_mutex_t *mutex);
+int pthread_mutex_lock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_trylock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_unlock(FAR pthread_mutex_t *mutex);
/* Operations on condition variables */
-EXTERN int pthread_condattr_init(FAR pthread_condattr_t *attr);
-EXTERN int pthread_condattr_destroy(FAR pthread_condattr_t *attr);
+int pthread_condattr_init(FAR pthread_condattr_t *attr);
+int pthread_condattr_destroy(FAR pthread_condattr_t *attr);
/* A thread can create and delete condition variables. */
-EXTERN int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr);
-EXTERN int pthread_cond_destroy(FAR pthread_cond_t *cond);
+int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr);
+int pthread_cond_destroy(FAR pthread_cond_t *cond);
/* A thread can signal to and broadcast on a condition variable. */
-EXTERN int pthread_cond_broadcast(FAR pthread_cond_t *cond);
-EXTERN int pthread_cond_signal(FAR pthread_cond_t *cond);
+int pthread_cond_broadcast(FAR pthread_cond_t *cond);
+int pthread_cond_signal(FAR pthread_cond_t *cond);
/* A thread can wait for a condition variable to be signalled or broadcast. */
-EXTERN int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex);
+int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex);
/* A thread can perform a timed wait on a condition variable. */
-EXTERN int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
- FAR const struct timespec *abstime);
+int pthread_cond_timedwait(FAR pthread_cond_t *cond,
+ FAR pthread_mutex_t *mutex,
+ FAR const struct timespec *abstime);
/* Barrier attributes */
-EXTERN int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
-EXTERN int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr);
-EXTERN int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr,
- FAR int *pshared);
-EXTERN int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr,
- int pshared);
+int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
+int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr);
+int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr,
+ FAR int *pshared);
+int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr,
+ int pshared);
/* Barriers */
-EXTERN int pthread_barrier_destroy(FAR pthread_barrier_t *barrier);
-EXTERN int pthread_barrier_init(FAR pthread_barrier_t *barrier,
+int pthread_barrier_destroy(FAR pthread_barrier_t *barrier);
+int pthread_barrier_init(FAR pthread_barrier_t *barrier,
FAR const pthread_barrierattr_t *attr,
unsigned int count);
-EXTERN int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
+int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
/* Pthread initialization */
-EXTERN int pthread_once(FAR pthread_once_t *once_control,
+int pthread_once(FAR pthread_once_t *once_control,
CODE void (*init_routine)(void));
/* Pthread signal management APIs */
-EXTERN int pthread_kill(pthread_t thread, int sig);
-EXTERN int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
+int pthread_kill(pthread_t thread, int sig);
+int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
-#undef EXTERN
#ifdef __cplusplus
}
#endif
diff --git a/nuttx/include/sched.h b/nuttx/include/sched.h
index 4494d8ef5..9ccbf57b2 100644
--- a/nuttx/include/sched.h
+++ b/nuttx/include/sched.h
@@ -79,7 +79,7 @@
#endif
/********************************************************************************
- * Global Type Definitions
+ * Public Type Definitions
********************************************************************************/
/* This is the POSIX-like scheduling parameter structure */
@@ -90,56 +90,61 @@ struct sched_param
};
/********************************************************************************
- * Global Function Prototypes
+ * Public Data
********************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
+/********************************************************************************
+ * Public Function Prototypes
+ ********************************************************************************/
+
/* Task Control Interfaces (non-standard) */
#ifndef CONFIG_CUSTOM_STACK
-EXTERN int task_init(FAR _TCB *tcb, const char *name, int priority,
- FAR uint32_t *stack, uint32_t stack_size,
- main_t entry, const char *argv[]);
+int task_init(FAR _TCB *tcb, const char *name, int priority,
+ FAR uint32_t *stack, uint32_t stack_size, main_t entry,
+ FAR const char *argv[]);
#else
-EXTERN int task_init(FAR _TCB *tcb, const char *name, int priority,
- main_t entry, const char *argv[]);
+int task_init(FAR _TCB *tcb, const char *name, int priority, main_t entry,
+ FAR const char *argv[]);
#endif
-EXTERN int task_activate(FAR _TCB *tcb);
+int task_activate(FAR _TCB *tcb);
#ifndef CONFIG_CUSTOM_STACK
-EXTERN int task_create(const char *name, int priority, int stack_size,
- main_t entry, const char *argv[]);
+int task_create(FAR const char *name, int priority, int stack_size, main_t entry,
+ FAR const char *argv[]);
#else
-EXTERN int task_create(const char *name, int priority,
- main_t entry, const char *argv[]);
+int task_create(FAR const char *name, int priority, main_t entry,
+ FAR const char *argv[]);
#endif
-EXTERN int task_delete(pid_t pid);
-EXTERN int task_restart(pid_t pid);
+int task_delete(pid_t pid);
+int task_restart(pid_t pid);
/* Task Scheduling Interfaces (based on POSIX APIs) */
-EXTERN int sched_setparam(pid_t pid, const struct sched_param *param);
-EXTERN int sched_getparam(pid_t pid, struct sched_param *param);
-EXTERN int sched_setscheduler(pid_t pid, int policy,
- const struct sched_param *param);
-EXTERN int sched_getscheduler(pid_t pid);
-EXTERN int sched_yield(void);
-EXTERN int sched_get_priority_max(int policy);
-EXTERN int sched_get_priority_min(int policy);
-EXTERN int sched_rr_get_interval(pid_t pid, struct timespec *interval);
+int sched_setparam(pid_t pid, const struct sched_param *param);
+int sched_getparam(pid_t pid, struct sched_param *param);
+int sched_setscheduler(pid_t pid, int policy,
+ FAR const struct sched_param *param);
+int sched_getscheduler(pid_t pid);
+int sched_yield(void);
+int sched_get_priority_max(int policy);
+int sched_get_priority_min(int policy);
+int sched_rr_get_interval(pid_t pid, FAR struct timespec *interval);
/* Task Switching Interfaces (non-standard) */
-EXTERN int sched_lock(void);
-EXTERN int sched_unlock(void);
-EXTERN int sched_lockcount(void);
+int sched_lock(void);
+int sched_unlock(void);
+int sched_lockcount(void);
/* If instrumentation of the scheduler is enabled, then some outboard logic
* must provide the following interfaces.
@@ -147,9 +152,9 @@ EXTERN int sched_lockcount(void);
#ifdef CONFIG_SCHED_INSTRUMENTATION
-EXTERN void sched_note_start(FAR _TCB *tcb);
-EXTERN void sched_note_stop(FAR _TCB *tcb);
-EXTERN void sched_note_switch(FAR _TCB *pFromTcb, FAR _TCB *pToTcb);
+void sched_note_start(FAR _TCB *tcb);
+void sched_note_stop(FAR _TCB *tcb);
+void sched_note_switch(FAR _TCB *pFromTcb, FAR _TCB *pToTcb);
#else
# define sched_note_start(t)
diff --git a/nuttx/include/semaphore.h b/nuttx/include/semaphore.h
index 257a5826f..203118bd6 100644
--- a/nuttx/include/semaphore.h
+++ b/nuttx/include/semaphore.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/semaphore.h
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -103,9 +103,13 @@ typedef struct sem_s sem_t;
/* Initializers */
#ifdef CONFIG_PRIORITY_INHERITANCE
-# define SEM_INITIALIZER(c) {(c), SEMHOLDER_INITIALIZER}
+# if CONFIG_SEM_PREALLOCHOLDERS > 0
+# define SEM_INITIALIZER(c) {(c), NULL} /* semcount, hhead */
+# else
+# define SEM_INITIALIZER(c) {(c), SEMHOLDER_INITIALIZER} /* semcount, holder */
+# endif
#else
-# define SEM_INITIALIZER(c) {(c)}
+# define SEM_INITIALIZER(c) {(c)} /* semcount */
#endif
/****************************************************************************
diff --git a/nuttx/include/signal.h b/nuttx/include/signal.h
index 02b222343..a02170242 100644
--- a/nuttx/include/signal.h
+++ b/nuttx/include/signal.h
@@ -61,49 +61,64 @@
/* All signals are "real time" signals */
-#define SIGRTMIN 0 /* First real time signal */
-#define SIGRTMAX 31 /* Last real time signal */
+#define SIGRTMIN MIN_SIGNO /* First real time signal */
+#define SIGRTMAX MAX_SIGNO /* Last real time signal */
/* A few of the real time signals are used within the OS. They have
* default values that can be overridden from the configuration file. The
- * rest are all user signals:
+ * rest are all user signals.
+ *
+ * The signal number zero is wasted for the most part. It is a valid
+ * signal number, but has special meaning at many interfaces (e.g., Kill()).
+ *
+ * These are the semi-standard signal definitions:
*/
#ifndef CONFIG_SIG_SIGUSR1
-#define SIGUSR1 0 /* User signal 1 */
+# define SIGUSR1 1 /* User signal 1 */
#else
-#define SIGUSR1 CONFIG_SIG_SIGUSR1
+# define SIGUSR1 CONFIG_SIG_SIGUSR1
#endif
#ifndef CONFIG_SIG_SIGUSR2
-#define SIGUSR2 1 /* User signal 2 */
+# define SIGUSR2 2 /* User signal 2 */
#else
-#define SIGUSR2 CONFIG_SIG_SIGUSR2
+# define SIGUSR2 CONFIG_SIG_SIGUSR2
#endif
#ifndef CONFIG_SIG_SIGALARM
-#define SIGALRM 2 /* Default signal used with POSIX timers (used only */
+# define SIGALRM 3 /* Default signal used with POSIX timers (used only */
/* no other signal is provided) */
#else
-#define SIGALRM CONFIG_SIG_SIGALARM
+# define SIGALRM CONFIG_SIG_SIGALARM
#endif
-#ifndef CONFIG_DISABLE_PTHREAD
-#ifndef CONFIG_SIG_SIGCONDTIMEDOUT
-#define SIGCONDTIMEDOUT 3 /* Used in the implementation of pthread_cond_timedwait */
-#else
-#define SIGCONDTIMEDOUT CONFIG_SIG_SIGCONDTIMEDOUT
+#ifdef CONFIG_SCHED_HAVE_PARENT
+# ifndef CONFIG_SIG_SIGCHLD
+# define SIGCHLD 4 /* Used by child threads to signal parent thread */
+# else
+# define SIGCHLD CONFIG_SIG_SIGCHLD
+# endif
#endif
+
+/* The following are non-standard signal definitions */
+
+#ifndef CONFIG_DISABLE_PTHREAD
+# ifndef CONFIG_SIG_SIGCONDTIMEDOUT
+# define SIGCONDTIMEDOUT 16 /* Used in the implementation of pthread_cond_timedwait */
+# else
+# define SIGCONDTIMEDOUT CONFIG_SIG_SIGCONDTIMEDOUT
+# endif
#endif
/* SIGWORK is used to wake up various internal, NuttX worker thread */
#if defined(CONFIG_SCHED_WORKQUEUE) || defined(CONFIG_PAGING)
-#ifndef CONFIG_SIG_SIGWORK
-#define SIGWORK 4 /* Used to wake up the work queue */
-#else
-#define SIGWORK CONFIG_SIG_SIGWORK
-#endif
+# ifndef CONFIG_SIG_SIGWORK
+# define SIGWORK 17 /* Used to wake up the work queue */
+# else
+# define SIGWORK CONFIG_SIG_SIGWORK
+# endif
#endif
/* sigprocmask() "how" definitions. Only one of the following can be specified: */
@@ -114,20 +129,28 @@
/* struct sigaction flag values */
-#define SA_NOCLDSTOP 1 /* Do not generate SIGCHILD when
- * children stop (ignored) */
-#define SA_SIGINFO 2 /* Invoke the signal-catching function
- * with 3 args instead of 1
- * (always assumed) */
+#define SA_NOCLDSTOP (1 << 0) /* Do not generate SIGCHILD when
+ * children stop (ignored) */
+#define SA_SIGINFO (1 << 1) /* Invoke the signal-catching function
+ * with 3 args instead of 1
+ * (always assumed) */
+#define SA_NOCLDWAIT (1 << 2) /* If signo=SIGCHLD, exit status of child
+ * processes will be discarded */
/* These are the possible values of the signfo si_code field */
-#define SI_USER 0 /* Signal sent from kill, raise, or abort */
-#define SI_QUEUE 1 /* Signal sent from sigqueue */
-#define SI_TIMER 2 /* Signal is result of timer expiration */
-#define SI_ASYNCIO 3 /* Signal is the result of asynch IO completion */
-#define SI_MESGQ 4 /* Signal generated by arrival of a message on an */
- /* empty message queue */
+#define SI_USER 0 /* Signal sent from kill, raise, or abort */
+#define SI_QUEUE 1 /* Signal sent from sigqueue */
+#define SI_TIMER 2 /* Signal is result of timer expiration */
+#define SI_ASYNCIO 3 /* Signal is the result of asynch IO completion */
+#define SI_MESGQ 4 /* Signal generated by arrival of a message on an */
+ /* empty message queue */
+#define CLD_EXITED 5 /* Child has exited (SIGCHLD only) */
+#define CLD_KILLED 6 /* Child was killed (SIGCHLD only) */
+#define CLD_DUMPED 7 /* Child terminated abnormally (SIGCHLD only) */
+#define CLD_TRAPPED 8 /* Traced child has trapped (SIGCHLD only) */
+#define CLD_STOPPED 9 /* Child has stopped (SIGCHLD only) */
+#define CLD_CONTINUED 10 /* Stopped child had continued (SIGCHLD only) */
/* Values for the sigev_notify field of struct sigevent */
@@ -175,6 +198,10 @@ struct siginfo
uint8_t si_signo; /* Identifies signal */
uint8_t si_code; /* Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ */
union sigval si_value; /* Data passed with signal */
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ pid_t si_pid; /* Sending task ID */
+ int si_status; /* Exit value or signal (SIGCHLD only). */
+#endif
};
typedef struct siginfo siginfo_t;
diff --git a/nuttx/include/spawn.h b/nuttx/include/spawn.h
new file mode 100644
index 000000000..5e0ce3416
--- /dev/null
+++ b/nuttx/include/spawn.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+ * include/spawn.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_SPAWN_H
+#define __INCLUDE_SPAWN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <sched.h>
+#include <signal.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* "The spawn.h header shall define the flags that may be set in a
+ * posix_spawnattr_t object using the posix_spawnattr_setflags() function:"
+ */
+
+#define POSIX_SPAWN_RESETIDS (1 << 0) /* 1: Reset effective user ID */
+#define POSIX_SPAWN_SETPGROUP (1 << 1) /* 1: Set process group */
+#define POSIX_SPAWN_SETSCHEDPARAM (1 << 2) /* 1: Set task's priority */
+#define POSIX_SPAWN_SETSCHEDULER (1 << 3) /* 1: Set task's scheduler policy */
+#define POSIX_SPAWN_SETSIGDEF (1 << 4) /* 1: Set default signal actions */
+#define POSIX_SPAWN_SETSIGMASK (1 << 5) /* 1: Set sigmask */
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+/* "The spawn.h header shall define the posix_spawnattr_t and
+ * posix_spawn_file_actions_t types used in performing spawn operations.
+ *
+ * The internal structure underlying the posix_spawnattr_t is exposed here
+ * because the user will be required to allocate this memory.
+ */
+
+struct posix_spawnattr_s
+{
+ uint8_t flags;
+ uint8_t priority;
+ uint8_t policy;
+#ifndef CONFIG_DISABLE_SIGNALS
+ sigset_t sigmask;
+#endif
+};
+
+typedef struct posix_spawnattr_s posix_spawnattr_t;
+
+/* posix_spawn_file_actions_addclose(), posix_spawn_file_actions_adddup2(),
+ * and posix_spawn_file_actions_addopen() will allocate memory and append
+ * a new file action to an instance of posix_spawn_file_actions_t. The
+ * internal representation of these structures is not exposed to the user.
+ * The user need only know that the size sizeof(posix_spawn_file_actions_t)
+ * will hold a pointer to data.
+ */
+
+typedef FAR void *posix_spawn_file_actions_t;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+/* "The following shall be declared as functions and may also be defined as
+ * macros. Function prototypes shall be provided."
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* posix_spawn[p] interfaces ************************************************/
+
+#ifdef CONFIG_BINFMT_EXEPATH
+int posix_spawnp(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[]);
+#define posix_spawn(pid,path,file_actions,attr,argv,envp) \
+ posix_spawnp(pid,path,file_actions,attr,argv,envp)
+#else
+int posix_spawn(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[]);
+#endif
+
+/* File action interfaces ***************************************************/
+/* File action initialization and destruction */
+
+int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions);
+int posix_spawn_file_actions_destroy(FAR posix_spawn_file_actions_t *file_actions);
+
+/* Add file action interfaces */
+
+int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actions,
+ int fd);
+int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_actions,
+ int fd1, int fd2);
+int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions,
+ int fd, FAR const char *path, int oflags, mode_t mode);
+
+/* Spawn attributes interfaces **********************************************/
+/* Spawn attributes initialization and destruction */
+
+int posix_spawnattr_init(FAR posix_spawnattr_t *attr);
+
+/* int posix_spawnattr_destroy(FAR posix_spawnattr_t *); */
+#ifdef CONFIG_DEBUG
+# define posix_spawnattr_destroy(attr) (attr ? 0 : EINVAL)
+#else
+# define posix_spawnattr_destroy(attr) (0)
+#endif
+
+/* Get spawn attributes interfaces */
+
+int posix_spawnattr_getflags(FAR const posix_spawnattr_t *attr, FAR short *flags);
+#define posix_spawnattr_getpgroup(attr,group) (ENOSYS)
+int posix_spawnattr_getschedparam(FAR const posix_spawnattr_t *attr,
+ FAR struct sched_param *param);
+int posix_spawnattr_getschedpolicy(FAR const posix_spawnattr_t *attr,
+ FAR int *policy);
+#define posix_spawnattr_getsigdefault(attr,sigdefault) (ENOSYS)
+#ifndef CONFIG_DISABLE_SIGNALS
+int posix_spawnattr_getsigmask(FAR const posix_spawnattr_t *attr,
+ FAR sigset_t *sigmask);
+#else
+# define posix_spawnattr_getsigmask(attr,sigmask) (ENOSYS)
+#endif
+
+/* Set spawn attributes interfaces */
+
+int posix_spawnattr_setflags(FAR posix_spawnattr_t *attr, short flags);
+#define posix_spawnattr_setpgroup(attr,group) (ENOSYS)
+int posix_spawnattr_setschedparam(FAR posix_spawnattr_t *attr,
+ FAR const struct sched_param *param);
+int posix_spawnattr_setschedpolicy(FAR posix_spawnattr_t *attr, int policy);
+#define posix_spawnattr_setsigdefault(attr,sigdefault) (ENOSYS)
+#ifndef CONFIG_DISABLE_SIGNALS
+int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr,
+ FAR const sigset_t *sigmask);
+#else
+# define posix_spawnattr_setsigmask(attr,sigmask) (ENOSYS)
+#endif
+
+/* Non standard debug functions */
+
+#ifdef CONFIG_DEBUG
+void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions);
+void posix_spawnattr_dump(FAR posix_spawnattr_t *attr);
+#else
+# define posix_spawn_file_actions_dump(fa)
+# define posix_spawnattr_dump(a)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_SPAWN_H */
diff --git a/nuttx/include/stdbool.h b/nuttx/include/stdbool.h
index 9c16aee29..6c3302549 100644
--- a/nuttx/include/stdbool.h
+++ b/nuttx/include/stdbool.h
@@ -90,8 +90,8 @@
# define bool _Bool8
#endif
-#define true 1
-#define false 0
+#define true (bool)1
+#define false (bool)0
#define __bool_true_false_are_defined 1
diff --git a/nuttx/include/sys/types.h b/nuttx/include/sys/types.h
index 2ae69d4a7..38f091e8a 100644
--- a/nuttx/include/sys/types.h
+++ b/nuttx/include/sys/types.h
@@ -154,15 +154,17 @@ typedef uint16_t dev_t;
typedef uint16_t ino_t;
-/* pid_t is used for process IDs and process group IDs */
+/* pid_t is used for process IDs and process group IDs. It must be signed because
+ * negative PID values are used to represent invalid PIDs.
+ */
-typedef int pid_t;
+typedef int16_t pid_t;
/* id_t is a general identifier that can be used to contain at least a pid_t,
* uid_t, or gid_t.
*/
-typedef unsigned int id_t;
+typedef int16_t id_t;
/* Signed integral type of the result of subtracting two pointers */
diff --git a/nuttx/include/sys/wait.h b/nuttx/include/sys/wait.h
index 6af1e971e..2476adef9 100644
--- a/nuttx/include/sys/wait.h
+++ b/nuttx/include/sys/wait.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/wait.h
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -66,7 +66,7 @@
#define WTERMSIG(s) (false) /* Return signal number that caused process to terminate */
/* The following symbolic constants are possible values for the options
- * argument to waitpi(1) (1) and/or waitid() (2),
+ * argument to waitpid() (1) and/or waitid() (2),
*/
#define WCONTINUED (1 << 0) /* Status for child that has been continued (1)(2) */
@@ -104,9 +104,9 @@ extern "C" {
#define EXTERN extern
#endif
-EXTERN pid_t wait(int *stat_loc);
-EXTERN int waitid(idtype_t idtype, id_t id, siginfo_t *siginfo, int options);
-EXTERN pid_t waitpid(pid_t pid, int *stat_loc, int options);
+EXTERN pid_t wait(FAR int *stat_loc);
+EXTERN int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options);
+EXTERN pid_t waitpid(pid_t pid, FAR int *stat_loc, int options);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/unistd.h b/nuttx/include/unistd.h
index 681ce9e63..46eb14cdd 100644
--- a/nuttx/include/unistd.h
+++ b/nuttx/include/unistd.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/unistd.h
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -129,6 +129,7 @@ EXTERN int optopt; /* unrecognized option character */
/* Task Control Interfaces */
+EXTERN pid_t vfork(void);
EXTERN pid_t getpid(void);
EXTERN void _exit(int status) noreturn_function;
EXTERN unsigned int sleep(unsigned int seconds);
@@ -159,6 +160,19 @@ EXTERN FAR char *getcwd(FAR char *buf, size_t size);
EXTERN int unlink(FAR const char *pathname);
EXTERN int rmdir(FAR const char *pathname);
+/* Execution of programs from files */
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+EXTERN int execl(FAR const char *path, ...);
+EXTERN int execv(FAR const char *path, FAR char *const argv[]);
+
+/* Non-standard functions to manage symbol tables */
+
+struct symtab_s; /* See include/nuttx/binfmt/symtab.h */
+EXTERN void exec_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols);
+EXTERN void exec_setsymtab(FAR const struct symtab_s *symtab, int nsymbols);
+#endif
+
/* Other */
EXTERN int getopt(int argc, FAR char *const argv[], FAR const char *optstring);
diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig
index bd470be7f..72a6a5346 100644
--- a/nuttx/libc/Kconfig
+++ b/nuttx/libc/Kconfig
@@ -3,6 +3,8 @@
# see misc/tools/kconfig-language.txt.
#
+comment "Standard C Library Options"
+
config STDIO_BUFFER_SIZE
int "C STDIO buffer size"
default 64
@@ -69,6 +71,67 @@ config EOL_IS_EITHER_CRLF
endchoice
+config LIBC_EXECFUNCS
+ bool "Enable exec[l|v] / posix_spawn() Support"
+ default n
+ depends on !BINFMT_DISABLE
+ ---help---
+ Enable support for the exec[l|v] family of functions that can be
+ used to start other programs, terminating the current program and
+ the posix_spawn() familty of functions that can be used start other
+ programs without terminating the current program. The typical
+ usage of the exec[l|v] functions is (1) first call vfork() to create
+ a new thread, then (2) call exec[l|v] to replace the new thread with
+ a program from the file system.
+
+ NOTE 1: This two step process start is completely unnecessary in
+ NuttX and is provided only for compatibily with Unix systems. These
+ functions are essentially just wrapper functions that (1) call the
+ non-standard binfmt function 'exec', and then (2) exit(0). Since
+ the new thread will be terminated by the exec[l|v] call, it really
+ served no purpose other than to suport Unix compatility.
+
+ The posix_spawn() functions do not have this inefficiency.
+
+ NOTE 2: Support for exec[l|v] and posix_spawn() is conditional
+ because they require additional support for symbol tables that
+ will not be available in the typical system.
+
+if LIBC_EXECFUNCS
+
+config EXECFUNCS_SYMTAB
+ string "Symbol table used by exec[l|v]"
+ default "g_symtab"
+ ---help---
+ The exec[l|v] and posix_spawn() functions are wrapper functions that
+ call the non-standard binfmt function 'exec'). The binfmt
+ function 'exec' needs to have (1) a symbol table that provides the
+ list of symbols exported by the base code, and (2) the number of
+ symbols in that table. This selection provides the name of that
+ symbol table.
+
+config EXECFUNCS_NSYMBOLS
+ int "Number of Symbols in the Table"
+ default 0
+ ---help---
+ The exec[l|v] and posix_spawn() functions are wrapper functions that
+ call the non-standard binfmt function 'exec'). The binfmt
+ function 'exec' needs to have (1) a symbol table that provides the
+ list of symbols exported by the base code, and (2) the number of
+ symbols in that table. This selection provides the number of
+ symbols in the symbol table.
+
+config POSIX_SPAWN_STACKSIZE
+ int "posix_spawn Stack Size"
+ default 1024
+ ---help---
+ If posix_spawn[p] uses I/O redirection options, then it will require
+ an intermediary/proxy task to muck with the file descriptors. This
+ configuration item specifies the stack size used for the proxy. Default:
+ 1024 bytes.
+
+endif
+
config LIBC_STRERROR
bool "Enable strerror"
default n
@@ -273,3 +336,29 @@ config ARCH_BZERO
of bzero().
endif
+
+comment "Non-standard Helper Functions"
+
+config LIB_KBDCODEC
+ bool "Keyboard CODEC"
+ default n
+ ---help---
+ In NuttX, a keyboard/keypad driver is simply a character driver that
+ may have an (optional) encoding/decoding layer on the data returned
+ by the character driver. A keyboard may return simple text data
+ (alphabetic, numeric, and punctuaction) or control characters
+ (enter, control-C, etc.). We can think about this the normal
+ "in-band" keyboard data stream. However, in addition, most
+ keyboards support actions that cannot be represented as text data.
+ Such actions include things like cursor controls (home, up arrow,
+ page down, etc.), editing functions (insert, delete, etc.), volume
+ controls, (mute, volume up, etc.) and other special functions. We
+ can think about this as special, "out-of-band" keyboard commands.
+ In this case, some special encoding may be required to multiplex
+ the in-band text data and out-of-band command streams.
+
+ This option enables the functions that implement the encoding and
+ decoding of keyboard data. These are the interfaces prototyped in
+ include/nuttx/input/kbd_codec.h. While not correctly a part of
+ the C library, it is included here because the decoding side of this
+ interface must be accessible by end user programs.
diff --git a/nuttx/libc/Makefile b/nuttx/libc/Makefile
index 22dbba1d9..a76620585 100644
--- a/nuttx/libc/Makefile
+++ b/nuttx/libc/Makefile
@@ -57,6 +57,7 @@ include time/Make.defs
include libgen/Make.defs
include dirent/Make.defs
include termios/Make.defs
+include spawn/Make.defs
include queue/Make.defs
include misc/Make.defs
diff --git a/nuttx/libc/lib_internal.h b/nuttx/libc/lib_internal.h
index c09c751d4..efe895465 100644
--- a/nuttx/libc/lib_internal.h
+++ b/nuttx/libc/lib_internal.h
@@ -140,6 +140,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj,
/* Defined lib_rawprintf.c */
int lib_rawvprintf(const char *src, va_list ap);
+int lib_rawvdprintf(int fd, const char *fmt, va_list ap);
/* Defined lib_lowprintf.c */
diff --git a/nuttx/libc/math/Kconfig b/nuttx/libc/math/Kconfig
index c24bfd53f..db9dfae63 100644
--- a/nuttx/libc/math/Kconfig
+++ b/nuttx/libc/math/Kconfig
@@ -4,7 +4,7 @@
#
config LIBM
- bool "Math library"
+ bool "Standard Math library"
default n
depends on !ARCH_MATH_H
---help---
diff --git a/nuttx/libc/misc/Make.defs b/nuttx/libc/misc/Make.defs
index f4284ac60..0d3c87d9d 100644
--- a/nuttx/libc/misc/Make.defs
+++ b/nuttx/libc/misc/Make.defs
@@ -63,6 +63,12 @@ CSRCS += lib_match.c
CSRCS += lib_crc32.c
CSRCS += lib_dbg.c lib_dumpbuffer.c
+# Keyboard driver encoder/decoder
+
+ifeq ($(CONFIG_LIB_KBDCODEC),y)
+CSRCS += lib_kbdencode.c lib_kbddecode.c
+endif
+
# Add the misc directory to the build
DEPPATH += --dep-path misc
diff --git a/nuttx/libc/misc/lib_filesem.c b/nuttx/libc/misc/lib_filesem.c
index 5cc4624ec..f38ff5f23 100644
--- a/nuttx/libc/misc/lib_filesem.c
+++ b/nuttx/libc/misc/lib_filesem.c
@@ -67,8 +67,8 @@
void lib_sem_initialize(FAR struct file_struct *stream)
{
- /* Initialize the LIB semaphore to one (to support one-at-
- * a-time access to private data sets.
+ /* Initialize the LIB semaphore to one (to support one-at-a-time access
+ * to private data sets.
*/
(void)sem_init(&stream->fs_sem, 0, 1);
@@ -98,13 +98,13 @@ void lib_take_semaphore(FAR struct file_struct *stream)
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&stream->fs_sem) != 0)
- {
- /* The only case that an error should occr here is if
- * the wait was awakened by a signal.
- */
+ {
+ /* The only case that an error should occr here is if the wait
+ * was awakened by a signal.
+ */
- ASSERT(get_errno() == EINTR);
- }
+ ASSERT(get_errno() == EINTR);
+ }
/* We have it. Claim the stak and return */
diff --git a/nuttx/libc/misc/lib_kbddecode.c b/nuttx/libc/misc/lib_kbddecode.c
new file mode 100644
index 000000000..62554902c
--- /dev/null
+++ b/nuttx/libc/misc/lib_kbddecode.c
@@ -0,0 +1,267 @@
+/****************************************************************************
+ * libc/msic/lib_kbddecode.c
+ * Decoding side of the Keyboard CODEC
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/input/kbd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define NDX_ESC 0
+#define NDX_BRACKET 1
+#define NDX_CODE 2
+#define NDX_TERMINATOR 3
+
+#define NCH_ESC 1
+#define NCH_BRACKET 2
+#define NCH_CODE 3
+#define NCH_TERMINATOR 4
+
+#define TERM_MIN ('a' + KBD_RELEASE)
+#define TERM_MAX ('a' + KBD_SPECREL)
+#define TERM_RETURN(a) ((a) - 'a')
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_reget
+ *
+ * Description:
+ * We have unused characters from the last, unsuccessful. Return one of
+ * these instead of the .
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location character to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ *
+ * Returned Value:
+ * KBD_PRESS - Indicates the successful receipt of norma keyboard data.
+ *
+ ****************************************************************************/
+
+static int kbd_reget(FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
+{
+ /* Return the next character */
+
+ *pch = state->buf[state->ndx];
+ state->ndx++;
+ state->nch--;
+ return KBD_PRESS;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the driver provided input
+ * buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that kbd_decode is called.
+ *
+ * Returned Value:
+ *
+ * KBD_PRESS - Indicates the successful receipt of normal, keyboard data.
+ * This corresponds to a keypress event. The returned value in pch is a
+ * simple byte of text or control data corresponding to the pressed key.
+ * KBD_RELEASE - Indicates a key release event. The returned value in pch
+ * is the byte of text or control data corresponding to the released key.
+ * KBD_SPECPRESS - Indicates the successful receipt of a special keyboard
+ * command. The returned value in pch is a value from enum kbd_getstate_s.
+ * KBD_SPECREL - Indicates a special key release event. The returned value
+ * in pch is a value from enum kbd_getstate_s.
+ * EOF - An error has getting the next character (reported by the stream).
+ * Normally indicates the end of file.
+ *
+ ****************************************************************************/
+
+int kbd_decode(FAR struct lib_instream_s *stream,
+ FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
+{
+ int ch;
+
+ DEBUGASSERT(stream && state && pch);
+
+ /* Are their ungotten characters from the last, failed parse? */
+
+ if (state->nch > 0)
+ {
+ /* Yes, return the next ungotten character */
+
+ return kbd_reget(state, pch);
+ }
+
+ state->ndx = 0;
+
+ /* No, ungotten characters. Check for the beginning of an ESC sequence. */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream */
+
+ return KBD_ERROR;
+ }
+ else
+ {
+ state->buf[NDX_ESC] = (uint8_t)ch;
+ state->nch = NCH_ESC;
+
+ if (ch != ASCII_ESC)
+ {
+ /* Not the beginning of an escape sequence. Return the character. */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Check for ESC-[ */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the escape character now. We will
+ * return the EOF indication next time.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_BRACKET] = ch;
+ state->nch = NCH_BRACKET;
+
+ if (ch != '[')
+ {
+ /* Not the beginning of an escape sequence. Return the ESC now,
+ * return the following character later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Get and verify the special keyboard data to decode */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Unget everything and return the ESC character.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_CODE] = (uint8_t)ch;
+ state->nch = NCH_CODE;
+
+ /* Check for a valid special command code */
+
+ if (ch < FIRST_KEYCODE || ch > LAST_KEYCODE)
+ {
+ /* Not a special command code, return the ESC now and the next two
+ * characters later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Check for the final semicolon */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Unget everything and return the ESC character.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_TERMINATOR] = (uint8_t)ch;
+ state->nch = NCH_TERMINATOR;
+
+ /* Check for a valid special command code */
+
+ if (ch < TERM_MIN || ch > TERM_MAX)
+ {
+ /* Not a special command code, return the ESC now and the next two
+ * characters later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* We have successfully parsed the the entire escape sequence. Return the
+ * keyboard value in pch and the value an indication determined by the
+ * terminating character.
+ */
+
+ *pch = state->buf[NDX_CODE];
+ state->nch = 0;
+ return TERM_RETURN(state->buf[NDX_TERMINATOR]);
+}
+
diff --git a/nuttx/libc/misc/lib_kbdencode.c b/nuttx/libc/misc/lib_kbdencode.c
new file mode 100644
index 000000000..80138ca80
--- /dev/null
+++ b/nuttx/libc/misc/lib_kbdencode.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * libc/msic/lib_kbdencode.c
+ * Encoding side of the Keyboard CODEC
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/input/kbd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_encode
+ *
+ * Description:
+ * Encode one special special sequence command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ * terminator - Escape sequence terminating character.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void kbd_encode(uint8_t keycode, FAR struct lib_outstream_s *stream,
+ uint8_t terminator)
+{
+ stream->put(stream, ASCII_ESC);
+ stream->put(stream, '[');
+ stream->put(stream, (int)keycode);
+ stream->put(stream, terminator);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_release
+ *
+ * Description:
+ * Encode the release of a normal key.
+ *
+ * Input Parameters:
+ * ch - The character associated with the key that was releared.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_release(uint8_t ch, FAR struct lib_outstream_s *stream)
+{
+ kbd_encode(ch, stream, ('a' + KBD_RELEASE));
+}
+
+/****************************************************************************
+ * Name: kbd_specpress
+ *
+ * Description:
+ * Denotes a special key press event. Put one special keyboard command
+ * into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specpress(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream)
+{
+ DEBUGASSERT(stream && keycode >= KEYCODE_FWDDEL && keycode <= LAST_KEYCODE);
+ kbd_encode((uint8_t)keycode, stream, ('a' + KBD_SPECPRESS));
+}
+
+/****************************************************************************
+ * Name: kbd_specrel
+ *
+ * Description:
+ * Denotes a special key release event. Put one special keyboard
+ * command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specrel(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream)
+{
+ DEBUGASSERT(stream && keycode >= KEYCODE_FWDDEL && keycode <= LAST_KEYCODE);
+ kbd_encode((uint8_t)keycode, stream, ('a' + KBD_SPECREL));
+}
diff --git a/nuttx/libc/misc/lib_streamsem.c b/nuttx/libc/misc/lib_streamsem.c
index e38298bdb..3397f9907 100644
--- a/nuttx/libc/misc/lib_streamsem.c
+++ b/nuttx/libc/misc/lib_streamsem.c
@@ -86,5 +86,3 @@ void stream_semgive(FAR struct streamlist *list)
{
sem_post(&list->sl_sem);
}
-
-
diff --git a/nuttx/libc/spawn/Make.defs b/nuttx/libc/spawn/Make.defs
new file mode 100644
index 000000000..8cb086fee
--- /dev/null
+++ b/nuttx/libc/spawn/Make.defs
@@ -0,0 +1,63 @@
+############################################################################
+# libc/spawn/Make.defs
+#
+# Copyright (C) 2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+# Add the spawn C files to the build
+
+ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
+
+CSRCS += lib_psfa_addaction.c lib_psfa_addclose.c lib_psfa_adddup2.c
+CSRCS += lib_psfa_addopen.c lib_psfa_destroy.c lib_psfa_init.c
+
+ifeq ($(CONFIG_DEBUG),y)
+CSRCS += lib_psfa_dump.c
+endif
+
+CSRCS += lib_psa_getflags.c lib_psa_getschedparam.c lib_psa_getschedpolicy.c
+CSRCS += lib_psa_init.c lib_psa_setflags.c lib_psa_setschedparam.c
+CSRCS += lib_psa_setschedpolicy.c
+
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+CSRCS += lib_psa_getsigmask.c lib_psa_setsigmask.c
+endif
+
+ifeq ($(CONFIG_DEBUG),y)
+CSRCS += lib_psa_dump.c
+endif
+
+# Add the spawn directory to the build
+
+DEPPATH += --dep-path spawn
+VPATH += :spawn
+endif
diff --git a/nuttx/libc/spawn/lib_psa_dump.c b/nuttx/libc/spawn/lib_psa_dump.c
new file mode 100644
index 000000000..03770c6ff
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_dump.c
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * libc/string/lib_psa_dump.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <debug.h>
+
+#ifdef CONFIG_DEBUG
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_dump
+ *
+ * Description:
+ * Show the current attributes.
+ *
+ * Input Parameters:
+ * attr - The address of the spawn attributes to be dumped.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void posix_spawnattr_dump(posix_spawnattr_t *attr)
+{
+ dbg("attr[%p]:\n", attr);
+ dbg(" flags: %04x\n", attr->flags);
+ if (attr->flags == 0)
+ {
+ dbg(" None\n");
+ }
+ else
+ {
+ if ((attr->flags & POSIX_SPAWN_RESETIDS) != 0)
+ {
+ dbg(" POSIX_SPAWN_RESETIDS\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETPGROUP) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETPGROUP\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSCHEDPARAM\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSCHEDULER\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSIGDEF) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSIGDEF\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSIGMASK\n");
+ }
+ }
+
+ dbg(" priority: %d\n", attr->priority);
+
+ dbg(" policy: %d\n", attr->policy);
+ if (attr->policy == SCHED_FIFO)
+ {
+ dbg(" SCHED_FIFO\n");
+ }
+ else if (attr->policy == SCHED_RR)
+ {
+ dbg(" SCHED_RR\n");
+ }
+ else
+ {
+ dbg(" Unrecognized\n");
+ }
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ dbg(" sigmask: %08x\n", attr->sigmask);
+#endif
+};
+
+#endif /* CONFIG_DEBUG */ \ No newline at end of file
diff --git a/nuttx/libc/spawn/lib_psa_getflags.c b/nuttx/libc/spawn/lib_psa_getflags.c
new file mode 100644
index 000000000..f0e07f0c2
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getflags.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libc/string/lib_psa_getflags.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getflags
+ *
+ * Description:
+ * The posix_spawnattr_getflags() function will obtain the value of the
+ * spawn-flags attribute from the attributes object referenced by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * flags - The location to return the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getflags(FAR const posix_spawnattr_t *attr,
+ FAR short *flags)
+{
+ DEBUGASSERT(attr && flags);
+ *flags = (short)attr->flags;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getschedparam.c b/nuttx/libc/spawn/lib_psa_getschedparam.c
new file mode 100644
index 000000000..ed8cb1f70
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getschedparam.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * libc/string/lib_psa_getschedparam.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getschedparam
+ *
+ * Description:
+ * The posix_spawnattr_getschedparam() function will obtain the value of
+ * the spawn-schedparam attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * flags - The location to return the spawn-schedparam value.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getschedparam(FAR const posix_spawnattr_t *attr,
+ FAR struct sched_param *param)
+{
+ DEBUGASSERT(attr && param);
+ param->sched_priority = attr->priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getschedpolicy.c b/nuttx/libc/spawn/lib_psa_getschedpolicy.c
new file mode 100644
index 000000000..8f3645666
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getschedpolicy.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+ * libc/string/lib_psa_getschedpolicy.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getschedpolicy
+ *
+ * Description:
+ * The posix_spawnattr_getschedpolicy() function shall obtain the value
+ * of the spawn-schedpolicy attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * policy - The location to return the scheduler policy
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getschedpolicy(FAR const posix_spawnattr_t *attr,
+ FAR int *policy)
+{
+ DEBUGASSERT(attr && policy);
+ *policy = (int)attr->policy;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getsigmask.c b/nuttx/libc/spawn/lib_psa_getsigmask.c
new file mode 100644
index 000000000..dd3495b4d
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getsigmask.c
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * libc/string/lib_psa_getsigmask.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <signal.h>
+#include <spawn.h>
+#include <assert.h>
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getsigmask
+ *
+ * Description:
+ * The posix_spawnattr_getsigdefault() function will obtain the value of
+ * the spawn-sigmask attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * sigmask - The location to return the signal mask
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getsigmask(FAR const posix_spawnattr_t *attr,
+ FAR sigset_t *sigmask)
+{
+ DEBUGASSERT(attr && sigmask);
+ *sigmask = attr->sigmask;
+ return OK;
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/libc/spawn/lib_psa_init.c b/nuttx/libc/spawn/lib_psa_init.c
new file mode 100644
index 000000000..f76188c52
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_init.c
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * libc/string/lib_psa_init.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_init
+ *
+ * Description:
+ * The posix_spawnattr_init() function initializes the object referenced
+ * by attr, to an empty set of spawn attributes for subsequent use in a
+ * call to posix_spawn() or posix_spawnp().
+ *
+ * Input Parameters:
+ * attr - The address of the spawn attributes to be initialized.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_init(posix_spawnattr_t *attr)
+{
+ struct sched_param param;
+ int ret;
+
+ DEBUGASSERT(attr);
+
+ /* Flags: None */
+
+ attr->flags = 0;
+
+ /* Set the default scheduler policy to the policy of this task */
+
+ attr->policy = sched_getscheduler(0);
+
+ /* Set the default priority to the same priority as this task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ return errno;
+ }
+
+ attr->priority = param.sched_priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setflags.c b/nuttx/libc/spawn/lib_psa_setflags.c
new file mode 100644
index 000000000..34b71d841
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setflags.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * libc/string/lib_psa_setflags.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setflags
+ *
+ * Description:
+ * The posix_spawnattr_setflags() function will set the spawn-flags
+ * attribute in an initialized attributes object referenced by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setflags(FAR posix_spawnattr_t *attr, short flags)
+{
+ DEBUGASSERT(attr && (flags & ~0xff) == 0);
+ attr->flags = (uint8_t)flags;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setschedparam.c b/nuttx/libc/spawn/lib_psa_setschedparam.c
new file mode 100644
index 000000000..5e992e8a9
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setschedparam.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * libc/string/lib_psa_setschedparam.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setschedparam
+ *
+ * Description:
+ * The posix_spawnattr_setschedparam() function shall set the spawn-
+ * schedparam attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * param - The new sched_priority to set.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setschedparam(FAR posix_spawnattr_t *attr,
+ FAR const struct sched_param *param)
+{
+ DEBUGASSERT(attr && param && (unsigned)param->sched_priority <= 0xff);
+ attr->priority = (uint8_t)param->sched_priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setschedpolicy.c b/nuttx/libc/spawn/lib_psa_setschedpolicy.c
new file mode 100644
index 000000000..136a6f0fd
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setschedpolicy.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libc/string/lib_psa_setschedpolicy.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setschedpolicy
+ *
+ * Description:
+ * The posix_spawnattr_setschedpolicy() function will set the spawn-
+ * schedpolicy attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setschedpolicy(FAR posix_spawnattr_t *attr, int policy)
+{
+ DEBUGASSERT(attr && (policy == SCHED_FIFO || policy == SCHED_RR));
+ attr->policy = (uint8_t)policy;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setsigmask.c b/nuttx/libc/spawn/lib_psa_setsigmask.c
new file mode 100644
index 000000000..28b7daf77
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setsigmask.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * libc/string/lib_psa_setsigmask.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <signal.h>
+#include <spawn.h>
+#include <assert.h>
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setsigmask
+ *
+ * Description:
+ * The posix_spawnattr_setsigmask() function will set the spawn-
+ * sigmask attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the default signal set
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr,
+ FAR const sigset_t *sigmask)
+{
+ DEBUGASSERT(attr && sigmask);
+ attr->sigmask = *sigmask;
+ return OK;
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
+
diff --git a/nuttx/libc/spawn/lib_psfa_addaction.c b/nuttx/libc/spawn/lib_psfa_addaction.c
new file mode 100644
index 000000000..8700efc2a
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addaction.c
@@ -0,0 +1,91 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addaction.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+
+#include <nuttx/spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: add_file_action
+ *
+ * Description:
+ * Add the file action to the end for the file action list.
+ *
+ * Input Parameters:
+ * file_actions - The head of the file action list.
+ * entry - The file action to be added
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void add_file_action(FAR posix_spawn_file_actions_t *file_actions,
+ FAR struct spawn_general_file_action_s *entry)
+{
+ FAR struct spawn_general_file_action_s *prev;
+ FAR struct spawn_general_file_action_s *next;
+
+ /* Find the end of the list */
+
+ for (prev = NULL, next = (FAR struct spawn_general_file_action_s *)*file_actions;
+ next;
+ prev = next, next = next->flink);
+
+ /* Here next is NULL and prev points to the last entry in the list (or
+ * is NULL if the list is empty).
+ */
+
+ if (prev)
+ {
+ prev->flink = entry;
+ }
+ else
+ {
+ *file_actions = (posix_spawn_file_actions_t)entry;
+ }
+
+ entry->flink = NULL;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_addclose.c b/nuttx/libc/spawn/lib_psfa_addclose.c
new file mode 100644
index 000000000..1c72f0f82
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addclose.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addclose.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_addclose
+ *
+ * Description:
+ * The posix_spawn_file_actions_addclose() function adds a close operation
+ * to the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd is closed as if
+ * close() had been called on it prior to the new child process starting
+ * execution.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd - The file descriptor to be closed.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actions,
+ int fd)
+{
+ FAR struct spawn_close_file_action_s *entry;
+
+ DEBUGASSERT(file_actions && fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Allocate the action list entry */
+
+ entry = (FAR struct spawn_close_file_action_s *)
+ zalloc(sizeof(struct spawn_close_file_action_s));
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_CLOSE;
+ entry->fd = fd;
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_adddup2.c b/nuttx/libc/spawn/lib_psfa_adddup2.c
new file mode 100644
index 000000000..deb3cbdb3
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_adddup2.c
@@ -0,0 +1,104 @@
+/****************************************************************************
+ * libc/string/lib_psfa_adddup2.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_adddup2
+ *
+ * Description:
+ * The posix_spawn_file_actions_adddup2() function adds a dup2 operation to
+ * the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd2 is created as
+ * if dup2() had been called on fd1 prior to the new child process
+ * starting execution.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd1 - The first file descriptor to be argument to dup2.
+ * fd2 - The first file descriptor to be argument to dup2.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_actions,
+ int fd1, int fd2)
+{
+ FAR struct spawn_dup2_file_action_s *entry;
+
+ DEBUGASSERT(file_actions &&
+ fd1 >= 0 && fd1 < CONFIG_NFILE_DESCRIPTORS &&
+ fd2 >= 0 && fd2 < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Allocate the action list entry */
+
+ entry = (FAR struct spawn_dup2_file_action_s *)
+ zalloc(sizeof(struct spawn_close_file_action_s));
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_DUP2;
+ entry->fd1 = fd1;
+ entry->fd2 = fd2;
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_addopen.c b/nuttx/libc/spawn/lib_psfa_addopen.c
new file mode 100644
index 000000000..66bbd813a
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addopen.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addopen.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_addopen
+ *
+ * Description:
+ * The posix_spawn_file_actions_addopen() function adds an open operation
+ * to the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd is opened using
+ * the path, oflag, and mode arguments as if open() had been called on it
+ * prior to the new child process starting execution. The string path is
+ * copied by the posix_spawn_file_actions_addopen() function during this
+ * process, so storage need not be persistent in the caller.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd - The file descriptor to be opened.
+ * path - The path to be opened.
+ * oflags - Open flags
+ * mode - File creation mode
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions,
+ int fd, FAR const char *path, int oflags,
+ mode_t mode)
+{
+ FAR struct spawn_open_file_action_s *entry;
+ size_t len;
+ size_t alloc;
+
+ DEBUGASSERT(file_actions && path &&
+ fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Get the size of the action including storage for the path plus its NUL
+ * terminating character.
+ */
+
+ len = strlen(path);
+ alloc = SIZEOF_OPEN_FILE_ACTION_S(len);
+
+ /* Allocate the action list entry of this size */
+
+ entry = (FAR struct spawn_open_file_action_s *)zalloc(alloc);
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_OPEN;
+ entry->fd = fd;
+ entry->oflags = oflags;
+ entry->mode = mode;
+ strncpy(entry->path, path, len+1);
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_destroy.c b/nuttx/libc/spawn/lib_psfa_destroy.c
new file mode 100644
index 000000000..a21886645
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_destroy.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * libc/string/lib_psfa_destroy.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+
+#include <nuttx/spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_destroy
+ *
+ * Description:
+ * The posix_spawn_file_actions_destroy() function destroys the object
+ * referenced by file_actions which was previously intialized by
+ * posix_spawn_file_actions_init(), returning any resources obtained at the
+ * time of initialization to the system for subsequent reuse. A
+ * posix_spawn_file_actions_t may be reinitialized after having been
+ * destroyed, but must not be reused after destruction, unless it has been
+ * reinitialized.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to be destroyed.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_destroy(FAR posix_spawn_file_actions_t *file_actions)
+{
+ FAR struct spawn_general_file_action_s *curr;
+ FAR struct spawn_general_file_action_s *next;
+
+ DEBUGASSERT(file_actions);
+
+ /* Destroy each file action, one at a time */
+
+ for (curr = (FAR struct spawn_general_file_action_s *)*file_actions;
+ curr;
+ curr = next)
+ {
+ /* Get the pointer to the next element before destroying the current one */
+
+ next = curr->flink;
+ free(curr);
+ }
+
+ /* Mark the list empty */
+
+ *file_actions = NULL;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_dump.c b/nuttx/libc/spawn/lib_psfa_dump.c
new file mode 100644
index 000000000..0dbaeb023
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_dump.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * libc/string/lib_psfa_dump.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/spawn.h>
+
+#ifdef CONFIG_DEBUG
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_psfa_dump
+ *
+ * Description:
+ * Show the entryent file actions.
+ *
+ * Input Parameters:
+ * file_actions - The address of the file_actions to be dumped.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions)
+{
+ FAR struct spawn_general_file_action_s *entry;
+
+ DEBUGASSERT(file_actions);
+
+ dbg("File Actions[%p->%p]:\n", file_actions, *file_actions);
+ if (!*file_actions)
+ {
+ dbg(" NONE\n");
+ return;
+ }
+
+ /* Destroy each file action, one at a time */
+
+ for (entry = (FAR struct spawn_general_file_action_s *)*file_actions;
+ entry;
+ entry = entry->flink)
+ {
+ switch (entry->action)
+ {
+ case SPAWN_FILE_ACTION_CLOSE:
+ {
+ FAR struct spawn_close_file_action_s *action =
+ (FAR struct spawn_close_file_action_s *)entry;
+
+ dbg(" CLOSE: fd=%d\n", action->fd);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_DUP2:
+ {
+ FAR struct spawn_dup2_file_action_s *action =
+ (FAR struct spawn_dup2_file_action_s *)entry;
+
+ dbg(" DUP2: %d->%d\n", action->fd1, action->fd2);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_OPEN:
+ {
+ FAR struct spawn_open_file_action_s *action =
+ (FAR struct spawn_open_file_action_s *)entry;
+
+ svdbg(" OPEN: path=%s oflags=%04x mode=%04x fd=%d\n",
+ action->path, action->oflags, action->mode, action->fd);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_NONE:
+ default:
+ dbg(" ERROR: Unknown action: %d\n", entry->action);
+ break;
+ }
+ }
+}
+
+#endif /* CONFIG_DEBUG */ \ No newline at end of file
diff --git a/nuttx/libc/spawn/lib_psfa_init.c b/nuttx/libc/spawn/lib_psfa_init.c
new file mode 100644
index 000000000..5c902125a
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_init.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * libc/string/lib_psfa_init.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_init
+ *
+ * Description:
+ * The posix_spawn_file_actions_init() function initializes the object
+ * referenced by file_actions to an empty set of file actions for
+ * subsequent use in a call to posix_spawn() or posix_spawnp().
+ *
+ * Input Parameters:
+ * file_actions - The address of the posix_spawn_file_actions_t to be
+ * initialized.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions)
+{
+ *file_actions = NULL;
+ return OK;
+}
diff --git a/nuttx/libc/stdio/Make.defs b/nuttx/libc/stdio/Make.defs
index e18ab0220..0670724da 100644
--- a/nuttx/libc/stdio/Make.defs
+++ b/nuttx/libc/stdio/Make.defs
@@ -59,7 +59,7 @@ CSRCS += lib_fopen.c lib_fclose.c lib_fread.c lib_libfread.c lib_fseek.c \
lib_gets.c lib_fwrite.c lib_libfwrite.c lib_fflush.c \
lib_libflushall.c lib_libfflush.c lib_rdflush.c lib_wrflush.c \
lib_fputc.c lib_puts.c lib_fputs.c lib_ungetc.c lib_vprintf.c \
- lib_fprintf.c lib_vfprintf.c lib_stdinstream.c lib_stdoutstream.c \
+ lib_fprintf.c lib_vfprintf.c lib_vdprintf.c lib_stdinstream.c lib_stdoutstream.c \
lib_perror.c lib_feof.c lib_ferror.c lib_clearerr.c
endif
diff --git a/nuttx/libc/stdio/lib_libfread.c b/nuttx/libc/stdio/lib_libfread.c
index bc6479037..3e851bf17 100644
--- a/nuttx/libc/stdio/lib_libfread.c
+++ b/nuttx/libc/stdio/lib_libfread.c
@@ -301,9 +301,10 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream)
{
stream->fs_flags |= __FS_FLAG_EOF;
}
+
+ lib_give_semaphore(stream);
}
- lib_give_semaphore(stream);
return bytes_read;
/* Error exits */
diff --git a/nuttx/libc/stdio/lib_rawprintf.c b/nuttx/libc/stdio/lib_rawprintf.c
index 98bbbea05..ddbb84f94 100644
--- a/nuttx/libc/stdio/lib_rawprintf.c
+++ b/nuttx/libc/stdio/lib_rawprintf.c
@@ -149,3 +149,18 @@ int lib_rawprintf(const char *fmt, ...)
return ret;
}
+
+
+/****************************************************************************
+ * Name: lib_rawvdprintf
+ ****************************************************************************/
+
+int lib_rawvdprintf(int fd, const char *fmt, va_list ap)
+{
+ /* Wrap the fd in a stream object and let lib_vsprintf
+ * do the work.
+ */
+ struct lib_rawoutstream_s rawoutstream;
+ lib_rawoutstream(&rawoutstream, fd);
+ return lib_vsprintf(&rawoutstream.public, fmt, ap);
+}
diff --git a/nuttx/libc/stdio/lib_vdprintf.c b/nuttx/libc/stdio/lib_vdprintf.c
new file mode 100644
index 000000000..932342e1c
--- /dev/null
+++ b/nuttx/libc/stdio/lib_vdprintf.c
@@ -0,0 +1,81 @@
+/****************************************************************************
+ * libc/stdio/lib_vdprintf.c
+ *
+ * Copyright (C) 2007-2009, 2011 Andrew Tridgell. All rights reserved.
+ * Author: Andrew Tridgell <andrew@tridgell.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+
+#include "lib_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int vdprintf(int fd, FAR const char *fmt, va_list ap)
+{
+ return lib_rawvdprintf(fd, fmt, ap);
+}
diff --git a/nuttx/libc/string/lib_strndup.c b/nuttx/libc/string/lib_strndup.c
index 524e09754..5a78e2dcf 100644
--- a/nuttx/libc/string/lib_strndup.c
+++ b/nuttx/libc/string/lib_strndup.c
@@ -1,7 +1,7 @@
/************************************************************************
* libc/string//lib_strndup.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -68,13 +68,9 @@ FAR char *strndup(FAR const char *s, size_t size)
FAR char *news = NULL;
if (s)
{
- /* Get the size of the new string = MIN(strlen(s), size) */
+ /* Get the size of the new string (limited to size) */
- size_t allocsize = strlen(s);
- if (allocsize > size)
- {
- allocsize = size;
- }
+ size_t allocsize = strnlen(s, size);
/* Allocate the new string, adding 1 for the NUL terminator */
@@ -89,5 +85,6 @@ FAR char *strndup(FAR const char *s, size_t size)
news[allocsize] = '\0';
}
}
+
return news;
}
diff --git a/nuttx/libc/unistd/Make.defs b/nuttx/libc/unistd/Make.defs
index 67fce9b1d..ee3ac0fc9 100644
--- a/nuttx/libc/unistd/Make.defs
+++ b/nuttx/libc/unistd/Make.defs
@@ -41,6 +41,10 @@ ifneq ($(CONFIG_NFILE_DESCRIPTORS),0)
ifneq ($(CONFIG_DISABLE_ENVIRON),y)
CSRCS += lib_chdir.c lib_getcwd.c
endif
+
+ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
+CSRCS += lib_execl.c lib_execv.c lib_execsymtab.c
+endif
endif
# Add the unistd directory to the build
diff --git a/nuttx/libc/unistd/lib_execl.c b/nuttx/libc/unistd/lib_execl.c
new file mode 100644
index 000000000..fa50c1429
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execl.c
@@ -0,0 +1,146 @@
+/****************************************************************************
+ * libc/unistd/lib_execl.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: execl
+ *
+ * Description:
+ * The standard 'exec' family of functions will replace the current process
+ * image with a new process image. The new image will be constructed from a
+ * regular, executable file called the new process image file. There will
+ * be no return from a successful exec, because the calling process image
+ * is overlaid by the new process image.
+ *
+ * Simplified 'execl()' and 'execv()' functions are provided by NuttX for
+ * compatibility. NuttX is a tiny embedded RTOS that does not support
+ * processes and hence the concept of overlaying a tasks process image with
+ * a new process image does not make any sense. In NuttX, these functions
+ * are wrapper functions that:
+ *
+ * 1. Call the non-standard binfmt function 'exec', and then
+ * 2. exit(0).
+ *
+ * Note the inefficiency when 'exec[l|v]()' is called in the normal, two-
+ * step process: (1) first call vfork() to create a new thread, then (2)
+ * call 'exec[l|v]()' to replace the new thread with a program from the
+ * file system. Since the new thread will be terminated by the
+ * 'exec[l|v]()' call, it really served no purpose other than to support
+ * Unix compatility.
+ *
+ * The non-standard binfmt function 'exec()' needs to have (1) a symbol
+ * table that provides the list of symbols exported by the base code, and
+ * (2) the number of symbols in that table. This information is currently
+ * provided to 'exec()' from 'exec[l|v]()' via NuttX configuration settings:
+ *
+ * CONFIG_LIBC_EXECFUNCS : Enable exec[l|v] support
+ * CONFIG_EXECFUNCS_SYMTAB : Symbol table used by exec[l|v]
+ * CONFIG_EXECFUNCS_NSYMBOLS : Number of symbols in the table
+ *
+ * As a result of the above, the current implementations of 'execl()' and
+ * 'execv()' suffer from some incompatibilities that may or may not be
+ * addressed in a future version of NuttX. Other than just being an
+ * inefficient use of MCU resource, the most serious of these is that
+ * the exec'ed task will not have the same task ID as the vfork'ed
+ * function. So the parent function cannot know the ID of the exec'ed
+ * task.
+ *
+ * Input Parameters:
+ * path - The path to the program to be executed. If CONFIG_BINFMT_EXEPATH
+ * is defined in the configuration, then this may be a relative path
+ * from the current working directory. Otherwise, path must be the
+ * absolute path to the program.
+ * ... - A list of the string arguments to be recevied by the
+ * program. Zero indicates the end of the list.
+ *
+ * Returned Value:
+ * This function does not return on success. On failure, it will return
+ * -1 (ERROR) and will set the 'errno' value appropriately.
+ *
+ ****************************************************************************/
+
+int execl(FAR const char *path, ...)
+{
+ FAR char *argv[CONFIG_MAX_TASK_ARGS+1];
+ va_list ap;
+ int argc;
+
+ /* Collect the arguments into the argv[] array */
+
+ va_start(ap, path);
+ for (argc = 0; argc < CONFIG_MAX_TASK_ARGS; argc++)
+ {
+ argv[argc] = va_arg(ap, FAR char *);
+ if (argv[argc] == NULL)
+ {
+ break;
+ }
+ }
+
+ argv[CONFIG_MAX_TASK_ARGS] = NULL;
+ va_end(ap);
+
+ /* Then let execv() do the real work */
+
+ return execv(path, (char * const *)&argv);
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */ \ No newline at end of file
diff --git a/nuttx/libc/unistd/lib_execsymtab.c b/nuttx/libc/unistd/lib_execsymtab.c
new file mode 100644
index 000000000..34b798bb4
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execsymtab.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * libc/unistd/lib_execsymtab.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/binfmt/symtab.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* If CONFIG_LIBC_EXECFUNCS is defined in the configuration, then the
+ * following must also be defined:
+ */
+
+/* Symbol table used by exec[l|v] */
+
+#ifndef CONFIG_EXECFUNCS_SYMTAB
+# error "CONFIG_EXECFUNCS_SYMTAB must be defined"
+#endif
+
+/* Number of Symbols in the Table */
+
+#ifndef CONFIG_EXECFUNCS_NSYMBOLS
+# error "CONFIG_EXECFUNCS_NSYMBOLS must be defined"
+#endif
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+extern const struct symtab_s CONFIG_EXECFUNCS_SYMTAB;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static FAR const struct symtab_s *g_exec_symtab = &CONFIG_EXECFUNCS_SYMTAB;
+static int g_exec_nsymbols = CONFIG_EXECFUNCS_NSYMBOLS;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_getsymtab
+ *
+ * Description:
+ * Get the current symbol table selection as an atomic operation.
+ *
+ * Input Parameters:
+ * symtab - The location to store the symbol table.
+ * nsymbols - The location to store the number of symbols in the symbol table.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void exec_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols)
+{
+ irqstate_t flags;
+
+ DEBUGASSERT(symtab && nsymbols);
+
+ /* Disable interrupts very briefly so that both the symbol table and its
+ * size are returned as a single atomic operation.
+ */
+
+ flags = irqsave();
+ *symtab = g_exec_symtab;
+ *nsymbols = g_exec_nsymbols;
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: exec_setsymtab
+ *
+ * Description:
+ * Select a new symbol table selection as an atomic operation.
+ *
+ * Input Parameters:
+ * symtab - The new symbol table.
+ * nsymbols - The number of symbols in the symbol table.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void exec_setsymtab(FAR const struct symtab_s *symtab, int nsymbols)
+{
+ irqstate_t flags;
+
+ DEBUGASSERT(symtab);
+
+ /* Disable interrupts very briefly so that both the symbol table and its
+ * size are set as a single atomic operation.
+ */
+
+ flags = irqsave();
+ g_exec_symtab = symtab;
+ g_exec_nsymbols = nsymbols;
+ irqrestore(flags);
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */ \ No newline at end of file
diff --git a/nuttx/libc/unistd/lib_execv.c b/nuttx/libc/unistd/lib_execv.c
new file mode 100644
index 000000000..48b089913
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execv.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * libc/unistd/lib_execv.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/binfmt.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: execv
+ *
+ * Description:
+ * The standard 'exec' family of functions will replace the current process
+ * image with a new process image. The new image will be constructed from a
+ * regular, executable file called the new process image file. There will
+ * be no return from a successful exec, because the calling process image
+ * is overlaid by the new process image.
+ *
+ * Simplified 'execl()' and 'execv()' functions are provided by NuttX for
+ * compatibility. NuttX is a tiny embedded RTOS that does not support
+ * processes and hence the concept of overlaying a tasks process image with
+ * a new process image does not make any sense. In NuttX, these functions
+ * are wrapper functions that:
+ *
+ * 1. Call the non-standard binfmt function 'exec', and then
+ * 2. exit(0).
+ *
+ * Note the inefficiency when 'exec[l|v]()' is called in the normal, two-
+ * step process: (1) first call vfork() to create a new thread, then (2)
+ * call 'exec[l|v]()' to replace the new thread with a program from the
+ * file system. Since the new thread will be terminated by the
+ * 'exec[l|v]()' call, it really served no purpose other than to support
+ * Unix compatility.
+ *
+ * The non-standard binfmt function 'exec()' needs to have (1) a symbol
+ * table that provides the list of symbols exported by the base code, and
+ * (2) the number of symbols in that table. This information is currently
+ * provided to 'exec()' from 'exec[l|v]()' via NuttX configuration settings:
+ *
+ * CONFIG_LIBC_EXECFUNCS : Enable exec[l|v] support
+ * CONFIG_EXECFUNCS_SYMTAB : Symbol table used by exec[l|v]
+ * CONFIG_EXECFUNCS_NSYMBOLS : Number of symbols in the table
+ *
+ * As a result of the above, the current implementations of 'execl()' and
+ * 'execv()' suffer from some incompatibilities that may or may not be
+ * addressed in a future version of NuttX. Other than just being an
+ * inefficient use of MCU resource, the most serious of these is that
+ * the exec'ed task will not have the same task ID as the vfork'ed
+ * function. So the parent function cannot know the ID of the exec'ed
+ * task.
+ *
+ * Input Parameters:
+ * path - The path to the program to be executed. If CONFIG_BINFMT_EXEPATH
+ * is defined in the configuration, then this may be a relative path
+ * from the current working directory. Otherwise, path must be the
+ * absolute path to the program.
+ * argv - A pointer to an array of string arguments. The end of the
+ * array is indicated with a NULL entry.
+ *
+ * Returned Value:
+ * This function does not return on success. On failure, it will return
+ * -1 (ERROR) and will set the 'errno' value appropriately.
+ *
+ ****************************************************************************/
+
+int execv(FAR const char *path, FAR char *const argv[])
+{
+ FAR const struct symtab_s *symtab;
+ int nsymbols;
+ int ret;
+
+ /* Get the current symbol table selection */
+
+ exec_getsymtab(&symtab, &nsymbols);
+
+ /* Start the task */
+
+ ret = exec(path, (FAR const char **)argv, symtab, nsymbols);
+ if (ret < 0)
+ {
+ sdbg("exec failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Then exit */
+
+ exit(0);
+
+ /* We should not get here, but might be needed by some compilers. Other,
+ * smarter compilers might complain that this code is unreachable. You just
+ * can't win.
+ */
+
+ return ERROR;
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */
diff --git a/nuttx/net/Kconfig b/nuttx/net/Kconfig
index d4ea8befb..6a084914f 100644
--- a/nuttx/net/Kconfig
+++ b/nuttx/net/Kconfig
@@ -97,14 +97,14 @@ config NET_TCPURGDATA
compiled in. Urgent data (out-of-band data) is a rarely used TCP feature
that is very seldom would be required.
+menu "TCP/IP Networking"
+
config NET_TCP
bool "TCP/IP Networking"
default n
---help---
TCP support on or off
-endif
-
if NET_TCP
config NET_TCP_CONNS
int "Number of TCP/IP connections"
@@ -164,7 +164,36 @@ config NET_TCPBACKLOG
Incoming connections pend in a backlog until accept() is called.
The size of the backlog is selected when listen() is called.
+config NET_TCP_SPLIT
+ bool "Enable packet splitting"
+ default n
+ ---help---
+ send() will not return until the the transfer has been ACKed by the
+ recipient. But under RFC 1122, the host need not ACK each packet
+ immediately; the host may wait for 500 MS before ACKing. This
+ combination can cause very slow performance with small transfers are
+ made to an RFC 1122 client. However, the RFC 1122 must ACK at least
+ every second (odd) packet.
+
+ This option enables logic to trick the RFC 1122 host be exploiting
+ this last RFC 1122 requirement: If an odd number of packets were to
+ be sent, then send() will split the last even packet to guarantee
+ that an even number of packets will be sent and the RFC 1122 host
+ will ACK the final packet immediately.
+
+if NET_TCP_SPLIT
+
+config NET_TCP_SPLIT_SIZE
+ int "Split size threshold"
+ default 40
+ ---help---
+ Packets of this size or smaller than this will not be split.
+
endif
+endif
+endmenu
+
+menu "UDP Networking"
config NET_UDP
bool "UDP Networking"
@@ -193,6 +222,7 @@ config NET_BROADCAST
Incoming UDP broadcast support
endif
+endmenu
config NET_ICMP
bool "ICMP networking support"
@@ -321,3 +351,4 @@ config SLIP_DEFPRIO
The priority of the SLIP RX and TX tasks. Default: 128
endif
+endif
diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h
index ed2f12aa7..0726c7a80 100644
--- a/nuttx/net/net_internal.h
+++ b/nuttx/net/net_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* net/net_internal.h
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -139,94 +139,96 @@
* Public Variables
****************************************************************************/
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
/* List of registered ethernet device drivers */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-extern struct uip_driver_s *g_netdevices;
+EXTERN struct uip_driver_s *g_netdevices;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
/* net_sockets.c *************************************************************/
-EXTERN int sockfd_allocate(int minsd);
-EXTERN void sock_release(FAR struct socket *psock);
-EXTERN void sockfd_release(int sockfd);
-EXTERN FAR struct socket *sockfd_socket(int sockfd);
+int sockfd_allocate(int minsd);
+void sock_release(FAR struct socket *psock);
+void sockfd_release(int sockfd);
+FAR struct socket *sockfd_socket(int sockfd);
/* net_connect.c *************************************************************/
#ifdef CONFIG_NET_TCP
-EXTERN int net_startmonitor(FAR struct socket *psock);
-EXTERN void net_stopmonitor(FAR struct uip_conn *conn);
+int net_startmonitor(FAR struct socket *psock);
+void net_stopmonitor(FAR struct uip_conn *conn);
+void net_lostconnection(FAR struct socket *psock, uint16_t flags);
#endif
/* net_close.c ***************************************************************/
-EXTERN int psock_close(FAR struct socket *psock);
+int psock_close(FAR struct socket *psock);
/* sockopt support ***********************************************************/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
-EXTERN int net_timeo(uint32_t start_time, socktimeo_t timeo);
-EXTERN socktimeo_t net_timeval2dsec(struct timeval *tv);
-EXTERN void net_dsec2timeval(uint16_t dsec, struct timeval *tv);
+int net_timeo(uint32_t start_time, socktimeo_t timeo);
+socktimeo_t net_timeval2dsec(FAR struct timeval *tv);
+void net_dsec2timeval(uint16_t dsec, FAR struct timeval *tv);
#endif
/* net_register.c ************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN void netdev_seminit(void);
-EXTERN void netdev_semtake(void);
-EXTERN void netdev_semgive(void);
+void netdev_seminit(void);
+void netdev_semtake(void);
+void netdev_semgive(void);
#endif
/* net_findbyname.c **********************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN FAR struct uip_driver_s *netdev_findbyname(const char *ifname);
+FAR struct uip_driver_s *netdev_findbyname(FAR const char *ifname);
#endif
/* net_findbyaddr.c **********************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr);
+FAR struct uip_driver_s *netdev_findbyaddr(FAR const uip_ipaddr_t *raddr);
#endif
/* net_txnotify.c ************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN void netdev_txnotify(const uip_ipaddr_t *raddr);
+void netdev_txnotify(const uip_ipaddr_t *raddr);
#endif
/* net_count.c ***************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN int netdev_count(void);
+int netdev_count(void);
#endif
/* net_arptimer.c ************************************************************/
#ifdef CONFIG_NET_ARP
-EXTERN void arptimer_init(void);
+void arptimer_init(void);
#else
# define arptimer_init()
#endif
/* send.c ********************************************************************/
-EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
- size_t len, int flags);
+ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
+ int flags);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/net/net_monitor.c b/nuttx/net/net_monitor.c
index 4bdae4ccf..1eeb4bd27 100644
--- a/nuttx/net/net_monitor.c
+++ b/nuttx/net/net_monitor.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/net_monitor.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -67,7 +67,6 @@ static void connection_event(struct uip_conn *conn, uint16_t flags);
* Some connection related event has occurred
*
* Parameters:
- * dev The sructure of the network driver that caused the interrupt
* conn The connection structure associated with the socket
* flags Set of events describing why the callback was invoked
*
@@ -79,7 +78,7 @@ static void connection_event(struct uip_conn *conn, uint16_t flags);
*
****************************************************************************/
-static void connection_event(struct uip_conn *conn, uint16_t flags)
+static void connection_event(FAR struct uip_conn *conn, uint16_t flags)
{
FAR struct socket *psock = (FAR struct socket *)conn->connection_private;
@@ -87,37 +86,11 @@ static void connection_event(struct uip_conn *conn, uint16_t flags)
{
nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
- /* These loss-of-connection events may be reported:
- *
- * UIP_CLOSE: The remote host has closed the connection
- * UIP_ABORT: The remote host has aborted the connection
- * UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
- *
- * And we need to set these two socket status bits appropriately:
- *
- * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
- * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
- * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
- */
+ /* UIP_CLOSE, UIP_ABORT, or UIP_TIMEDOUT: Loss-of-connection events */
- if ((flags & UIP_CLOSE) != 0)
- {
- /* The peer gracefully closed the connection. Marking the
- * connection as disconnected will suppress some subsequent
- * ENOTCONN errors from receive. A graceful disconnection is
- * not handle as an error but as an "end-of-file"
- */
-
- psock->s_flags &= ~_SF_CONNECTED;
- psock->s_flags |= _SF_CLOSED;
- }
- else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
+ if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
- /* The loss of connection was less than graceful. This will (eventually)
- * be reported as an ENOTCONN error.
- */
-
- psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
+ net_lostconnection(psock, flags);
}
/* UIP_CONNECTED: The socket is successfully connected */
@@ -184,4 +157,60 @@ void net_stopmonitor(FAR struct uip_conn *conn)
conn->connection_event = NULL;
}
+/****************************************************************************
+ * Name: net_lostconnection
+ *
+ * Description:
+ * Called when a loss-of-connection event has occurred.
+ *
+ * Parameters:
+ * psock The TCP socket structure associated.
+ * flags Set of connection events events
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+void net_lostconnection(FAR struct socket *psock, uint16_t flags)
+{
+ DEBUGASSERT(psock)
+
+ /* These loss-of-connection events may be reported:
+ *
+ * UIP_CLOSE: The remote host has closed the connection
+ * UIP_ABORT: The remote host has aborted the connection
+ * UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
+ *
+ * And we need to set these two socket status bits appropriately:
+ *
+ * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
+ * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
+ * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
+ */
+
+ if ((flags & UIP_CLOSE) != 0)
+ {
+ /* The peer gracefully closed the connection. Marking the
+ * connection as disconnected will suppress some subsequent
+ * ENOTCONN errors from receive. A graceful disconnection is
+ * not handle as an error but as an "end-of-file"
+ */
+
+ psock->s_flags &= ~_SF_CONNECTED;
+ psock->s_flags |= _SF_CLOSED;
+ }
+ else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
+ {
+ /* The loss of connection was less than graceful. This will (eventually)
+ * be reported as an ENOTCONN error.
+ */
+
+ psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
+ }
+}
+
#endif /* CONFIG_NET && CONFIG_NET_TCP */
diff --git a/nuttx/net/net_poll.c b/nuttx/net/net_poll.c
index 815c6a71d..2e73bd73c 100644
--- a/nuttx/net/net_poll.c
+++ b/nuttx/net/net_poll.c
@@ -125,16 +125,22 @@ static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
if ((flags & UIP_POLL) != 0)
{
- eventset |= POLLOUT & fds->events;
+ eventset |= (POLLOUT & fds->events);
}
- /* Check for a loss of connection events */
+ /* Check for a loss of connection events.
+ *
+ * REVISIT: Need to call net_lostconnection() here, but don't have
+ * the psock instance. What should we do?
+ */
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
- eventset |= (POLLERR|POLLHUP);
+ eventset |= (POLLERR | POLLHUP);
}
+ /* Awaken the caller of poll() is requested event occurred. */
+
if (eventset)
{
fds->revents |= eventset;
@@ -192,9 +198,9 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
goto errout_with_irq;
}
- /* Initialize the callbcack structure */
+ /* Initialize the callback structure */
- cb->flags = UIP_NEWDATA|UIP_BACKLOG|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
+ cb->flags = (UIP_NEWDATA|UIP_BACKLOG|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT);
cb->priv = (FAR void *)fds;
cb->event = poll_interrupt;
@@ -212,13 +218,23 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
if (!sq_empty(&conn->readahead))
#endif
{
- fds->revents = fds->events & POLLIN;
- if (fds->revents != 0)
- {
- /* If data is available now, the signal the poll logic */
+ fds->revents |= (POLLOUT & fds->events);
+ }
- sem_post(fds->sem);
- }
+ /* Check for a loss of connection events */
+
+ if (!_SS_ISCONNECTED(psock->s_flags))
+ {
+ fds->revents |= (POLLERR | POLLHUP);
+ }
+
+ /* Check if any requested events are already in effect */
+
+ if (fds->revents != 0)
+ {
+ /* Yes.. then signal the poll logic */
+
+ sem_post(fds->sem);
}
uip_unlock(flags);
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index 6bfbd31ad..6864dace3 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/recvfrom.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -83,7 +83,7 @@ struct recvfrom_s
FAR struct sockaddr_in *rf_from; /* Address of sender */
#endif
size_t rf_recvlen; /* The received length */
- int rf_result; /* OK:success, failure:negated errno */
+ int rf_result; /* Success:OK, failure:negated errno */
};
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
@@ -464,10 +464,11 @@ static inline void recvfrom_tcpsender(struct uip_driver_s *dev, struct recvfrom_
****************************************************************************/
#ifdef CONFIG_NET_TCP
-static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
- void *pvpriv, uint16_t flags)
+static uint16_t recvfrom_tcpinterrupt(FAR struct uip_driver_s *dev,
+ FAR void *conn, FAR void *pvpriv,
+ uint16_t flags)
{
- struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv;
+ FAR struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv;
nllvdbg("flags: %04x\n", flags);
@@ -553,7 +554,7 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
- nllvdbg("error\n");
+ nllvdbg("Lost connection\n");
/* Stop further callbacks */
@@ -561,17 +562,40 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
pstate->rf_cb->priv = NULL;
pstate->rf_cb->event = NULL;
- /* If the peer gracefully closed the connection, then return zero
- * (end-of-file). Otherwise, report a not-connected error
- */
+ /* Handle loss-of-connection event */
+
+ net_lostconnection(pstate->rf_sock, flags);
+
+ /* Check if the peer gracefully closed the connection. */
if ((flags & UIP_CLOSE) != 0)
{
+ /* This case should always return success (zero)! The value of
+ * rf_recvlen, if zero, will indicate that the connection was
+ * gracefully closed.
+ */
+
pstate->rf_result = 0;
}
else
{
+ /* If no data has been received, then return ENOTCONN.
+ * Otherwise, let this return success. The failure will
+ * be reported the next time that recv[from]() is called.
+ */
+
+#if CONFIG_NET_TCP_RECVDELAY > 0
+ if (pstate->rf_recvlen > 0)
+ {
+ pstate->rf_result = 0;
+ }
+ else
+ {
+ pstate->rf_result = -ENOTCONN;
+ }
+#else
pstate->rf_result = -ENOTCONN;
+#endif
}
/* Wake up the waiting thread */
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 8a5154191..79dfef4ec 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/send.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,9 @@
#include <sys/types.h>
#include <sys/socket.h>
+
#include <stdint.h>
+#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
@@ -62,6 +64,10 @@
* Definitions
****************************************************************************/
+#if defined(CONFIG_NET_TCP_SPLIT) && !defined(CONFIG_NET_TCP_SPLIT_SIZE)
+# define CONFIG_NET_TCP_SPLIT_SIZE 40
+#endif
+
#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
/****************************************************************************
@@ -85,6 +91,9 @@ struct send_s
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint32_t snd_time; /* last send time for determining timeout */
#endif
+#if defined(CONFIG_NET_TCP_SPLIT)
+ bool snd_odd; /* True: Odd packet in pair transaction */
+#endif
};
/****************************************************************************
@@ -200,6 +209,14 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
pstate->snd_sent = pstate->snd_acked;
+#if defined(CONFIG_NET_TCP_SPLIT)
+ /* Reset the the even/odd indicator to even since we need to
+ * retransmit.
+ */
+
+ pstate->snd_odd = false;
+#endif
+
/* Fall through to re-send data from the last that was ACKed */
}
@@ -210,6 +227,8 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
/* Report not connected */
nllvdbg("Lost connection\n");
+
+ net_lostconnection(pstate->snd_sock, flags);
pstate->snd_sent = -ENOTCONN;
goto end_wait;
}
@@ -242,6 +261,89 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
/* Get the amount of data that we can send in the next packet */
uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;
+
+
+#if defined(CONFIG_NET_TCP_SPLIT)
+
+ /* RFC 1122 states that a host may delay ACKing for up to 500ms but
+ * must respond to every second segment). This logic here will trick
+ * the RFC 1122 recipient into responding sooner. This logic will be
+ * activated if:
+ *
+ * 1. An even number of packets has been send (where zero is an even
+ * number),
+ * 2. There is more data be sent (more than or equal to
+ * CONFIG_NET_TCP_SPLIT_SIZE), but
+ * 3. Not enough data for two packets.
+ *
+ * Then we will split the remaining, single packet into two partial
+ * packets. This will stimulate the RFC 1122 peer to ACK sooner.
+ *
+ * Don't try to split very small packets (less than CONFIG_NET_TCP_SPLIT_SIZE).
+ * Only the first even packet and the last odd packets could have
+ * sndlen less than CONFIG_NET_TCP_SPLIT_SIZE. The value of sndlen on
+ * the last even packet is guaranteed to be at least MSS/2 by the
+ * logic below.
+ */
+
+ if (sndlen >= CONFIG_NET_TCP_SPLIT_SIZE)
+ {
+ /* sndlen is the number of bytes remaining to be sent.
+ * uip_mss(conn) will return the number of bytes that can sent
+ * in one packet. The difference, then, is the number of bytes
+ * that would be sent in the next packet after this one.
+ */
+
+ int32_t next_sndlen = sndlen - uip_mss(conn);
+
+ /* Is this the even packet in the packet pair transaction? */
+
+ if (!pstate->snd_odd)
+ {
+ /* next_sndlen <= 0 means that the entire remaining data
+ * could fit into this single packet. This is condition
+ * in which we must do the split.
+ */
+
+ if (next_sndlen <= 0)
+ {
+ /* Split so that there will be an odd packet. Here
+ * we know that 0 < sndlen <= MSS
+ */
+
+ sndlen = (sndlen / 2) + 1;
+ }
+ }
+
+ /* No... this is the odd packet in the packet pair transaction */
+
+ else
+ {
+ /* Will there be another (even) packet afer this one?
+ * (next_sndlen > 0) Will the split conidition occur on that
+ * next, even packet? ((next_sndlen - uip_mss(conn)) < 0) If
+ * so, then perform the split now to avoid the case where the
+ * byte count is less than CONFIG_NET_TCP_SPLIT_SIZE on the
+ * next pair.
+ */
+
+ if (next_sndlen > 0 && (next_sndlen - uip_mss(conn)) < 0)
+ {
+ /* Here, we know that sndlen must be MSS < sndlen <= 2*MSS
+ * and so (sndlen / 2) is <= MSS.
+ */
+
+ sndlen /= 2;
+ }
+ }
+ }
+
+ /* Toggle the even/odd indicator */
+
+ pstate->snd_odd ^= true;
+
+#endif /* CONFIG_NET_TCP_SPLIT */
+
if (sndlen > uip_mss(conn))
{
sndlen = uip_mss(conn);
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index bfaec3b5d..fe9a88085 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -4,7 +4,7 @@
#
config MSEC_PER_TICK
- int "tick timer"
+ int "Milliseconds per system timer tick"
default 10
---help---
The default system timer is 100Hz or MSEC_PER_TICK=10. This setting
@@ -12,7 +12,7 @@ config MSEC_PER_TICK
system timer interrupts at some interrupt interval other than 10 msec.
config RR_INTERVAL
- int "round robin timeslice"
+ int "Round robin timeslice (MSEC)"
default 0
---help---
The round robin timeslice will be set this number of milliseconds;
@@ -38,6 +38,92 @@ config TASK_NAME_SIZE
Useful if scheduler instrumentation is selected. Set to zero to
disable.
+config SCHED_HAVE_PARENT
+ bool "Support parent/child task relationships"
+ default n
+ ---help---
+ Remember the ID of the parent task when a new child task is
+ created. This support enables some additional features (such as
+ SIGCHLD) and modifies the behavior of other interfaces. For
+ example, it makes waitpid() more standards complete by restricting
+ the waited-for tasks to the children of the caller. Default:
+ disabled.
+
+config SCHED_CHILD_STATUS
+ bool "Retain child exit status"
+ default n
+ depends on SCHED_HAVE_PARENT
+ ---help---
+ If this option is selected, then the exit status of the child task
+ will be retained after the child task exits. This option should be
+ selected if you require knowledge of a child process' exit status.
+ Without this setting, wait(), waitpid() or waitid() may fail. For
+ example, if you do:
+
+ 1) Start child task
+ 2) Wait for exit status (using wait(), waitpid(), or waitid()).
+
+ This can fail because the child task may run to completion before
+ the wait begins. There is a non-standard work-around in this case:
+ The above sequence will work if you disable pre-emption using
+ sched_lock() prior to starting the child task, then re-enable pre-
+ emption with sched_unlock() after the wait completes. This works
+ because the child task is not permitted to run until the wait is in
+ place.
+
+ The standard solution would be to enable SCHED_CHILD_STATUS. In
+ this case the exit status of the child task is retained after the
+ child exits and the wait will successful obtain the child task's
+ exit status whether it is called before the child task exits or not.
+
+ Warning: If you enable this feature, then your application must
+ either (1) take responsibility for reaping the child status with wait(),
+ waitpid(), or waitid(), or (2) suppress retention of child status.
+ If you do not reap the child status, then you have a memory leak and
+ your system will eventually fail.
+
+ Retention of child status can be suppressed on the parent using logic like:
+
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+ int ret = sigaction(SIGCHLD, &sa, NULL);
+
+config PREALLOC_CHILDSTATUS
+ int "Number of pre-allocated child status"
+ default 0
+ depends on SCHED_CHILD_STATUS
+ ---help---
+ To prevent runaway child status allocations and to improve
+ allocation performance, child task exit status structures are pre-
+ allocated when the system boots. This setting determines the number
+ of child status structures that will be pre-allocated. If this
+ setting is not defined or if it is defined to be zero then a value
+ of 2*MAX_TASKS is used.
+
+ Note that there cannot be more that CONFIG_MAX_TASKS tasks in total.
+ However, the number of child status structures may need to be
+ significantly larger because this number includes the maximum number
+ of tasks that are running PLUS the number of tasks that have exit'ed
+ without having their exit status reaped (via wait(), waitid(), or
+ waitpid()).
+
+ Obviously, if tasks spawn children indefinitely and never have the
+ exit status reaped, then you may have a memory leak! If you enable
+ the SCHED_CHILD_STATUS feature, then your application must take
+ responsibility for either (1) reaping the child status with wait(),
+ waitpid(), or waitid() or it must (2) suppress retention of child
+ status. Otherwise, your system will eventually fail.
+
+ Retention of child status can be suppressed on the parent using logic like:
+
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+ int ret = sigaction(SIGCHLD, &sa, NULL);
+
config JULIAN_TIME
bool "Enables Julian time conversions"
default n
@@ -45,15 +131,15 @@ config JULIAN_TIME
Enables Julian time conversions
config START_YEAR
- int "start year"
+ int "Start year"
default 2013
config START_MONTH
- int "start month"
+ int "Start month"
default 1
config START_DAY
- int "start day"
+ int "Start day"
default 1
config DEV_CONSOLE
@@ -77,7 +163,7 @@ config PRIORITY_INHERITANCE
Set to enable support for priority inheritance on mutexes and semaphores.
config SEM_PREALLOCHOLDERS
- int "Pre-allocated holders"
+ int "Number of pre-allocated holders"
default 16
depends on PRIORITY_INHERITANCE
---help---
@@ -127,6 +213,7 @@ config SDCLONE_DISABLE
config SCHED_WORKQUEUE
bool "Enable worker thread"
default n
+ depends on !DISABLE_SIGNALS
---help---
Create a dedicated "worker" thread to handle delayed processing from interrupt
handlers. This feature is required for some drivers but, if there are no
@@ -158,14 +245,6 @@ config SCHED_WORKSTACKSIZE
---help---
The stack size allocated for the worker thread. Default: 2K.
-config SIG_SIGWORK
- int "Worker thread wakeup signal"
- default 4
- depends on SCHED_WORKQUEUE
- ---help---
- The signal number that will be used to wake-up the worker thread.
- Default: 4
-
config SCHED_LPWORK
bool "Enable a lower priority worker thread"
default n
@@ -203,7 +282,12 @@ config SCHED_WAITPID
bool "Enable waitpid() API"
default n
---help---
- Enables the waitpid() API
+ Enables the waitpid() interface in a default, non-standard mode
+ (non-standard in the sense that the waited for PID need not be child
+ of the caller). If SCHED_HAVE_PARENT is also defined, then this
+ setting will modify the behavior or waitpid() (making more spec
+ compliant) and will enable the waitid() and wait() interfaces as
+ well.
config SCHED_ATEXIT
bool "Enable atexit() API"
@@ -310,10 +394,60 @@ config DISABLE_POLL
depends on DISABLE_OS_API
default n
+if !DISABLE_SIGNALS
+comment "Signal Numbers"
+
+config SIG_SIGUSR1
+ int "SIGUSR1"
+ default 1
+ ---help---
+ Value of standard user signal 1 (SIGUSR1). Default: 1
+
+config SIG_SIGUSR2
+ int "SIGUSR2"
+ default 2
+ ---help---
+ Value of standard user signal 2 (SIGUSR2). Default: 2
+
+config SIG_SIGALARM
+ int "SIGALRM"
+ default 3
+ ---help---
+ Default the signal number used with POSIX timers (SIGALRM).
+ Default: 3
+
+config SIG_SIGCHLD
+ int "SIGCHLD"
+ default 4
+ depends on SCHED_HAVE_PARENT
+ ---help---
+ The SIGCHLD signal is sent to the parent of a child process when it
+ exits, is interrupted (stopped), or resumes after being interrupted.
+ Default: 4
+
+config SIG_SIGCONDTIMEDOUT
+ int "SIGCONDTIMEDOUT"
+ default 16
+ depends on !DISABLE_PTHREAD
+ ---help---
+ This non-standard signal number is used the implementation of
+ pthread_cond_timedwait(). Default 16.
+
+config SIG_SIGWORK
+ int "SIGWORK"
+ default 17
+ depends on SCHED_WORKQUEUE
+ ---help---
+ SIGWORK is a non-standard signal used to wake up the internal NuttX
+ worker thread. This setting specifies the signal number that will be
+ used for SIGWORK. Default: 17
+
+endif
+
comment "Sizes of configurable things (0 disables)"
config MAX_TASKS
- int "Max tasks"
+ int "Max number of tasks"
default 32
---help---
The maximum number of simultaneously active tasks. This value must be
@@ -327,33 +461,32 @@ config MAX_TASK_ARGS
receive (i.e., maxmum value of 'argc')
config NPTHREAD_KEYS
- int "Number of pthread keys"
+ int "Maximum number of pthread keys"
default 4
---help---
The number of items of thread-
specific data that can be retained
config NFILE_DESCRIPTORS
- int "Max file descriptors"
+ int "Maximum number of file descriptors per task"
default 16
---help---
- The maximum number of file
- descriptors (one for each open)
+ The maximum number of file descriptors per task (one for each open)
config NFILE_STREAMS
- int "Max file streams"
+ int "Maximum number of FILE streams"
default 16
---help---
The maximum number of streams that can be fopen'ed
config NAME_MAX
- int "name max"
+ int "Maximum size of a file name"
default 32
---help---
The maximum size of a file name.
config PREALLOC_MQ_MSGS
- int "Pre-allocated messages"
+ int "Number of pre-allocated messages"
default 32
---help---
The number of pre-allocated message structures. The system manages
@@ -367,21 +500,20 @@ config MQ_MAXMSGSIZE
setting (does not include other message structure overhead.
config MAX_WDOGPARMS
- int "max watchdog parms"
+ int "Maximum number of watchdog parameters"
default 4
---help---
- Maximum number of parameters that
- can be passed to a watchdog handler
+ Maximum number of parameters that can be passed to a watchdog handler
config PREALLOC_WDOGS
- int "Pre-allocated watchdogs"
+ int "Number of pre-allocated watchdog timers"
default 32
---help---
The number of pre-allocated watchdog structures. The system manages a
pool of preallocated watchdog structures to minimize dynamic allocations
config PREALLOC_TIMERS
- int "Pre-allocated timers"
+ int "Number of pre-allocated POSIX timers"
default 8
---help---
The number of pre-allocated POSIX timer structures. The system manages a
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile
index 82f74fc3c..1ad244450 100644
--- a/nuttx/sched/Makefile
+++ b/nuttx/sched/Makefile
@@ -1,7 +1,7 @@
############################################################################
# sched/Makefile
#
-# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -35,159 +35,175 @@
-include $(TOPDIR)/Make.defs
-ASRCS =
-AOBJS = $(ASRCS:.S=$(OBJEXT))
+ASRCS =
+AOBJS = $(ASRCS:.S=$(OBJEXT))
-MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \
- sched_garbage.c sched_setupstreams.c sched_getfiles.c sched_getsockets.c \
- sched_getstreams.c sched_setupidlefiles.c sched_setuptaskfiles.c \
- sched_setuppthreadfiles.c sched_releasefiles.c
+MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c
+MISC_SRCS += sched_garbage.c sched_setupstreams.c sched_getfiles.c sched_getsockets.c
+MISC_SRCS += sched_getstreams.c sched_setupidlefiles.c sched_setuptaskfiles.c
+MISC_SRCS += sched_setuppthreadfiles.c sched_releasefiles.c
-TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c \
- task_start.c task_delete.c task_deletecurrent.c task_exithook.c \
- task_restart.c exit.c getpid.c sched_addreadytorun.c \
- sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \
- sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \
- sched_verifytcb.c sched_releasetcb.c
+TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c
+TSK_SRCS += task_start.c task_delete.c task_deletecurrent.c task_exithook.c
+TSK_SRCS += task_restart.c task_vfork.c exit.c getpid.c sched_addreadytorun.c
+TSK_SRCS += sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c
+TSK_SRCS += sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c
+TSK_SRCS += sched_verifytcb.c sched_releasetcb.c
-SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \
- sched_setscheduler.c sched_getscheduler.c \
- sched_yield.c sched_rrgetinterval.c sched_foreach.c \
- sched_lock.c sched_unlock.c sched_lockcount.c sched_self.c
+ifneq ($(CONFIG_BINFMT_DISABLE),y)
+ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
+TSK_SRCS += task_posixspawn.c
+endif
+endif
+
+SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c
+SCHED_SRCS += sched_setscheduler.c sched_getscheduler.c
+SCHED_SRCS += sched_yield.c sched_rrgetinterval.c sched_foreach.c
+SCHED_SRCS += sched_lock.c sched_unlock.c sched_lockcount.c sched_self.c
ifeq ($(CONFIG_SCHED_ATEXIT),y)
-SCHED_SRCS += atexit.c
+SCHED_SRCS += atexit.c
endif
ifeq ($(CONFIG_SCHED_ONEXIT),y)
-SCHED_SRCS += on_exit.c
+SCHED_SRCS += on_exit.c
endif
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
-SCHED_SRCS += sched_reprioritize.c
+SCHED_SRCS += sched_reprioritize.c
+endif
+
+ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
+SCHED_SRCS += task_reparent.c
+ifeq ($(CONFIG_SCHED_CHILD_STATUS),y)
+SCHED_SRCS += task_childstatus.c
+endif
endif
ifeq ($(CONFIG_SCHED_WAITPID),y)
-SCHED_SRCS += sched_waitpid.c
+SCHED_SRCS += sched_waitpid.c
+ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
+SCHED_SRCS += sched_waitid.c sched_wait.c
+endif
endif
-ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c \
- env_findvar.c env_removevar.c \
- env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c
+ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c
+ENV_SRCS += env_findvar.c env_removevar.c
+ENV_SRCS += env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c
-WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c \
- wd_gettime.c
+WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c
+WDOG_SRCS += wd_gettime.c
-TIME_SRCS = sched_processtimer.c
+TIME_SRCS = sched_processtimer.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-TIME_SRCS += sleep.c usleep.c
+TIME_SRCS += sleep.c usleep.c
endif
-CLOCK_SRCS = clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c \
- clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c \
- clock_gettimeofday.c clock_systimer.c
+CLOCK_SRCS = clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c
+CLOCK_SRCS += clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c
+CLOCK_SRCS += clock_gettimeofday.c clock_systimer.c
-SIGNAL_SRCS = sig_initialize.c \
- sig_action.c sig_procmask.c sig_pending.c sig_suspend.c \
- sig_kill.c sig_queue.c sig_waitinfo.c sig_timedwait.c \
- sig_findaction.c sig_allocatependingsigaction.c \
- sig_releasependingsigaction.c sig_unmaskpendingsignal.c \
- sig_removependingsignal.c sig_releasependingsignal.c sig_lowest.c \
- sig_mqnotempty.c sig_cleanup.c sig_received.c sig_deliver.c pause.c
+SIGNAL_SRCS = sig_initialize.c
+SIGNAL_SRCS += sig_action.c sig_procmask.c sig_pending.c sig_suspend.c
+SIGNAL_SRCS += sig_kill.c sig_queue.c sig_waitinfo.c sig_timedwait.c
+SIGNAL_SRCS += sig_findaction.c sig_allocatependingsigaction.c
+SIGNAL_SRCS += sig_releasependingsigaction.c sig_unmaskpendingsignal.c
+SIGNAL_SRCS += sig_removependingsignal.c sig_releasependingsignal.c sig_lowest.c
+SIGNAL_SRCS += sig_mqnotempty.c sig_cleanup.c sig_received.c sig_deliver.c pause.c
-MQUEUE_SRCS = mq_open.c mq_close.c mq_unlink.c mq_send.c mq_timedsend.c\
- mq_sndinternal.c mq_receive.c mq_timedreceive.c mq_rcvinternal.c \
- mq_initialize.c mq_descreate.c mq_findnamed.c mq_msgfree.c mq_msgqfree.c
+MQUEUE_SRCS = mq_open.c mq_close.c mq_unlink.c mq_send.c mq_timedsend.c
+MQUEUE_SRCS += mq_sndinternal.c mq_receive.c mq_timedreceive.c mq_rcvinternal.c
+MQUEUE_SRCS += mq_initialize.c mq_descreate.c mq_findnamed.c mq_msgfree.c mq_msgqfree.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-MQUEUE_SRCS += mq_waitirq.c
+MQUEUE_SRCS += mq_waitirq.c
endif
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-MQUEUE_SRCS += mq_notify.c
+MQUEUE_SRCS += mq_notify.c
endif
-PTHREAD_SRCS = pthread_create.c pthread_exit.c pthread_join.c pthread_detach.c \
- pthread_yield.c pthread_getschedparam.c pthread_setschedparam.c \
- pthread_mutexinit.c pthread_mutexdestroy.c \
- pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c \
- pthread_condinit.c pthread_conddestroy.c \
- pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c \
- pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c \
- pthread_cancel.c pthread_setcancelstate.c \
- pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c \
- pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c \
- pthread_removejoininfo.c pthread_once.c pthread_setschedprio.c
+PTHREAD_SRCS = pthread_create.c pthread_exit.c pthread_join.c pthread_detach.c
+PTHREAD_SRCS += pthread_yield.c pthread_getschedparam.c pthread_setschedparam.c
+PTHREAD_SRCS += pthread_mutexinit.c pthread_mutexdestroy.c
+PTHREAD_SRCS += pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c
+PTHREAD_SRCS += pthread_condinit.c pthread_conddestroy.c
+PTHREAD_SRCS += pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c
+PTHREAD_SRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
+PTHREAD_SRCS += pthread_cancel.c pthread_setcancelstate.c
+PTHREAD_SRCS += pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c
+PTHREAD_SRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
+PTHREAD_SRCS += pthread_removejoininfo.c pthread_once.c pthread_setschedprio.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c
+PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c
endif
-SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \
- sem_wait.c sem_trywait.c sem_timedwait.c sem_post.c sem_findnamed.c
+SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c
+SEM_SRCS += sem_wait.c sem_trywait.c sem_timedwait.c sem_post.c sem_findnamed.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-SEM_SRCS += sem_waitirq.c
+SEM_SRCS += sem_waitirq.c
endif
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
-SEM_SRCS += sem_holder.c
+SEM_SRCS += sem_holder.c
endif
ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
-TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c \
- timer_gettime.c timer_settime.c timer_release.c
+TIMER_SRCS += timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c
+TIMER_SRCS += timer_gettime.c timer_settime.c timer_release.c
endif
ifeq ($(CONFIG_SCHED_WORKQUEUE),y)
-WORK_SRCS = work_thread.c work_queue.c work_cancel.c work_signal.c
+WORK_SRCS = work_thread.c work_queue.c work_cancel.c work_signal.c
endif
ifeq ($(CONFIG_PAGING),y)
-PGFILL_SRCS = pg_miss.c pg_worker.c
+PGFILL_SRCS = pg_miss.c pg_worker.c
endif
-IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c
+IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c
-KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c \
- kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c
+KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c
+KMM_SRCS = kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c
-CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \
- $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS)
+CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \
+ $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS)
ifneq ($(CONFIG_DISABLE_CLOCK),y)
-CSRCS += $(CLOCK_SRCS)
+CSRCS += $(CLOCK_SRCS)
endif
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
-CSRCS += $(PTHREAD_SRCS)
+CSRCS += $(PTHREAD_SRCS)
endif
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-CSRCS += $(SIGNAL_SRCS)
+CSRCS += $(SIGNAL_SRCS)
endif
ifneq ($(CONFIG_DISABLE_MQUEUE),y)
-CSRCS += $(MQUEUE_SRCS)
+CSRCS += $(MQUEUE_SRCS)
endif
ifneq ($(CONFIG_DISABLE_ENVIRON),y)
-CSRCS += $(ENV_SRCS)
+CSRCS += $(ENV_SRCS)
endif
ifeq ($(CONFIG_NUTTX_KERNEL),y)
-CSRCS += $(KMM_SRCS)
+CSRCS += $(KMM_SRCS)
endif
-COBJS = $(CSRCS:.c=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
-SRCS = $(ASRCS) $(CSRCS)
-OBJS = $(AOBJS) $(COBJS)
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
-BIN = libsched$(LIBEXT)
+BIN = libsched$(LIBEXT)
-all: $(BIN)
+all: $(BIN)
.PHONY: context depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
diff --git a/nuttx/sched/clock_time2ticks.c b/nuttx/sched/clock_time2ticks.c
index 9265872bb..012f4e4f1 100644
--- a/nuttx/sched/clock_time2ticks.c
+++ b/nuttx/sched/clock_time2ticks.c
@@ -89,14 +89,48 @@
int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks)
{
+#ifdef CONFIG_HAVE_LONG_LONG
+ int64_t relnsec;
+
+ /* Convert the relative time into nanoseconds. The range of the int64_t is
+ * sufficiently large that there is no real need for range checking.
+ */
+
+ relnsec = (int64_t)reltime->tv_sec * NSEC_PER_SEC +
+ (int64_t)reltime->tv_nsec;
+
+ /* Convert nanoseconds to clock ticks, rounding up to the smallest integer
+ * that is greater than or equal to the exact number of tick.
+ */
+
+ *ticks = (int)((relnsec + NSEC_PER_TICK - 1) / NSEC_PER_TICK);
+ return OK;
+#else
int32_t relusec;
- /* Convert the relative time into microseconds.*/
+ /* This function uses an int32_t to only the relative time in microseconds.
+ * that means that the maximum supported relative time is 2,147,487.647
+ * seconds
+ */
+
+#if 0 // overkill
+ DEBUGASSERT(reltime->tv_sec < 2147487 ||
+ reltime->tv_sec == 2147487 &&
+ reltime->tv_nsec <= 647 * NSEC_PER_MSEC);
+#endif
+
+ /* Convert the relative time into microseconds, rounding up to the smallest
+ * value that is greater than or equal to the exact number of microseconds.
+ */
- relusec = reltime->tv_sec * USEC_PER_SEC + reltime->tv_nsec / NSEC_PER_USEC;
+ relusec = reltime->tv_sec * USEC_PER_SEC +
+ (reltime->tv_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC;
- /* Convert microseconds to clock ticks */
+ /* Convert microseconds to clock ticks, rounding up to the smallest integer
+ * that is greater than or equal to the exact number of tick.
+ */
- *ticks = (relusec + USEC_PER_TICK - 1) / USEC_PER_TICK;
+ *ticks = (int)((relusec + USEC_PER_TICK - 1) / USEC_PER_TICK);
return OK;
+#endif
}
diff --git a/nuttx/sched/mq_initialize.c b/nuttx/sched/mq_initialize.c
index 5b03a1120..dd7c7ed0f 100644
--- a/nuttx/sched/mq_initialize.c
+++ b/nuttx/sched/mq_initialize.c
@@ -217,11 +217,11 @@ void mq_initialize(void)
void mq_desblockalloc(void)
{
- struct mq_des_block_s *mqdesblock;
+ FAR struct mq_des_block_s *mqdesblock;
/* Allocate a block of message descriptors */
- mqdesblock = (struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s));
+ mqdesblock = (FAR struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s));
if (mqdesblock)
{
int i;
diff --git a/nuttx/sched/os_bringup.c b/nuttx/sched/os_bringup.c
index e0a236bbe..610d8515a 100644
--- a/nuttx/sched/os_bringup.c
+++ b/nuttx/sched/os_bringup.c
@@ -57,9 +57,6 @@
#ifdef CONFIG_SCHED_WORKQUEUE
# include "work_internal.h"
#endif
-#ifdef CONFIG_BUILTIN_APP_START
-# include "apps/apps.h"
-#endif
#ifdef CONFIG_NUTTX_KERNEL
# include "arch/board/user_map.h"
#endif
@@ -112,22 +109,15 @@
* function is to serve as the "bottom half" of device
* drivers.
*
- * And the main application entry point. This may be one of two different
+ * And the main application entry point:
* symbols:
*
- * - USER_ENTRYPOINT: This is the default entry point used for all of the
- * example code in apps/examples.
- * - CONFIG_BUILTIN_APP_START: The system can also be configured to start
- * custom applications at however CONFIG_BUILTIN_APP_START
- * is defined in the NuttX start-up file.
+ * - USER_ENTRYPOINT: This is the default user application entry point.
*
****************************************************************************/
int os_bringup(void)
{
-#ifdef CONFIG_BUILTIN_APP_START
- static const char *argv[3] = {NULL, "init", NULL};
-#endif
int init_taskid;
/* Setup up the initial environment for the idle task. At present, this
@@ -188,19 +178,11 @@ int os_bringup(void)
svdbg("Starting init thread\n");
-#ifdef CONFIG_BUILTIN_APP_START
- /* Start the built-in named application, passing an "init" argument, so that
- * application can distinguish different run-levels
- */
-
- init_taskid = exec_namedapp(CONFIG_BUILTIN_APP_START, argv);
-#else
/* Start the default application at CONFIG_USER_ENTRYPOINT() */
init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT,
CONFIG_USERMAIN_STACKSIZE,
(main_t)CONFIG_USER_ENTRYPOINT, (const char **)NULL);
-#endif
ASSERT(init_taskid != ERROR);
/* We an save a few bytes by discarding the IDLE thread's environment. */
diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h
index 13b8083cf..7d5095bad 100644
--- a/nuttx/sched/os_internal.h
+++ b/nuttx/sched/os_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/os_internal.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -83,10 +83,10 @@ enum os_crash_codes_e
OSERR_BADREPRIORITIZESTATE /* Attempt to reprioritize in bad state or priority */
};
-/* Special task IDS */
+/* Special task IDS. Any negative PID is invalid. */
-#define NULL_TASK_PROCESS_ID 0
-#define INVALID_PROCESS_ID 0
+#define NULL_TASK_PROCESS_ID (pid_t)0
+#define INVALID_PROCESS_ID (pid_t)-1
/* Although task IDs can take the (positive, non-zero)
* range of pid_t, the number of tasks that will be supported
@@ -264,10 +264,22 @@ extern const tasklist_t g_tasklisttable[NUM_TASK_STATES];
int os_bringup(void);
void task_start(void);
int task_schedsetup(FAR _TCB *tcb, int priority, start_t start,
- main_t main);
+ main_t main, uint8_t ttype);
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]);
void task_exithook(FAR _TCB *tcb, int status);
int task_deletecurrent(void);
+#ifdef CONFIG_SCHED_HAVE_PARENT
+#ifdef CONFIG_SCHED_CHILD_STATUS
+void weak_function task_initialize(void);
+FAR struct child_status_s *task_allocchild(void);
+void task_freechild(FAR struct child_status_s *status);
+void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child);
+FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid);
+FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid);
+void task_removechildren(FAR _TCB *tcb);
+#endif
+int task_reparent(pid_t ppid, pid_t chpid);
+#endif
#ifndef CONFIG_CUSTOM_STACK
int kernel_thread(FAR const char *name, int priority, int stack_size,
main_t entry, FAR const char *argv[]);
diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c
index a53ac2aa8..a6d4e83b9 100644
--- a/nuttx/sched/os_start.c
+++ b/nuttx/sched/os_start.c
@@ -286,7 +286,7 @@ void os_start(void)
/* Initialize the processor-specific portion of the TCB */
- g_idletcb.flags = TCB_FLAG_TTYPE_KERNEL;
+ g_idletcb.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NOCLDWAIT);
up_initial_state(&g_idletcb);
/* Initialize the semaphore facility(if in link). This has to be done
@@ -314,6 +314,17 @@ void os_start(void)
kmm_initialize((void*)CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE);
#endif
+ /* Initialize tasking data structures */
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+#ifdef CONFIG_HAVE_WEAKFUNCTIONS
+ if (task_initialize != NULL)
+#endif
+ {
+ task_initialize();
+ }
+#endif
+
/* Initialize the interrupt handling subsystem (if included) */
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c
index dc2db2916..f4d0d8fdf 100644
--- a/nuttx/sched/pthread_create.c
+++ b/nuttx/sched/pthread_create.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread_create.c
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -354,15 +354,10 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
#endif
}
- /* Mark this task as a pthread (this setting will be needed in
- * task_schedsetup() when up_initial_state() is called.
- */
-
- ptcb->flags |= TCB_FLAG_TTYPE_PTHREAD;
-
/* Initialize the task control block */
- ret = task_schedsetup(ptcb, priority, pthread_start, (main_t)start_routine);
+ ret = task_schedsetup(ptcb, priority, pthread_start, (main_t)start_routine,
+ TCB_FLAG_TTYPE_PTHREAD);
if (ret != OK)
{
sched_releasetcb(ptcb);
diff --git a/nuttx/sched/sched_addprioritized.c b/nuttx/sched/sched_addprioritized.c
index 8f19a4731..20178fb9c 100644
--- a/nuttx/sched/sched_addprioritized.c
+++ b/nuttx/sched/sched_addprioritized.c
@@ -114,7 +114,7 @@ bool sched_addprioritized(FAR _TCB *tcb, DSEG dq_queue_t *list)
(next && sched_priority <= next->sched_priority);
next = next->flink);
- /* Add the tcb to the spot found in the list. Check if the tcb
+ /* Add the tcb to the spot found in the list. Check if the tcb
* goes at the end of the list. NOTE: This could only happen if list
* is the g_pendingtasks list!
*/
diff --git a/nuttx/sched/sched_addreadytorun.c b/nuttx/sched/sched_addreadytorun.c
index f6117b6ff..1e1829343 100644
--- a/nuttx/sched/sched_addreadytorun.c
+++ b/nuttx/sched/sched_addreadytorun.c
@@ -84,8 +84,8 @@
* btcb - Points to the blocked TCB that is ready-to-run
*
* Return Value:
- * true if the currently active task (the head of the
- * g_readytorun list) has changed.
+ * true if the currently active task (the head of the g_readytorun list)
+ * has changed.
*
* Assumptions:
* - The caller has established a critical section before
@@ -104,7 +104,7 @@ bool sched_addreadytorun(FAR _TCB *btcb)
bool ret;
/* Check if pre-emption is disabled for the current running task and if
- * the new ready-to-run task would cause the current running task to be
+ * the new ready-to-run task would cause the current running task to be
* preempted.
*/
@@ -123,7 +123,7 @@ bool sched_addreadytorun(FAR _TCB *btcb)
else if (sched_addprioritized(btcb, (FAR dq_queue_t*)&g_readytorun))
{
- /* Information the instrumentation logic that we are switching tasks */
+ /* Inform the instrumentation logic that we are switching tasks */
sched_note_switch(rtcb, btcb);
diff --git a/nuttx/sched/sched_setuptaskfiles.c b/nuttx/sched/sched_setuptaskfiles.c
index fe0b14143..d01b8d4cd 100644
--- a/nuttx/sched/sched_setuptaskfiles.c
+++ b/nuttx/sched/sched_setuptaskfiles.c
@@ -200,7 +200,8 @@ static inline void sched_dupsockets(FAR _TCB *tcb)
* tcb - tcb of the new task.
*
* Return Value:
- * None
+ * Zero (OK) is returned on success; A negated errno value is returned on
+ * failure.
*
* Assumptions:
*
diff --git a/nuttx/sched/sched_unlock.c b/nuttx/sched/sched_unlock.c
index 9a52e8358..5eafcfc9e 100644
--- a/nuttx/sched/sched_unlock.c
+++ b/nuttx/sched/sched_unlock.c
@@ -126,5 +126,6 @@ int sched_unlock(void)
irqrestore(flags);
}
+
return OK;
}
diff --git a/nuttx/sched/sched_wait.c b/nuttx/sched/sched_wait.c
new file mode 100644
index 000000000..813d4f842
--- /dev/null
+++ b/nuttx/sched/sched_wait.c
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * sched/sched_wait.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: wait
+ *
+ * Description:
+ * The wait() function will suspend execution of the calling thread until
+ * status information for one of its terminated child processes is
+ * available, or until delivery of a signal whose action is either to
+ * execute a signal-catching function or to terminate the process. If more
+ * than one thread is suspended in wait() or waitpid() awaiting termination
+ * of the same process, exactly one thread will return the process status
+ * at the time of the target process termination. If status information is
+ * available prior to the call to wait(), return will be immediate.
+ *
+ * The waitpid() function will behave identically to wait(), if the pid
+ * argument is (pid_t)-1 and the options argument is 0. Otherwise, its
+ * behaviour will be modified by the values of the pid and options arguments.
+ *
+ * Input Parameters:
+ * stat_loc - The location to return the exit status
+ *
+ * Returned Value:
+ * See waitpid();
+ *
+ *****************************************************************************/
+
+pid_t wait(FAR int *stat_loc)
+{
+ return waitpid((pid_t)-1, stat_loc, 0);
+}
+
+#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT*/
diff --git a/nuttx/sched/sched_waitid.c b/nuttx/sched/sched_waitid.c
new file mode 100644
index 000000000..37ee26ce0
--- /dev/null
+++ b/nuttx/sched/sched_waitid.c
@@ -0,0 +1,331 @@
+/*****************************************************************************
+ * sched/sched_waitid.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: waitid
+ *
+ * Description:
+ * The waitid() function suspends the calling thread until one child of
+ * the process containing the calling thread changes state. It records the
+ * current state of a child in the structure pointed to by 'info'. If a
+ * child process changed state prior to the call to waitid(), waitid()
+ * returns immediately. If more than one thread is suspended in wait() or
+ * waitpid() waiting termination of the same process, exactly one thread
+ * will return the process status at the time of the target process
+ * termination
+ *
+ * The idtype and id arguments are used to specify which children waitid()
+ * will wait for.
+ *
+ * If idtype is P_PID, waitid() will wait for the child with a process
+ * ID equal to (pid_t)id.
+ *
+ * If idtype is P_PGID, waitid() will wait for any child with a process
+ * group ID equal to (pid_t)id.
+ *
+ * If idtype is P_ALL, waitid() will wait for any children and id is
+ * ignored.
+ *
+ * The options argument is used to specify which state changes waitid()
+ * will will wait for. It is formed by OR-ing together one or more of the
+ * following flags:
+ *
+ * WEXITED - Wait for processes that have exited.
+ * WSTOPPED - Status will be returned for any child that has stopped
+ * upon receipt of a signal.
+ * WCONTINUED - Status will be returned for any child that was stopped
+ * and has been continued.
+ * WNOHANG - Return immediately if there are no children to wait for.
+ * WNOWAIT - Keep the process whose status is returned in 'info' in a
+ * waitable state. This will not affect the state of the process; the
+ * process may be waited for again after this call completes.
+ *
+ * The 'info' argument must point to a siginfo_t structure. If waitid()
+ * returns because a child process was found that satisfied the conditions
+ * indicated by the arguments idtype and options, then the structure pointed
+ * to by 'info' will be filled in by the system with the status of the
+ * process. The si_signo member will always be equal to SIGCHLD.
+ *
+ * Input Parameters:
+ * See description.
+ *
+ * Returned Value:
+ * If waitid() returns due to the change of state of one of its children,
+ * 0 is returned. Otherwise, -1 is returned and errno is set to indicate
+ * the error.
+ *
+ * The waitid() function will fail if:
+ *
+ * ECHILD - The calling process has no existing unwaited-for child
+ * processes.
+ * EINTR - The waitid() function was interrupted by a signal.
+ * EINVAL - An invalid value was specified for options, or idtype and id
+ * specify an invalid set of processes.
+ *
+ *****************************************************************************/
+
+int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
+{
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ sigset_t sigset;
+ int err;
+ int ret;
+
+ /* MISSING LOGIC: If WNOHANG is provided in the options, then this function
+ * should returned immediately. However, there is no mechanism available now
+ * know if the thread has child: The children remember their parents (if
+ * CONFIG_SCHED_HAVE_PARENT) but the parents do not remember their children.
+ */
+
+ /* None of the options are supported except for WEXITED (which must be
+ * provided. Currently SIGCHILD always reports CLD_EXITED so we cannot
+ * distinguish any other events.
+ */
+
+#ifdef CONFIG_DEBUG
+ if (options != WEXITED)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
+ /* Create a signal set that contains only SIGCHLD */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+
+ /* Disable pre-emption so that nothing changes while the loop executes */
+
+ sched_lock();
+
+ /* Verify that this task actually has children and that the the requested
+ * TCB is actually a child of this task.
+ */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ if (rtcb->children == NULL)
+ {
+ /* There are no children */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (idtype == P_PID)
+ {
+ if (task_findchild(rtcb, (pid_t)id) == NULL)
+ {
+ /* This specific pid is not a child */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+#else
+ if (rtcb->nchildren == 0)
+ {
+ /* There are no children */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (idtype == P_PID)
+ {
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
+
+ FAR _TCB *ctcb = sched_gettcb((pid_t)id);
+ if (!ctcb || ctcb->parent != rtcb->pid)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+#endif
+
+ /* Loop until the child that we are waiting for dies */
+
+ for (;;)
+ {
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ DEBUGASSERT(rtcb->children);
+ if (rtcb->children == NULL)
+ {
+ /* This should not happen. I am just wasting your FLASH. */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (idtype == P_PID)
+ {
+ FAR struct child_status_s *child;
+
+ /* We are waiting for a specific PID. Get the current status
+ * of the child task.
+ */
+
+ child = task_findchild(rtcb, (pid_t)id);
+ DEBUGASSERT(child);
+ if (!child)
+ {
+ /* Yikes! The child status entry just disappeared! */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+
+ /* Did the child exit? */
+
+ if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
+ {
+ /* The child has exited. Return the saved exit status */
+
+ info->si_signo = SIGCHLD;
+ info->si_code = CLD_EXITED;
+ info->si_value.sival_ptr = NULL;
+ info->si_pid = (pid_t)id;
+ info->si_status = child->ch_status;
+
+ /* Discard the child entry and break out of the loop */
+
+ (void)task_removechild(rtcb, (pid_t)id);
+ task_freechild(child);
+ }
+ }
+#else
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ if (rtcb->nchildren == 0 ||
+ (idtype == P_PID && (ret = kill((pid_t)id, 0)) < 0))
+ {
+ /* We know that the child task was running okay we stared,
+ * so we must have lost the signal. What can we do?
+ * Let's claim we were interrupted by a signal.
+ */
+
+ err = EINTR;
+ goto errout_with_errno;
+ }
+#endif
+
+ /* Wait for any death-of-child signal */
+
+ ret = sigwaitinfo(&sigset, info);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Make there this was SIGCHLD */
+
+ if (info->si_signo == SIGCHLD)
+ {
+ /* Yes.. Are we waiting for the death of a specific child? */
+
+ if (idtype == P_PID)
+ {
+ /* Was this the death of the thread we were waiting for? */
+
+ if (info->si_pid == (pid_t)id)
+ {
+ /* Yes... return success */
+
+ break;
+ }
+ }
+
+ /* Are we waiting for any child to change state? */
+
+ else if (idtype == P_ALL)
+ {
+ /* Return success */
+
+ break;
+ }
+
+ /* Other ID types are not supported */
+
+ else /* if (idtype == P_PGID) */
+ {
+ set_errno(ENOSYS);
+ goto errout;
+ }
+ }
+ }
+
+ sched_unlock();
+ return OK;
+
+errout_with_errno:
+ set_errno(err);
+errout:
+ sched_unlock();
+ return ERROR;
+}
+
+#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT*/
diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c
index 692ef6410..fe3f7167d 100644
--- a/nuttx/sched/sched_waitpid.c
+++ b/nuttx/sched/sched_waitpid.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* sched/sched_waitpid.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,13 +41,14 @@
#include <sys/wait.h>
#include <semaphore.h>
+#include <signal.h>
#include <errno.h>
#include <nuttx/sched.h>
#include "os_internal.h"
-#ifdef CONFIG_SCHED_WAITPID /* Experimental */
+#ifdef CONFIG_SCHED_WAITPID
/*****************************************************************************
* Private Functions
@@ -58,7 +59,7 @@
*****************************************************************************/
/*****************************************************************************
- * Name: sched_waitpid
+ * Name: waitpid
*
* Description:
*
@@ -172,10 +173,16 @@
*
*****************************************************************************/
-/***************************************************************************/
-/* NOTE: This is a partially functional, experimental version of waitpid() */
-/***************************************************************************/
+/***************************************************************************
+ * NOTE: This is a partially functional, experimental version of waitpid()
+ *
+ * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
+ * defined), then waitpid() is still available, but does not obey the
+ * restriction that the pid be a child of the caller.
+ *
+ ***************************************************************************/
+#ifndef CONFIG_SCHED_HAVE_PARENT
pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
_TCB *tcb;
@@ -183,9 +190,24 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
int err;
int ret;
+ DEBUGASSERT(stat_loc);
+
+ /* None of the options are supported */
+
+#ifdef CONFIG_DEBUG
+ if (options != 0)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
/* Disable pre-emption so that nothing changes in the following tests */
sched_lock();
+
+ /* Get the TCB corresponding to this PID */
+
tcb = sched_gettcb(pid);
if (!tcb)
{
@@ -193,16 +215,6 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
goto errout_with_errno;
}
- /* None of the options are supported */
-
-#ifdef CONFIG_DEBUG
- if (options != 0)
- {
- err = ENOSYS;
- goto errout_with_errno;
- }
-#endif
-
/* "If more than one thread is suspended in waitpid() awaiting termination of
* the same process, exactly one thread will return the process status at the
* time of the target process termination." Hmmm.. what do we return to the
@@ -245,4 +257,212 @@ errout:
return ERROR;
}
+/***************************************************************************
+ *
+ * If CONFIG_SCHED_HAVE_PARENT is defined, then waitpid will use the SIGHCLD
+ * signal. It can also handle the pid == (pid_t)-1 arguement. This is
+ * slightly more spec-compliant.
+ *
+ * But then I have to be concerned about the fact that NuttX does not queue
+ * signals. This means that a flurry of signals can cause signals to be
+ * lost (or to have the data in the struct siginfo to be overwritten by
+ * the next signal).
+ *
+ ***************************************************************************/
+
+#else
+pid_t waitpid(pid_t pid, int *stat_loc, int options)
+{
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ FAR struct child_status_s *child;
+#endif
+ FAR struct siginfo info;
+ sigset_t sigset;
+ int err;
+ int ret;
+
+ DEBUGASSERT(stat_loc);
+
+ /* None of the options are supported */
+
+#ifdef CONFIG_DEBUG
+ if (options != 0)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
+ /* Create a signal set that contains only SIGCHLD */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+
+ /* Disable pre-emption so that nothing changes while the loop executes */
+
+ sched_lock();
+
+ /* Verify that this task actually has children and that the the request
+ * TCB is actually a child of this task.
+ */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ if (rtcb->children == NULL)
+ {
+ /* There are no children */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (pid != (pid_t)-1)
+ {
+ /* This specific pid is not a child */
+
+ if (task_findchild(rtcb, pid) == NULL)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+#else
+ if (rtcb->nchildren == 0)
+ {
+ /* There are no children */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (pid != (pid_t)-1)
+ {
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
+
+ FAR _TCB *ctcb = sched_gettcb(pid);
+ if (!ctcb || ctcb->parent != rtcb->pid)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+#endif
+
+ /* Loop until the child that we are waiting for dies */
+
+ for (;;)
+ {
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ if (pid == (pid_t)-1)
+ {
+ /* We are waiting for any child, check if there are still
+ * chilren.
+ */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ DEBUGASSERT(rtcb->children);
+ if (rtcb->children == NULL)
+#else
+ if (rtcb->nchildren == 0)
+#endif
+ {
+ /* There were one or more children when we started so they
+ * must have exit'ed. There are just no bread crumbs left
+ * behind to tell us the PID(s) of the existed children.
+ * Reporting ECHLD is about all we can do in this case.
+ */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+ else
+ {
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* We are waiting for a specific PID. Get the current status
+ * of the child task.
+ */
+
+ child = task_findchild(rtcb, pid);
+ DEBUGASSERT(child);
+ if (!child)
+ {
+ /* Yikes! The child status entry just disappeared! */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+
+ /* Did the child exit? */
+
+ if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
+ {
+ /* The child has exited. Return the saved exit status */
+
+ *stat_loc = child->ch_status;
+
+ /* Discard the child entry and break out of the loop */
+
+ (void)task_removechild(rtcb, pid);
+ task_freechild(child);
+ }
+#else
+ /* We are waiting for a specific PID. We can use kill() with
+ * signal number 0 to determine if that task is still alive.
+ */
+
+ ret = kill(pid, 0);
+ if (ret < 0)
+ {
+ /* It is no longer running. We know that the child task was
+ * running okay when we started, so we must have lost the
+ * signal. In this case, we know that the task exit'ed, but
+ * we do not know its exit status. It would be better to
+ * reported ECHILD that bogus status.
+ */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+#endif
+ }
+
+ /* Wait for any death-of-child signal */
+
+ ret = sigwaitinfo(&sigset, &info);
+ if (ret < 0)
+ {
+ goto errout_with_lock;
+ }
+
+ /* Was this the death of the thread we were waiting for? In the of
+ * pid == (pid_t)-1, we are waiting for any child thread.
+ */
+
+ if (info.si_signo == SIGCHLD &&
+ (pid == (pid_t)-1 || info.si_pid == pid))
+ {
+ /* Yes... return the status and PID (in the event it was -1) */
+
+ *stat_loc = info.si_status;
+ pid = info.si_pid;
+ break;
+ }
+ }
+
+ sched_unlock();
+ return (int)pid;
+
+errout_with_errno:
+ set_errno(err);
+
+errout_with_lock:
+ sched_unlock();
+ return ERROR;
+}
+#endif /* CONFIG_SCHED_HAVE_PARENT */
+
#endif /* CONFIG_SCHED_WAITPID */
diff --git a/nuttx/sched/sig_action.c b/nuttx/sched/sig_action.c
index fef5f1558..708667993 100644
--- a/nuttx/sched/sig_action.c
+++ b/nuttx/sched/sig_action.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/sig_action.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,7 @@
#include <signal.h>
#include <queue.h>
#include <sched.h>
+#include <errno.h>
#include "os_internal.h"
#include "sig_internal.h"
@@ -156,10 +157,11 @@ static FAR sigactq_t *sig_allocateaction(void)
* Assumptions:
*
* POSIX Compatibility:
- * - Special values of sa_handler in the struct sigaction
- * act input not handled (SIG_DFL, SIG_IGN).
- * - All sa_flags in struct sigaction of act input are
- * ignored (all treated like SA_SIGINFO).
+ * - There are no default actions so the special value SIG_DFL is treated
+ * like SIG_IGN.
+ * - All sa_flags in struct sigaction of act input are ignored (all
+ * treated like SA_SIGINFO). The one exception is if CONFIG_SCHED_CHILDSTATUS
+ * is defined; then SA_NOCLDWAIT is supported but only for SIGCHLD
*
****************************************************************************/
@@ -167,90 +169,129 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
FAR sigactq_t *sigact;
- int ret = ERROR; /* Assume failure */
+ int ret;
/* Since sigactions can only be installed from the running thread of
* execution, no special precautions should be necessary.
*/
- /* Verify the signal */
+ /* Verify the signal number */
- if (GOOD_SIGNO(signo))
+ if (!GOOD_SIGNO(signo))
{
- ret = OK; /* Assume success */
+ set_errno(EINVAL);
+ return ERROR;
+ }
- /* Find the signal in the sigactionq */
+ /* Find the signal in the sigactionq */
- sigact = sig_findaction(rtcb, signo);
+ sigact = sig_findaction(rtcb, signo);
- /* Return the old sigaction value if so requested */
+ /* Return the old sigaction value if so requested */
- if (oact)
+ if (oact)
+ {
+ if (sigact)
{
- if (sigact)
- {
- COPY_SIGACTION(oact, &sigact->act);
- }
- else
- {
- /* There isn't an old value */
-
- oact->sa_u._sa_handler = NULL;
- oact->sa_mask = NULL_SIGNAL_SET;
- oact->sa_flags = 0;
- }
+ COPY_SIGACTION(oact, &sigact->act);
+ }
+ else
+ {
+ /* There isn't an old value */
+
+ oact->sa_u._sa_handler = NULL;
+ oact->sa_mask = NULL_SIGNAL_SET;
+ oact->sa_flags = 0;
}
+ }
+
+ /* If the argument act is a null pointer, signal handling is unchanged;
+ * thus, the call can be used to enquire about the current handling of
+ * a given signal.
+ */
- /* If no sigaction was found, but one is needed, then
- * allocate one.
+ if (!act)
+ {
+ return OK;
+ }
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+
+ /* Handle a special case. Retention of child status can be suppressed
+ * if signo == SIGCHLD and sa_flags == SA_NOCLDWAIT.
+ *
+ * POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated
+ * when a child process terminates. In NuttX, a SIGCHLD signal is
+ * generated in this case; but in some other implementations, it may not
+ * be.
+ */
+
+ if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0)
+ {
+ irqstate_t flags;
+
+ /* We do require a critical section to muck with the TCB values that
+ * can be modified by the child thread.
*/
- if (!sigact && act && act->sa_u._sa_handler)
- {
- sigact = sig_allocateaction();
+ flags = irqsave();
- /* An error has occurred if we could not allocate the sigaction */
+ /* Mark that status should be not be retained */
- if (!sigact)
- {
- ret = ERROR;
- }
- else
- {
- /* Put the signal number in the queue entry */
+ rtcb->flags |= TCB_FLAG_NOCLDWAIT;
- sigact->signo = (uint8_t)signo;
+ /* Free all pending exit status */
- /* Add the new sigaction to sigactionq */
+ task_removechildren(rtcb);
+ irqrestore(flags);
+ }
+#endif
- sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
- }
- }
+ /* Handle the case where no sigaction is supplied (SIG_IGN) */
+
+ if (act->sa_u._sa_handler == SIG_IGN)
+ {
+ /* If there is a old sigaction, remove it from sigactionq */
+
+ sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
+
+ /* And deallocate it */
+
+ sig_releaseaction(sigact);
+ }
- /* Set the new sigaction if so requested */
+ /* A sigaction has been supplied */
- if ((sigact) && (act))
+ else
+ {
+ /* Check if a sigaction was found */
+
+ if (!sigact)
{
- /* Check if it is a request to install a new handler */
+ /* No sigaction was found, but one is needed. Allocate one. */
- if (act->sa_u._sa_handler)
- {
- COPY_SIGACTION(&sigact->act, act);
- }
+ sigact = sig_allocateaction();
- /* No.. It is a request to remove the old handler */
+ /* An error has occurred if we could not allocate the sigaction */
- else
- {
- /* Remove the old sigaction from sigactionq */
+ if (!sigact)
+ {
+ set_errno(ENOMEM);
+ return ERROR;
+ }
+
+ /* Put the signal number in the queue entry */
- sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
+ sigact->signo = (uint8_t)signo;
- /* And deallocate it */
+ /* Add the new sigaction to sigactionq */
- sig_releaseaction(sigact);
- }
+ sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
}
+
+ /* Set the new sigaction */
+
+ COPY_SIGACTION(&sigact->act, act);
}
return ret;
diff --git a/nuttx/sched/sig_kill.c b/nuttx/sched/sig_kill.c
index 17921015f..b3d74d8a1 100644
--- a/nuttx/sched/sig_kill.c
+++ b/nuttx/sched/sig_kill.c
@@ -84,6 +84,9 @@
int kill(pid_t pid, int signo)
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -124,6 +127,10 @@ int kill(pid_t pid, int signo)
info.si_signo = signo;
info.si_code = SI_USER;
info.si_value.sival_ptr = NULL;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/sched/sig_mqnotempty.c b/nuttx/sched/sig_mqnotempty.c
index 9a1fd7243..f7ae6fd0d 100644
--- a/nuttx/sched/sig_mqnotempty.c
+++ b/nuttx/sched/sig_mqnotempty.c
@@ -88,6 +88,9 @@ int sig_mqnotempty (int pid, int signo, union sigval value)
int sig_mqnotempty (int pid, int signo, void *sival_ptr)
#endif
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -113,6 +116,10 @@ int sig_mqnotempty (int pid, int signo, void *sival_ptr)
#else
info.si_value.sival_ptr = sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Verify that we can perform the signalling operation */
diff --git a/nuttx/sched/sig_queue.c b/nuttx/sched/sig_queue.c
index dee1c798a..db404238e 100644
--- a/nuttx/sched/sig_queue.c
+++ b/nuttx/sched/sig_queue.c
@@ -111,6 +111,9 @@ int sigqueue (int pid, int signo, union sigval value)
int sigqueue(int pid, int signo, void *sival_ptr)
#endif
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -142,13 +145,17 @@ int sigqueue(int pid, int signo, void *sival_ptr)
/* Create the siginfo structure */
- info.si_signo = signo;
- info.si_code = SI_QUEUE;
+ info.si_signo = signo;
+ info.si_code = SI_QUEUE;
#ifdef CONFIG_CAN_PASS_STRUCTS
- info.si_value = value;
+ info.si_value = value;
#else
info.si_value.sival_ptr = sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/sched/sig_timedwait.c b/nuttx/sched/sig_timedwait.c
index 1b8dfd162..f8c619b21 100644
--- a/nuttx/sched/sig_timedwait.c
+++ b/nuttx/sched/sig_timedwait.c
@@ -38,6 +38,7 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <nuttx/compiler.h>
#include <stdint.h>
#include <string.h>
@@ -119,6 +120,10 @@ static void sig_timeout(int argc, uint32_t itcb)
u.wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT;
u.wtcb->sigunbinfo.si_code = SI_TIMER;
u.wtcb->sigunbinfo.si_value.sival_int = 0;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ u.wtcb->sigunbinfo.si_pid = 0; /* Not applicable */
+ u.wtcb->sigunbinfo.si_status = OK;
+#endif
up_unblock_task(u.wtcb);
}
}
@@ -223,7 +228,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
/* The return value is the number of the signal that awakened us */
- ret = info->si_signo;
+ ret = sigpend->info.si_signo;
}
/* We will have to wait for a signal to be posted to this task. */
@@ -238,10 +243,25 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
if (timeout)
{
- /* Convert the timespec to milliseconds */
+ /* Convert the timespec to system clock ticks, making sure that
+ * the resultint delay is greater than or equal to the requested
+ * time in nanoseconds.
+ */
- waitticks = MSEC2TICK(timeout->tv_sec * MSEC_PER_SEC
- + timeout->tv_nsec / NSEC_PER_MSEC);
+#ifdef CONFIG_HAVE_LONG_LONG
+ uint64_t waitticks64 = ((uint64_t)timeout->tv_sec * NSEC_PER_SEC +
+ (uint64_t)timeout->tv_nsec + NSEC_PER_TICK - 1) /
+ NSEC_PER_TICK;
+ DEBUGASSERT(waitticks64 <= UINT32_MAX);
+ waitticks = (uint32_t)waitticks64;
+#else
+ uint32_t waitmsec;
+
+ DEBUGASSERT(timeout->tv_sec < UINT32_MAX / MSEC_PER_SEC);
+ waitmsec = timeout->tv_sec * MSEC_PER_SEC +
+ (timeout->tv_nsec + NSEC_PER_MSEC - 1) / NSEC_PER_MSEC;
+ waitticks = (waitmsec + MSEC_PER_TICK - 1) / MSEC_PER_TICK;
+#endif
/* Create a watchdog */
@@ -326,6 +346,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
{
memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo));
}
+
irqrestore(saved_state);
}
diff --git a/nuttx/sched/task_childstatus.c b/nuttx/sched/task_childstatus.c
new file mode 100644
index 000000000..0f6d36c29
--- /dev/null
+++ b/nuttx/sched/task_childstatus.c
@@ -0,0 +1,396 @@
+/*****************************************************************************
+ * sched/task_childstatus.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+/* Note that there cannot be more that CONFIG_MAX_TASKS tasks in total.
+ * However, the number of child status structures may need to be significantly
+ * larger because this number includes the maximum number of tasks that are
+ * running PLUS the number of tasks that have exit'ed without having their
+ * exit status reaped (via wait(), waitid(), or waitpid()).
+ *
+ * Obviously, if tasks spawn children indefinitely and never have the exit
+ * status reaped, then you have a memory leak!
+ */
+
+#if !defined(CONFIG_PREALLOC_CHILDSTATUS) || CONFIG_PREALLOC_CHILDSTATUS == 0
+# undef CONFIG_PREALLOC_CHILDSTATUS
+# define CONFIG_PREALLOC_CHILDSTATUS (2*CONFIG_MAX_TASKS)
+#endif
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_CHILDSTATUS
+#endif
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+/* Globals are maintained in a structure to minimize name collisions. */
+
+struct child_pool_s
+{
+ struct child_status_s alloc[CONFIG_PREALLOC_CHILDSTATUS];
+ FAR struct child_status_s *freelist;
+};
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+static struct child_pool_s g_child_pool;
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: task_dumpchildren
+ *
+ * Description:
+ * Dump all of the children when the part TCB list is modified.
+ *
+ * Parameters:
+ * tcb - The parent TCB.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called early in initialization. No special precautions are required.
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_DEBUG_CHILDSTATUS
+static void task_dumpchildren(FAR _TCB *tcb, FAR const char *msg)
+{
+ FAR struct child_status_s *child;
+ int i;
+
+ dbg("Parent TCB=%p: %s\n", tcb, msg);
+ for (i = 0, child = tcb->children; child; i++, child = child->flink)
+ {
+ dbg(" %d. ch_flags=%02x ch_pid=%d ch_status=%d\n",
+ i, child->ch_flags, child->ch_pid, child->ch_status);
+ }
+}
+#else
+# task_dumpchildren(t,m)
+#endif
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: task_initialize
+ *
+ * Description:
+ * Initialize task related status. At present, this includes only the
+ * initialize of the child status pool.
+ *
+ * Parameters:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called early in initialization. No special precautions are required.
+ *
+ *****************************************************************************/
+
+void task_initialize(void)
+{
+ FAR struct child_status_s *curr;
+ FAR struct child_status_s *prev;
+ int i;
+
+ /* Save all of the child status structures in a free list */
+
+ prev = &g_child_pool.alloc[0];
+ g_child_pool.freelist = prev;
+ for (i = 0; i < CONFIG_PREALLOC_CHILDSTATUS; i++)
+ {
+ curr = &g_child_pool.alloc[i];
+ prev->flink = curr;
+ prev = curr;
+ }
+}
+
+/*****************************************************************************
+ * Name: task_allocchild
+ *
+ * Description:
+ * Allocate a child status structure by removing the next entry from a
+ * free list.
+ *
+ * Parameters:
+ * None.
+ *
+ * Return Value:
+ * On success, a non-NULL pointer to a child status structure. NULL is
+ * returned if there are no remaining, pre-allocated child status structures.
+ *
+ * Assumptions:
+ * Called during task creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+FAR struct child_status_s *task_allocchild(void)
+{
+ FAR struct child_status_s *ret;
+
+ /* Return the status block at the head of the free list */
+
+ ret = g_child_pool.freelist;
+ if (ret)
+ {
+ g_child_pool.freelist = ret->flink;
+ ret->flink = NULL;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+ * Name: task_freechild
+ *
+ * Description:
+ * Release a child status structure by returning it to a free list.
+ *
+ * Parameters:
+ * status - The child status structure to be freed.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called during task creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+void task_freechild(FAR struct child_status_s *child)
+{
+ /* Return the child status structure to the free list */
+
+ if (child)
+ {
+ child->flink = g_child_pool.freelist;
+ g_child_pool.freelist = child;
+ }
+}
+
+/*****************************************************************************
+ * Name: task_addchild
+ *
+ * Description:
+ * Add a child status structure in the given TCB.
+ *
+ * Parameters:
+ * tcb - The TCB of the parent task to containing the child status.
+ * child - The structure to be added
+ *
+ * Return Value:
+ * N
+ *
+ * Assumptions:
+ * Called during task creation processing in a safe context. No special
+ * precautions are required here.
+ *
+ *****************************************************************************/
+
+void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
+{
+ /* Add the entry into the TCB list of children */
+
+ child->flink = tcb->children;
+ tcb->children = child;
+
+ task_dumpchildren(tcb, "task_addchild");
+}
+
+/*****************************************************************************
+ * Name: task_findchild
+ *
+ * Description:
+ * Find a child status structure in the given TCB. A reference to the
+ * child structure is returned, but the child remains the the TCB's list
+ * of children.
+ *
+ * Parameters:
+ * tcb - The TCB of the parent task to containing the child status.
+ * pid - The ID of the child to find.
+ *
+ * Return Value:
+ * On success, a non-NULL pointer to a child status structure. NULL is
+ * returned if there is child status structure for that pid in the TCB.
+ *
+ * Assumptions:
+ * Called during SIGCHLD processing in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
+{
+ FAR struct child_status_s *child;
+
+ /* Find the status structure with the matching PID */
+
+ for (child = tcb->children; child; child = child->flink)
+ {
+ if (child->ch_pid == pid)
+ {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * Name: task_removechild
+ *
+ * Description:
+ * Remove one child structure from the TCB. The child is removed, but is
+ * not yet freed. task_freechild must be called in order to free the child
+ * status structure.
+ *
+ * Parameters:
+ * tcb - The TCB of the parent task to containing the child status.
+ * pid - The ID of the child to find.
+ *
+ * Return Value:
+ * On success, a non-NULL pointer to a child status structure. NULL is
+ * returned if there is child status structure for that pid in the TCB.
+ *
+ * Assumptions:
+ * Called during SIGCHLD processing in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
+{
+ FAR struct child_status_s *curr;
+ FAR struct child_status_s *prev;
+
+ /* Find the status structure with the matching PID */
+
+ for (prev = NULL, curr = tcb->children;
+ curr;
+ prev = curr, curr = curr->flink)
+ {
+ if (curr->ch_pid == pid)
+ {
+ break;
+ }
+ }
+
+ /* Did we find it? If so, remove it from the TCB. */
+
+ if (curr)
+ {
+ /* Do we remove it from mid-list? Or from the head of the list? */
+
+ if (prev)
+ {
+ prev->flink = curr->flink;
+ }
+ else
+ {
+ tcb->children = curr->flink;
+ }
+
+ curr->flink = NULL;
+ task_dumpchildren(tcb, "task_removechild");
+ }
+
+ return curr;
+}
+
+/*****************************************************************************
+ * Name: task_removechildren
+ *
+ * Description:
+ * Remove and free all child structure from the TCB.
+ *
+ * Parameters:
+ * tcb - The TCB of the parent task to containing the child status.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called during task exit processing in a safe context. No special
+ * precautions are required here.
+ *
+ *****************************************************************************/
+
+void task_removechildren(FAR _TCB *tcb)
+{
+ FAR struct child_status_s *curr;
+ FAR struct child_status_s *next;
+
+ /* Remove all child structures for the TCB and return them to the freelist */
+
+ for (curr = tcb->children; curr; curr = next)
+ {
+ next = curr->flink;
+ task_freechild(curr);
+ }
+
+ tcb->children = NULL;
+ task_dumpchildren(tcb, "task_removechildren");
+}
+
+#endif /* CONFIG_SCHED_HAVE_PARENT && CONFIG_SCHED_CHILD_STATUS */
diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c
index 4d92c9bb0..2ed929ab0 100644
--- a/nuttx/sched/task_create.c
+++ b/nuttx/sched/task_create.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_create.c
*
- * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,7 @@
*
* Input Parameters:
* name - Name of the new task
- * type - Type of the new task
+ * ttype - Type of the new task
* priority - Priority of the new task
* stack_size - size (in bytes) of the stack needed
* entry - Entry point of a new task
@@ -99,10 +99,10 @@
****************************************************************************/
#ifndef CONFIG_CUSTOM_STACK
-static int thread_create(const char *name, uint8_t type, int priority,
+static int thread_create(const char *name, uint8_t ttype, int priority,
int stack_size, main_t entry, const char **argv)
#else
-static int thread_create(const char *name, uint8_t type, int priority,
+static int thread_create(const char *name, uint8_t ttype, int priority,
main_t entry, const char **argv)
#endif
{
@@ -142,15 +142,9 @@ static int thread_create(const char *name, uint8_t type, int priority,
}
#endif
- /* Mark the type of this thread (this setting will be needed in
- * task_schedsetup() when up_initial_state() is called.
- */
-
- tcb->flags |= type;
-
/* Initialize the task control block */
- ret = task_schedsetup(tcb, priority, task_start, entry);
+ ret = task_schedsetup(tcb, priority, task_start, entry, ttype);
if (ret != OK)
{
goto errout_with_tcb;
@@ -169,6 +163,8 @@ static int thread_create(const char *name, uint8_t type, int priority,
ret = task_activate(tcb);
if (ret != OK)
{
+ /* The TCB was added to the active task list by task_schedsetup() */
+
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
goto errout_with_tcb;
}
diff --git a/nuttx/sched/task_deletecurrent.c b/nuttx/sched/task_deletecurrent.c
index 77025f5e0..e1e06acf6 100644
--- a/nuttx/sched/task_deletecurrent.c
+++ b/nuttx/sched/task_deletecurrent.c
@@ -90,6 +90,9 @@
* Return Value:
* OK on success; or ERROR on failure
*
+ * Assumeptions:
+ * Interrupts are disabled.
+ *
****************************************************************************/
int task_deletecurrent(void)
@@ -108,13 +111,16 @@ int task_deletecurrent(void)
(void)sched_removereadytorun(dtcb);
rtcb = (FAR _TCB*)g_readytorun.head;
- /* We are not in a bad state -- the head of the ready to run task list
+ /* We are now in a bad state -- the head of the ready to run task list
* does not correspond to the thread that is running. Disabling pre-
* emption on this TCB and marking the new ready-to-run task as not
* running (see, for example, get_errno_ptr()).
+ *
+ * We disable pre-emption here by directly incrementing the lockcount
+ * (vs. calling sched_lock()).
*/
- sched_lock();
+ rtcb->lockcount++;
rtcb->task_state = TSTATE_TASK_READYTORUN;
/* Move the TCB to the specified blocked task list and delete it */
@@ -132,9 +138,15 @@ int task_deletecurrent(void)
(void)sched_mergepending();
}
- /* Now calling sched_unlock() should have no effect */
+ /* We can't use sched_unlock() to decrement the lock count because the
+ * sched_mergepending() call above might have changed the task at the
+ * head of the ready-to-run list. Furthermore, we should not need to
+ * perform the unlock action anyway because we know that the pending
+ * task list is empty. So all we really need to do is to decrement
+ * the lockcount on rctb.
+ */
- sched_unlock();
+ rtcb->lockcount--;
return OK;
}
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c
index 3bde8fb7a..1813c12ed 100644
--- a/nuttx/sched/task_exithook.c
+++ b/nuttx/sched/task_exithook.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_exithook.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include <signal.h>
#include <debug.h>
#include <errno.h>
@@ -188,6 +189,105 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
#endif
/****************************************************************************
+ * Name: task_sigchild
+ *
+ * Description:
+ * Send the SIGCHILD signal to the parent thread
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_sigchild(FAR _TCB *tcb, int status)
+{
+ FAR _TCB *ptcb;
+ siginfo_t info;
+
+ /* Only exiting tasks should generate SIGCHLD. pthreads use other
+ * mechansims.
+ */
+
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+ {
+ /* Keep things stationary through the following */
+
+ sched_lock();
+
+ /* Get the TCB of the receiving task */
+
+ ptcb = sched_gettcb(tcb->parent);
+ if (!ptcb)
+ {
+ /* The parent no longer exists... bail */
+
+ sched_unlock();
+ return;
+ }
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Check if the parent task has suppressed retention of child exit
+ * status information. Only 'tasks' report exit status, not pthreads.
+ * pthreads have a different mechanism.
+ */
+
+ if ((ptcb->flags & TCB_FLAG_NOCLDWAIT) == 0)
+ {
+ FAR struct child_status_s *child;
+
+ /* No.. Find the exit status entry for this task in the parent TCB */
+
+ child = task_findchild(ptcb, getpid());
+ DEBUGASSERT(child);
+ if (child)
+ {
+ /* Mark that the child has exit'ed */
+
+ child->ch_flags |= CHILD_FLAG_EXITED;
+
+ /* Save the exit status */
+
+ child->ch_status = status;
+ }
+ }
+#else
+ /* Decrement the number of children from this parent */
+
+ DEBUGASSERT(ptcb->nchildren > 0);
+ ptcb->nchildren--;
+#endif
+
+ /* Set the parent to an impossible PID. We do this because under
+ * certain conditions, task_exithook() can be called multiple times.
+ * If this function is called again, sched_gettcb() will fail on the
+ * invalid parent PID above, nchildren will be decremented once and
+ * all will be well.
+ */
+
+ tcb->parent = INVALID_PROCESS_ID;
+
+ /* Create the siginfo structure. We don't actually know the cause.
+ * That is a bug. Let's just say that the child task just exit-ted
+ * for now.
+ */
+
+ info.si_signo = SIGCHLD;
+ info.si_code = CLD_EXITED;
+ info.si_value.sival_ptr = NULL;
+ info.si_pid = tcb->pid;
+ info.si_status = status;
+
+ /* Send the signal. We need to use this internal interface so that we
+ * can provide the correct si_code value with the signal.
+ */
+
+ (void)sig_received(ptcb, &info);
+ sched_unlock();
+ }
+}
+#else
+# define task_sigchild(tcb,status)
+#endif
+
+/****************************************************************************
* Name: task_exitwakeup
*
* Description:
@@ -195,7 +295,7 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
*
****************************************************************************/
-#ifdef CONFIG_SCHED_WAITPID
+#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
static inline void task_exitwakeup(FAR _TCB *tcb, int status)
{
/* Wakeup any tasks waiting for this task to exit */
@@ -263,6 +363,10 @@ void task_exithook(FAR _TCB *tcb, int status)
task_onexit(tcb, status);
+ /* Send SIGCHLD to the parent of the exit-ing task */
+
+ task_sigchild(tcb, status);
+
/* Wakeup any tasks waiting for this task to exit */
task_exitwakeup(tcb, status);
@@ -275,6 +379,12 @@ void task_exithook(FAR _TCB *tcb, int status)
(void)lib_flushall(tcb->streams);
#endif
+ /* Discard any un-reaped child status (no zombies here!) */
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+ task_removechildren(tcb);
+#endif
+
/* Free all file-related resources now. This gets called again
* just be be certain when the TCB is delallocated. However, we
* really need to close files as soon as possible while we still
diff --git a/nuttx/sched/task_init.c b/nuttx/sched/task_init.c
index 31fc5ef70..0f0fdc68e 100644
--- a/nuttx/sched/task_init.c
+++ b/nuttx/sched/task_init.c
@@ -141,7 +141,8 @@ int task_init(FAR _TCB *tcb, const char *name, int priority,
/* Initialize the task control block */
- ret = task_schedsetup(tcb, priority, task_start, entry);
+ ret = task_schedsetup(tcb, priority, task_start, entry,
+ TCB_FLAG_TTYPE_TASK);
if (ret == OK)
{
/* Setup to pass parameters to the new task */
diff --git a/nuttx/sched/task_posixspawn.c b/nuttx/sched/task_posixspawn.c
new file mode 100644
index 000000000..7bb9c9a4d
--- /dev/null
+++ b/nuttx/sched/task_posixspawn.c
@@ -0,0 +1,674 @@
+/****************************************************************************
+ * sched/task_posixspawn.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/binfmt.h>
+#include <nuttx/spawn.h>
+
+#include "os_internal.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct spawn_parms_s
+{
+ int result;
+ FAR pid_t *pid;
+ FAR const char *path;
+ FAR const posix_spawn_file_actions_t *file_actions;
+ FAR const posix_spawnattr_t *attr;
+ FAR char *const *argv;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_ps_parmsem = SEM_INITIALIZER(1);
+#ifndef CONFIG_SCHED_WAITPID
+static sem_t g_ps_execsem = SEM_INITIALIZER(0);
+#endif
+static struct spawn_parms_s g_ps_parms;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spawn_semtake and spawn_semgive
+ *
+ * Description:
+ * Give and take semaphores
+ *
+ * Input Parameters:
+ *
+ * sem - The semaphore to act on.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void spawn_semtake(FAR sem_t *sem)
+{
+ int ret;
+
+ do
+ {
+ ret = sem_wait(sem);
+ ASSERT(ret == 0 || errno == EINTR);
+ }
+ while (ret != 0);
+}
+
+#define spawn_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: spawn_exec
+ *
+ * Description:
+ * Execute the task from the file system.
+ *
+ * Input Parameters:
+ *
+ * pidp - Upon successful completion, this will return the task ID of the
+ * child task in the variable pointed to by a non-NULL 'pid' argument.|
+ *
+ * path - The 'path' argument identifies the file to execute. If
+ * CONFIG_BINFMT_EXEPATH is defined, this may be either a relative or
+ * or an absolute path. Otherwise, it must be an absolute path.
+ *
+ * attr - If the value of the 'attr' parameter is NULL, the all default
+ * values for the POSIX spawn attributes will be used. Otherwise, the
+ * attributes will be set according to the spawn flags. The
+ * following spawn flags are supported:
+ *
+ * - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
+ * value.
+ * - POSIX_SPAWN_SETSCHEDULER: Set the new tasks scheduler priority to
+ * the sched_policy value.
+ *
+ * NOTE: POSIX_SPAWN_SETSIGMASK is handled in ps_proxy().
+ *
+ * argv - argv[] is the argument list for the new task. argv[] is an
+ * array of pointers to null-terminated strings. The list is terminated
+ * with a null pointer.
+ *
+ * Returned Value:
+ * This function will return zero on success. Otherwise, an error number
+ * will be returned as the function return value to indicate the error.
+ * This errno value may be that set by execv(), sched_setpolicy(), or
+ * sched_setparam().
+ *
+ ****************************************************************************/
+
+static int spawn_exec(FAR pid_t *pidp, FAR const char *path,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[])
+{
+ struct sched_param param;
+ FAR const struct symtab_s *symtab;
+ int nsymbols;
+ int pid;
+ int ret = OK;
+
+ DEBUGASSERT(path);
+
+ /* Get the current symbol table selection */
+
+ exec_getsymtab(&symtab, &nsymbols);
+
+ /* Disable pre-emption so that we can modify the task parameters after
+ * we start the new task; the new task will not actually begin execution
+ * until we re-enable pre-emption.
+ */
+
+ sched_lock();
+
+ /* Start the task */
+
+ pid = exec(path, (FAR const char **)argv, symtab, nsymbols);
+ if (pid < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: exec failed: %d\n", ret);
+ goto errout;
+ }
+
+ /* Return the task ID to the caller */
+
+ if (pid)
+ {
+ *pidp = pid;
+ }
+
+ /* Now set the attributes. Note that we ignore all of the return values
+ * here because we have already successfully started the task. If we
+ * return an error value, then we would also have to stop the task.
+ */
+
+ if (attr)
+ {
+ /* If we are only setting the priority, then call sched_setparm()
+ * to set the priority of the of the new task.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
+ {
+ /* Get the priority from the attrributes */
+
+ param.sched_priority = attr->priority;
+
+ /* If we are setting *both* the priority and the scheduler,
+ * then we will call sched_setscheduler() below.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) == 0)
+ {
+ svdbg("Setting priority=%d for pid=%d\n",
+ param.sched_priority, pid);
+
+ (void)sched_setparam(pid, &param);
+ }
+ }
+
+ /* If we are only changing the scheduling policy, then reset
+ * the priority to the default value (the same as this thread) in
+ * preparation for the sched_setscheduler() call below.
+ */
+
+ else if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ (void)sched_getparam(0, &param);
+ }
+
+ /* Are we setting the scheduling policy? If so, use the priority
+ * setting determined above.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ svdbg("Setting policy=%d priority=%d for pid=%d\n",
+ attr->policy, param.sched_priority, pid);
+
+ (void)sched_setscheduler(pid, attr->policy, &param);
+ }
+ }
+
+ /* Re-enable pre-emption and return */
+
+errout:
+ sched_unlock();
+ return ret;
+}
+
+/****************************************************************************
+ * Name: spawn_close, spawn_dup2, and spawn_open
+ *
+ * Description:
+ * Implement individual file actions
+ *
+ * Input Parameters:
+ * action - describes the action to be performed
+ *
+ * Returned Value:
+ * posix_spawn() and posix_spawnp() will return zero on success.
+ * Otherwise, an error number will be returned as the function return
+ * value to indicate the error.
+ *
+ ****************************************************************************/
+
+static inline int spawn_close(FAR struct spawn_close_file_action_s *action)
+{
+ /* The return value from close() is ignored */
+
+ svdbg("Closing fd=%d\n", action->fd);
+
+ (void)close(action->fd);
+ return OK;
+}
+
+static inline int spawn_dup2(FAR struct spawn_dup2_file_action_s *action)
+{
+ int ret;
+
+ /* Perform the dup */
+
+ svdbg("Dup'ing %d->%d\n", action->fd1, action->fd2);
+
+ ret = dup2(action->fd1, action->fd2);
+ if (ret < 0)
+ {
+ int errcode = errno;
+
+ sdbg("ERROR: dup2 failed: %d\n", errcode);
+ return errcode;
+ }
+
+ return OK;
+}
+
+static inline int spawn_open(FAR struct spawn_open_file_action_s *action)
+{
+ int fd;
+ int ret = OK;
+
+ /* Open the file */
+
+ svdbg("Open'ing path=%s oflags=%04x mode=%04x\n",
+ action->path, action->oflags, action->mode);
+
+ fd = open(action->path, action->oflags, action->mode);
+ if (fd < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: open failed: %d\n", ret);
+ }
+
+ /* Does the return file descriptor happen to match the required file
+ * desciptor number?
+ */
+
+ else if (fd != action->fd)
+ {
+ /* No.. dup2 to get the correct file number */
+
+ svdbg("Dup'ing %d->%d\n", fd, action->fd);
+
+ ret = dup2(fd, action->fd);
+ if (ret < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: dup2 failed: %d\n", ret);
+ }
+
+ svdbg("Closing fd=%d\n", fd);
+ close(fd);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: spawn_proxy
+ *
+ * Description:
+ * Perform file_actions, then execute the task from the file system.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * Standard task return value.
+ *
+ ****************************************************************************/
+
+static int spawn_proxy(int argc, char *argv[])
+{
+ FAR struct spawn_general_file_action_s *entry;
+ FAR const posix_spawnattr_t *attr = g_ps_parms.attr;
+ int ret = OK;
+
+ /* Perform file actions and/or set a custom signal mask. We get here only
+ * if the file_actions parameter to posix_spawn[p] was non-NULL and/or the
+ * option to change the signal mask was selected.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ DEBUGASSERT((g_ps_parms.file_actions && *g_ps_parms.file_actions) ||
+ (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0));
+#else
+ DEBUGASSERT(g_ps_parms.file_actions && *g_ps_parms.file_actions);
+#endif
+
+ /* Check if we need to change the signal mask */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
+ {
+ (void)sigprocmask(SIG_SETMASK, &attr->sigmask, NULL);
+ }
+
+ /* Were we also requested to perform file actions? */
+
+ if (g_ps_parms.file_actions)
+#endif
+ {
+ /* Execute each file action */
+
+ for (entry = (FAR struct spawn_general_file_action_s *)*g_ps_parms.file_actions;
+ entry && ret == OK;
+ entry = entry->flink)
+ {
+ switch (entry->action)
+ {
+ case SPAWN_FILE_ACTION_CLOSE:
+ ret = spawn_close((FAR struct spawn_close_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_DUP2:
+ ret = spawn_dup2((FAR struct spawn_dup2_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_OPEN:
+ ret = spawn_open((FAR struct spawn_open_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_NONE:
+ default:
+ sdbg("ERROR: Unknown action: %d\n", entry->action);
+ ret = EINVAL;
+ break;
+ }
+ }
+ }
+
+ /* Check for failures */
+
+ if (ret == OK)
+ {
+ /* Start the task */
+
+ ret = spawn_exec(g_ps_parms.pid, g_ps_parms.path, attr,
+ g_ps_parms.argv);
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ if (ret == OK)
+ {
+ /* Change of the parent of the task we just spawned to our parent.
+ * What should we do in the event of a failure?
+ */
+
+ int tmp = task_reparent(0, *g_ps_parms.pid);
+ if (tmp < 0)
+ {
+ sdbg("ERROR: task_reparent() failed: %d\n", tmp);
+ }
+ }
+#endif
+ }
+
+ /* Post the semaphore to inform the parent task that we have completed
+ * what we need to do.
+ */
+
+ g_ps_parms.result = ret;
+#ifndef CONFIG_SCHED_WAITPID
+ spawn_semgive(&g_ps_execsem);
+#endif
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn
+ *
+ * Description:
+ * The posix_spawn() and posix_spawnp() functions will create a new,
+ * child task, constructed from a regular executable file.
+ *
+ * Input Parameters:
+ *
+ * pid - Upon successful completion, posix_spawn() and posix_spawnp() will
+ * return the task ID of the child task to the parent task, in the
+ * variable pointed to by a non-NULL 'pid' argument. If the 'pid'
+ * argument is a null pointer, the process ID of the child is not
+ * returned to the caller.
+ *
+ * path - The 'path' argument to posix_spawn() is the absolute path that
+ * identifies the file to execute. The 'path' argument to posix_spawnp()
+ * may also be a relative path and will be used to construct a pathname
+ * that identifies the file to execute. In the case of a relative path,
+ * the path prefix for the file will be obtained by a search of the
+ * directories passed as the environment variable PATH.
+ *
+ * NOTE: NuttX provides only one implementation: If
+ * CONFIG_BINFMT_EXEPATH is defined, then only posix_spawnp() behavior
+ * is supported; otherwise, only posix_spawn behavior is supported.
+ *
+ * file_actions - If 'file_actions' is a null pointer, then file
+ * descriptors open in the calling process will remain open in the
+ * child process (unless CONFIG_FDCLONE_STDIO is defined). If
+ * 'file_actions' is not NULL, then the file descriptors open in the
+ * child process will be those open in the calling process as modified
+ * by the spawn file actions object pointed to by file_actions.
+ *
+ * attr - If the value of the 'attr' parameter is NULL, the all default
+ * values for the POSIX spawn attributes will be used. Otherwise, the
+ * attributes will be set according to the spawn flags. The
+ * posix_spawnattr_t spawn attributes object type is defined in spawn.h.
+ * It will contains these attributes, not all of which are supported by
+ * NuttX:
+ *
+ * - POSIX_SPAWN_SETPGROUP: Setting of the new task's process group is
+ * not supported. NuttX does not support process groups.
+ * - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
+ * value.
+ * - POSIX_SPAWN_SETSCHEDULER: Set the new task's scheduler policy to
+ * the sched_policy value.
+ * - POSIX_SPAWN_RESETIDS: Resetting of the effective user ID of the child
+ * process is not supported. NuttX does not support effective user
+ * IDs.
+ * - POSIX_SPAWN_SETSIGMASK: Set the new task's signal mask.
+ * - POSIX_SPAWN_SETSIGDEF: Resetting signal default actions is not
+ * supported. NuttX does not support default signal actions.
+ *
+ * argv - argv[] is the argument list for the new task. argv[] is an
+ * array of pointers to null-terminated strings. The list is terminated
+ * with a null pointer.
+ *
+ * envp - The envp[] argument is not used by NuttX and may be NULL. In
+ * standard implementations, envp[] is an array of character pointers to
+ * null-terminated strings that provide the environment for the new
+ * process image. The environment array is terminated by a null pointer.
+ * In NuttX, the envp[] argument is ignored and the new task will simply
+ * inherit the environment of the parent task.
+ *
+ * Returned Value:
+ * posix_spawn() and posix_spawnp() will return zero on success.
+ * Otherwise, an error number will be returned as the function return
+ * value to indicate the error:
+ *
+ * - EINVAL: The value specified by 'file_actions' or 'attr' is invalid.
+ * - Any errors that might have been return if vfork() and excec[l|v]()
+ * had been called.
+ *
+ * Assumptions/Limitations:
+ * - NuttX provides only posix_spawn() or posix_spawnp() behavior
+ * depending upon the setting of CONFIG_BINFMT_EXEPATH: If
+ * CONFIG_BINFMT_EXEPATH is defined, then only posix_spawnp() behavior
+ * is supported; otherwise, only posix_spawn behavior is supported.
+ * - The 'envp' argument is not used and the 'environ' variable is not
+ * altered (NuttX does not support the 'environ' variable).
+ * - Process groups are not supported (POSIX_SPAWN_SETPGROUP).
+ * - Effective user IDs are not supported (POSIX_SPAWN_RESETIDS).
+ * - Signal default actions cannot be modified in the newly task executed
+ * because NuttX does not support default signal actions
+ * (POSIX_SPAWN_SETSIGDEF).
+ *
+ * POSIX Compatibility
+ * - The value of the argv[0] received by the child task is assigned by
+ * NuttX. For the caller of posix_spawn(), the provided argv[0] will
+ * correspond to argv[1] received by the new task.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BINFMT_EXEPATH
+int posix_spawnp(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[])
+#else
+int posix_spawn(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[])
+#endif
+{
+ struct sched_param param;
+ pid_t proxy;
+#ifdef CONFIG_SCHED_WAITPID
+ int status;
+#endif
+ int ret;
+
+ DEBUGASSERT(path);
+
+ svdbg("pid=%p path=%s file_actions=%p attr=%p argv=%p\n",
+ pid, path, file_actions, attr, argv);
+
+ /* If there are no file actions to be performed and there is no change to
+ * the signal mask, then start the new child task directly from the parent task.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if ((file_actions == NULL || *file_actions == NULL) &&
+ (attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0))
+#else
+ if (file_actions == NULL || *file_actions == NULL)
+#endif
+ {
+ return spawn_exec(pid, path, attr, argv);
+ }
+
+ /* Otherwise, we will have to go through an intermediary/proxy task in order
+ * to perform the I/O redirection. This would be a natural place to fork().
+ * However, true fork() behavior requires an MMU and most implementations
+ * of vfork() are not capable of these operations.
+ *
+ * Even without fork(), we can still do the job, but parameter passing is
+ * messier. Unfortunately, there is no (clean) way to pass binary values
+ * as a task parameter, so we will use a semaphore-protected global
+ * structure.
+ */
+
+ /* Get exclusive access to the global parameter structure */
+
+ spawn_semtake(&g_ps_parmsem);
+
+ /* Populate the parameter structure */
+
+ g_ps_parms.result = ENOSYS;
+ g_ps_parms.pid = pid;
+ g_ps_parms.path = path;
+ g_ps_parms.file_actions = file_actions;
+ g_ps_parms.attr = attr;
+ g_ps_parms.argv = argv;
+
+ /* Get the priority of this (parent) task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ int errcode = errno;
+
+ sdbg("ERROR: sched_getparam failed: %d\n", errcode);
+ spawn_semgive(&g_ps_parmsem);
+ return errcode;
+ }
+
+ /* Disable pre-emption so that the proxy does not run until we waitpid
+ * is called. This is probably unnecessary since the spawn_proxy has
+ * the same priority as this thread; it should be schedule behind this
+ * task in the ready-to-run list.
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ sched_lock();
+#endif
+
+ /* Start the intermediary/proxy task at the same priority as the parent
+ * task.
+ */
+
+ proxy = TASK_CREATE("spawn_proxy", param.sched_priority,
+ CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy,
+ (FAR const char **)NULL);
+ if (proxy < 0)
+ {
+ ret = get_errno();
+ sdbg("ERROR: Failed to start spawn_proxy: %d\n", ret);
+
+ goto errout_with_lock;
+ }
+
+ /* Wait for the proxy to complete its job */
+
+#ifdef CONFIG_SCHED_WAITPID
+ ret = waitpid(proxy, &status, 0);
+ if (ret < 0)
+ {
+ sdbg("ERROR: waitpid() failed: %d\n", errno);
+ goto errout_with_lock;
+ }
+#else
+ spawn_semtake(&g_ps_execsem);
+#endif
+
+ /* Get the result and relinquish our access to the parameter structure */
+
+ ret = g_ps_parms.result;
+
+errout_with_lock:
+#ifdef CONFIG_SCHED_WAITPID
+ sched_unlock();
+#endif
+ spawn_semgive(&g_ps_parmsem);
+ return ret;
+}
diff --git a/nuttx/sched/task_reparent.c b/nuttx/sched/task_reparent.c
new file mode 100644
index 000000000..28d371bf1
--- /dev/null
+++ b/nuttx/sched/task_reparent.c
@@ -0,0 +1,163 @@
+/*****************************************************************************
+ * sched/task_reparent.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+
+#include "os_internal.h"
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: task_reparent
+ *
+ * Description:
+ * Change the parent of a task.
+ *
+ * Parameters:
+ * ppid - PID of the new parent task (0 for grandparent, i.e. the parent
+ * of the current parent task)
+ * chpid - PID of the child to be reparented.
+ *
+ * Return Value:
+ * 0 (OK) on success; A negated errno value on failure.
+ *
+ *****************************************************************************/
+
+int task_reparent(pid_t ppid, pid_t chpid)
+{
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ FAR struct child_status_s *child;
+#endif
+ _TCB *ptcb;
+ _TCB *chtcb;
+ _TCB *otcb;
+ pid_t opid;
+ irqstate_t flags;
+ int ret;
+
+ /* Disable interrupts so that nothing can change in the relatinoship of
+ * the three task: Child, current parent, and new parent.
+ */
+
+ flags = irqsave();
+
+ /* Get the child tasks TCB (chtcb) */
+
+ chtcb = sched_gettcb(chpid);
+ if (!chtcb)
+ {
+ ret = -ECHILD;
+ goto errout_with_ints;
+ }
+
+ /* Get the PID of the child task's parent (opid) */
+
+ opid = chtcb->parent;
+
+ /* Get the TCB of the child task's parent (otcb) */
+
+ otcb = sched_gettcb(opid);
+ if (!otcb)
+ {
+ ret = -ESRCH;
+ goto errout_with_ints;
+ }
+
+ /* If new parent task's PID (ppid) is zero, then new parent is the
+ * grandparent will be the new parent, i.e., the parent of the current
+ * parent task.
+ */
+
+ if (ppid == 0)
+ {
+ ppid = otcb->parent;
+ }
+
+ /* Get the new parent task's TCB (ptcb) */
+
+ ptcb = sched_gettcb(ppid);
+ if (!ptcb)
+ {
+ ret = -ESRCH;
+ goto errout_with_ints;
+ }
+
+ /* Then reparent the child */
+
+ chtcb->parent = ppid; /* The task specified by ppid is the new parent */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Remove the child status entry from old parent TCB */
+
+ child = task_removechild(otcb, chpid);
+ if (child)
+ {
+ /* Add the child status entry to the new parent TCB */
+
+ task_addchild(ptcb, child);
+ ret = OK;
+ }
+ else
+ {
+ ret = -ENOENT;
+ }
+#else
+ DEBUGASSERT(otcb->nchildren > 0);
+
+ otcb->nchildren--; /* The orignal parent now has one few children */
+ ptcb->nchildren++; /* The new parent has one additional child */
+ ret = OK;
+#endif
+
+errout_with_ints:
+ irqrestore(flags);
+ return ret;
+}
+
+#endif /* CONFIG_SCHED_HAVE_PARENT */
diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c
index a37fb165a..43ed24b32 100644
--- a/nuttx/sched/task_setup.c
+++ b/nuttx/sched/task_setup.c
@@ -147,6 +147,82 @@ static int task_assignpid(FAR _TCB *tcb)
}
/****************************************************************************
+ * Name: task_saveparent
+ *
+ * Description:
+ * Save the task ID of the parent task in the child task's TCB.
+ *
+ * Parameters:
+ * tcb - The TCB of the new, child task.
+ * ttype - Type of the new thread: task, pthread, or kernel thread
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The parent of the new task is the task at the head of the ready-to-run
+ * list.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_saveparent(FAR _TCB *tcb, uint8_t ttype)
+{
+ FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+
+ /* Save the parent task's ID in the child task's TCB. I am not sure if
+ * this makes sense for the case of pthreads or not, but I don't think it
+ * is harmful in any event.
+ */
+
+ tcb->parent = rtcb->pid;
+
+ /* Exit status only needs to be retained for the case of tasks, however */
+
+ if (ttype == TCB_FLAG_TTYPE_TASK)
+ {
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ FAR struct child_status_s *child;
+
+ /* Make sure that there is not already a structure for this PID in the
+ * parent TCB. There should not be.
+ */
+
+ child = task_findchild(rtcb, tcb->pid);
+ DEBUGASSERT(!child);
+ if (!child)
+ {
+ /* Allocate a new status structure */
+
+ child = task_allocchild();
+ }
+
+ /* Did we successfully find/allocate the child status structure? */
+
+ DEBUGASSERT(child);
+ if (child)
+ {
+ /* Yes.. Initialize the structure */
+
+ child->ch_flags = ttype;
+ child->ch_pid = tcb->pid;
+ child->ch_status = 0;
+
+ /* Add the entry into the TCB list of children */
+
+ task_addchild(rtcb, child);
+ }
+#else
+ DEBUGASSERT(rtcb->nchildren < UINT16_MAX);
+ rtcb->nchildren++;
+#endif
+ }
+}
+#else
+# define task_saveparent(tcb, type)
+#endif
+
+/****************************************************************************
* Name: task_dupdspace
*
* Description:
@@ -161,6 +237,8 @@ static int task_assignpid(FAR _TCB *tcb)
* None
*
* Assumptions:
+ * The parent of the new task is the task at the head of the ready-to-run
+ * list.
*
****************************************************************************/
@@ -202,7 +280,7 @@ static inline void task_dupdspace(FAR _TCB *tcb)
* priority - Priority of the new task
* entry - Entry point of a new task
* main - Application start point of the new task
- * type - Type of the new thread: task, pthread, or kernel thread
+ * ttype - Type of the new thread: task, pthread, or kernel thread
*
* Return Value:
* OK on success; ERROR on failure.
@@ -212,7 +290,8 @@ static inline void task_dupdspace(FAR _TCB *tcb)
*
****************************************************************************/
-int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main)
+int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main,
+ uint8_t ttype)
{
int ret;
@@ -231,8 +310,20 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main)
tcb->start = start;
tcb->entry.main = main;
- /* exec() and pthread_create() inherit the signal mask of the
- * parent thread. I suppose that task_create() should as well.
+ /* Save the thrad type. This setting will be needed in
+ * up_initial_state() is called.
+ */
+
+ ttype &= TCB_FLAG_TTYPE_MASK;
+ tcb->flags &= ~TCB_FLAG_TTYPE_MASK;
+ tcb->flags |= ttype;
+
+ /* Save the task ID of the parent task in the TCB */
+
+ task_saveparent(tcb, ttype);
+
+ /* exec(), pthread_create(), task_create(), and vfork() all
+ * inherit the signal mask of the parent thread.
*/
#ifndef CONFIG_DISABLE_SIGNALS
@@ -243,7 +334,7 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main)
* until it is activated.
*/
- tcb->task_state = TSTATE_TASK_INVALID;
+ tcb->task_state = TSTATE_TASK_INVALID;
/* Clone the parent tasks D-Space (if it was running PIC). This
* must be done before calling up_initial_state() so that the
diff --git a/nuttx/sched/task_vfork.c b/nuttx/sched/task_vfork.c
new file mode 100644
index 000000000..fece4c596
--- /dev/null
+++ b/nuttx/sched/task_vfork.c
@@ -0,0 +1,333 @@
+/****************************************************************************
+ * sched/task_vfork
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <queue.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+#include "env_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: task_vforksetup
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * This functin provides one step in the overall vfork() sequence: It
+ * Allocates and initializes the child task's TCB. The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() is provided in architecture-specific
+ * code.
+ * 2) vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * retaddr - The return address from vfork() where the child task
+ * will be started.
+ *
+ * Returned Value:
+ * Upon successful completion, task_vforksetup() returns a pointer to
+ * newly allocated and initalized child task's TCB. NULL is returned
+ * on any failure and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+FAR _TCB *task_vforksetup(start_t retaddr)
+{
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+ _TCB *child;
+ int priority;
+ int ret;
+
+ DEBUGASSERT(retaddr);
+
+ /* Allocate a TCB for the child task. */
+
+ child = (FAR _TCB*)kzalloc(sizeof(_TCB));
+ if (!child)
+ {
+ set_errno(ENOMEM);
+ return NULL;
+ }
+
+ /* Associate file descriptors with the new task */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+ ret = sched_setuptaskfiles(child);
+ if (ret != OK)
+ {
+ goto errout_with_tcb;
+ }
+#endif
+
+ /* Clone the parent's task environment */
+
+ (void)env_dup(child);
+
+ /* Get the priority of the parent task */
+
+#ifdef CONFIG_PRIORITY_INHERITANCE
+ priority = parent->base_priority; /* "Normal," unboosted priority */
+#else
+ priority = parent->sched_priority; /* Current priority */
+#endif
+
+ /* Initialize the task control block. This calls up_initial_state() */
+
+ svdbg("Child priority=%d start=%p\n", priority, retaddr);
+ ret = task_schedsetup(child, priority, retaddr, parent->entry.main,
+ TCB_FLAG_TTYPE_TASK);
+ if (ret != OK)
+ {
+ goto errout_with_tcb;
+ }
+
+ svdbg("parent=%p, returning child=%p\n", parent, child);
+ return child;
+
+errout_with_tcb:
+ sched_releasetcb(child);
+ set_errno(-ret);
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: task_vforkstart
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * This functin provides one step in the overall vfork() sequence: It
+ * starts execution of the previously initialized TCB. The overall
+ * sequence is:
+ *
+ * 1) User code calls vfork()
+ * 2) Architecture-specific code provides vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) vfork() provides any additional operating context. vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * retaddr - The return address from vfork() where the child task
+ * will be started.
+ *
+ * Returned Value:
+ * Upon successful completion, vfork() returns 0 to the child process and
+ * returns the process ID of the child process to the parent process.
+ * Otherwise, -1 is returned to the parent, no child process is created,
+ * and errno is set to indicate the error.
+ *
+ ****************************************************************************/
+
+pid_t task_vforkstart(FAR _TCB *child)
+{
+#if CONFIG_TASK_NAME_SIZE > 0
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+#endif
+ FAR const char *name;
+ pid_t pid;
+#ifdef CONFIG_SCHED_WAITPID
+ int rc;
+#endif
+ int ret;
+
+ svdbg("Starting Child TCB=%p, parent=%p\n", child, g_readytorun.head);
+ DEBUGASSERT(child);
+
+ /* Setup to pass parameters to the new task */
+
+#if CONFIG_TASK_NAME_SIZE > 0
+ name = parent->name;
+#else
+ name = NULL;
+#endif
+
+ (void)task_argsetup(child, name, (const char **)NULL);
+
+ /* Get the assigned pid before we start the task */
+
+ pid = (int)child->pid;
+
+ /* Activate the task */
+
+ ret = task_activate(child);
+ if (ret != OK)
+ {
+ task_vforkabort(child, -ret);
+ return ERROR;
+ }
+
+ /* Since the child task has the same priority as the parent task, it is
+ * now ready to run, but has not yet ran. It is a requirement that
+ * the parent enivornment be stable while vfork runs; the child thread
+ * is still dependent on things in the parent thread... like the pointers
+ * into parent thread's stack which will still appear in the child's
+ * registers and environment.
+ *
+ * We do not have SIG_CHILD, so we have to do some silly things here.
+ * The simplest way to make sure that the child thread runs to completion
+ * is simply to yield here. Since the child can only do exit() or
+ * execv/l(), that should be all that is needed.
+ *
+ * Hmmm.. this is probably not sufficient. What if we are running
+ * SCHED_RR? What if the child thread is suspeneded and rescheduled
+ * after the parent thread again?
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+
+ /* We can also exploit a bug in the execv() implementation: The PID
+ * of the task exec'ed by the child will not be the same as the PID of
+ * the child task. Therefore, waitpid() on the child task's PID will
+ * accomplish what we need to do.
+ */
+
+ rc = 0;
+
+#ifdef CONFIG_DEBUG
+ ret = waitpid(pid, &rc, 0);
+ if (ret < 0)
+ {
+ sdbg("ERROR: waitpid failed: %d\n", errno);
+ }
+#else
+ (void)waitpid(pid, &rc, 0);
+#endif
+
+#else
+ /* The following logic does not appear to work... It gets stuff in an
+ * infinite kill() loop and hogs the processor. Therefore, it looks
+ * as though CONFIG_SCHED_WAITPID may be a requirement to used vfork().
+ *
+ * Again exploiting that execv() bug: Check if the child thread is
+ * still running.
+ */
+
+ while (kill(pid, 0) == OK)
+ {
+ /* Yes.. then we can yield to it -- assuming that it has not lowered
+ * its priority. sleep(0) might be a safer thing to do since it does
+ * not depend on prioirities: It will halt the parent thread for one
+ * system clock tick. This will delay the return to the parent thread.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ sleep(0);
+#else
+ sched_yield();
+#endif
+ }
+#endif
+
+ return pid;
+}
+
+/****************************************************************************
+ * Name: task_vforkabort
+ *
+ * Description:
+ * Recover from any errors after task_vforksetup() was called.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void task_vforkabort(FAR _TCB *child, int errcode)
+{
+ /* The TCB was added to the active task list by task_schedsetup() */
+
+ dq_rem((FAR dq_entry_t*)child, (dq_queue_t*)&g_inactivetasks);
+
+ /* Release the TCB */
+
+ sched_releasetcb(child);
+ set_errno(errcode);
+}
diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c
index 1814ba898..f09842ad4 100644
--- a/nuttx/sched/timer_settime.c
+++ b/nuttx/sched/timer_settime.c
@@ -113,6 +113,10 @@ static void inline timer_sigqueue(FAR struct posix_timer_s *timer)
#else
info.si_value.sival_ptr = timer->pt_value.sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = 0; /* Not applicable */
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/syscall/syscall.csv b/nuttx/syscall/syscall.csv
index 4ccd53f9d..5bc52a71d 100644
--- a/nuttx/syscall/syscall.csv
+++ b/nuttx/syscall/syscall.csv
@@ -43,6 +43,8 @@
"prctl","sys/prctl.h", "CONFIG_TASK_NAME_SIZE > 0","int","int","..."
"clock_systimer","nuttx/clock.h","!defined(CONFIG_DISABLE_CLOCK)","uint32_t"
"poll","poll.h","!defined(CONFIG_DISABLE_POLL) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","FAR struct pollfd*","nfds_t","int"
+"posix_spawnp", defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []"
+"posix_spawn", !defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []"
"pthread_barrier_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*"
"pthread_barrier_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*","FAR const pthread_barrierattr_t*","unsigned int"
"pthread_barrier_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*"
diff --git a/nuttx/tools/Makefile.export b/nuttx/tools/Makefile.export
index 002cb526b..6dfe72bf9 100644
--- a/nuttx/tools/Makefile.export
+++ b/nuttx/tools/Makefile.export
@@ -37,14 +37,18 @@ include $(TOPDIR)/.config
include $(EXPORTDIR)/Make.defs
ifdef ARCHSCRIPT
+#
+# ARCHSCRIPT may contain a leading -T; it must not be followed by a space
+# for this to work.
+#
ifeq ($(WINTOOL),y)
-LDPATH = ${shell cygpath -u $(patsubst -T,,$(ARCHSCRIPT))}
+LDPATH = $(shell cygpath -u $(patsubst -T%,%,$(ARCHSCRIPT)))
else
-LDPATH = $(patsubst -T,,$(ARCHSCRIPT))
+LDPATH = $(patsubst -T%,%,$(ARCHSCRIPT))
endif
-LDNAME = ${shell basename ${LDPATH}}
-LDDIR = ${shell dirname ${LDPATH}}
+LDNAME = ${notdir ${LDPATH}}
+LDDIR = ${dir ${LDPATH}}
endif
ARCHSUBDIR = "arch/$(CONFIG_ARCH)/src"
diff --git a/nuttx/tools/Makefile.host b/nuttx/tools/Makefile.host
index 4a46901e6..998d38916 100644
--- a/nuttx/tools/Makefile.host
+++ b/nuttx/tools/Makefile.host
@@ -37,31 +37,41 @@ TOPDIR ?= ${shell pwd}/..
-include $(TOPDIR)/Make.defs
include ${TOPDIR}/tools/Config.mk
+# Define HOSTCC on the make command line if it differs from these defaults
+# Define HOSTCFLAGS with -g on the make command line to build debug versions
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+
+# In the Windows native environment, the MinGW GCC compiler is assumed
+
+HOSTCC ?= mingw-gcc.exe
+HOSTCFLAGS ?= -O2 -Wall -Wstrict-prototypes -Wshadow -I. -DCONFIG_WINDOWS_NATIVE=y
+
+else
+
+# GCC is assumed in the POSIX environment.
# strtok_r is used in some tools, but does not seem to be available in
# the MinGW environment.
-ifneq ($(CONFIG_WINDOWS_NATIVE),y)
- HOSTCFLAGS += -D HAVE_STRTOK_C
+HOSTCC ?= gcc
+HOSTCFLAGS ?= -O2 -Wall -Wstrict-prototypes -Wshadow -I. -DHAVE_STRTOK_C
+
endif
+# Targets
+
all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \
- mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) mksymtab$(HOSTEXEEXT) \
+ configure$(HOSTEXEEXT) mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) mksymtab$(HOSTEXEEXT) \
mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT)
default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT)
ifdef HOSTEXEEXT
-.PHONY: b16 bdf-converter cmpconfig clean mkconfig mkdeps mksymtab \
- mksyscall mkversion
+.PHONY: b16 bdf-converter cmpconfig clean configure mkconfig mkdeps mksymtab mksyscall mkversion
else
.PHONY: clean
endif
-# Add HOSTCFLAGS=-g on the make command line build debug versions
-
-HOSTCFLAGS ?= -O2 -Wall -I.
-HOSTCC ?= gcc
-
-# b16 - Fixed precision math converstion tool
+# b16 - Fixed precision math conversion tool
b16$(HOSTEXEEXT): b16.c
$(Q) $(HOSTCC) $(HOSTCFLAGS) -o b16$(HOSTEXEEXT) b16.c
@@ -70,10 +80,19 @@ ifdef HOSTEXEEXT
b16: b16$(HOSTEXEEXT)
endif
+# configure - Instantiate a canned NuttX configuration
+
+configure$(HOSTEXEEXT): configure.c cfgparser.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o configure$(HOSTEXEEXT) configure.c cfgparser.c
+
+ifdef HOSTEXEEXT
+configure: configure$(HOSTEXEEXT)
+endif
+
# mkconfig - Convert a .config file into a C config.h file
-mkconfig$(HOSTEXEEXT): mkconfig.c cfgparser.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkconfig$(HOSTEXEEXT) mkconfig.c cfgparser.c
+mkconfig$(HOSTEXEEXT): mkconfig.c cfgdefine.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkconfig$(HOSTEXEEXT) mkconfig.c cfgdefine.c
ifdef HOSTEXEEXT
mkconfig: mkconfig$(HOSTEXEEXT)
@@ -81,8 +100,8 @@ endif
# cmpconfig - Compare the contents of two configuration files
-cmpconfig$(HOSTEXEEXT): cmpconfig.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o cmpconfig$(HOSTEXEEXT) cmpconfig.c
+cmpconfig$(HOSTEXEEXT): cmpconfig.c cfgparser.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o cmpconfig$(HOSTEXEEXT) cmpconfig.c cfgparser.c
ifdef HOSTEXEEXT
cmpconfig: cmpconfig$(HOSTEXEEXT)
@@ -90,8 +109,8 @@ endif
# mkversion - Convert a .version file into a C version.h file
-mkversion$(HOSTEXEEXT): mkconfig.c cfgparser.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkversion$(HOSTEXEEXT) mkversion.c cfgparser.c
+mkversion$(HOSTEXEEXT): mkconfig.c cfgdefine.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkversion$(HOSTEXEEXT) mkversion.c cfgdefine.c
ifdef HOSTEXEEXT
mkversion: mkversion$(HOSTEXEEXT)
diff --git a/nuttx/tools/README.txt b/nuttx/tools/README.txt
index 2b9ac61f4..8df4a7783 100644
--- a/nuttx/tools/README.txt
+++ b/nuttx/tools/README.txt
@@ -26,19 +26,42 @@ Config.mk
override these default definitions as necessary.
configure.sh
+configure.bat
+configure.c, cfgparser.c, and cfgparser.h
------------
- This is a bash script that is used to configure NuttX for a given
- target board. See configs/README.txt or Documentation/NuttxPortingGuide.html
+ configure.sh is a bash script that is used to configure NuttX for a given
+ target board in a environment that supports POSIX paths (Linux, Cygwin,
+ OSX, or similar). See configs/README.txt or Documentation/NuttxPortingGuide.html
for a description of how to configure NuttX with this script.
+ configure.c, cfgparser.c, and cfgparser.h can be used to build a work-alike
+ program as a replacement for configure.sh. This work-alike program would be
+ used in environments that do not support Bash scripting (such as the Windows
+ native environment).
+
+ configure.bat is a small Windows batch file that can be used as a replacement
+ for configure.sh in a Windows native environment. configure.bat is actually
+ just a thin layer that execuates configure.exe if it is available. If
+ configure.exe is not available, then configure.bat will attempt to build it
+ first.
+
+ In order two build configure.exe from configure.c in the Windows native
+ environment, two assumptions are made:
+
+ 1) You have installed the MinGW GCC toolchain. This toolchain can be
+ downloaded from http://www.mingw.org/. Tt is recommended the you not
+ install the optional MSYS components as there may be conflicts.
+ 2) That path to bin bin/ directory containing mingw-gcc.exe must be
+ included in the PATH variable.
+
discover.py
-----------
Example script for discovering devices in the local network.
It is the counter part to apps/netutils/discover
-mkconfig.c, cfgparser.c, and cfgparser.h
+mkconfig.c, cfgdefine.c, and cfgdefine.h
----------------------------------------
These are Cs file that are used to build mkconfig program. The mkconfig
@@ -79,7 +102,7 @@ mkfsdata.pl
NOTE: This perl script comes from uIP and was (probably) written
by Adam Dunkels. uIP has a license that is compatible with NuttX.
-mkversion.c, cfgparser.c, and cfgparser.h
+mkversion.c, cfgdefine.c, and cfgdefine.h
-----------------------------------------
This is C file that is used to build mkversion program. The mkversion
@@ -413,6 +436,36 @@ unlink.bat
NTFS mklink.exe command instead of copying files. That logic, however,
has not been verified as of this writing.
+kconfig.bat
+-----------
+
+ Recent versions of NuttX support building NuttX from a native Windows
+ CMD.exe shell. But kconfig-frontends is a Linux tool and is not yet
+ available in the pure CMD.exe environment. At this point, there are
+ only a few options for the Windows user (see the top-level README.txt
+ file).
+
+ You can, with some effort, run the the Cygwin kconfig-mconf tool directly
+ in the CMD.exe shell. In this case, you do not have to modify the
+ .config file, but there are other complexities: You need to
+ temporarily set the Cgywin directories in the PATH variable and
+ then run kconfig-mconf outside of the Make system.
+
+ kconfig.bat is a Windows batch file at tools/kconfig.bat that automates
+ these steps. It is used from the top-level NuttX directory like:
+
+ tools/kconfig menuconfig
+
+ NOTE: There is an currently an issue with accessing DOS environment
+ variables from the Cygwin kconfig-mconf running in the CMD.exe shell.
+ The following change to the top-level Kconfig file seems to work around
+ these problems:
+
+ config APPSDIR
+ string
+ - option env="APPSDIR"
+ + default "../apps"
+
mkimage.sh
----------
diff --git a/nuttx/tools/bdf-converter.c b/nuttx/tools/bdf-converter.c
index b32209fcf..a03faa93e 100644
--- a/nuttx/tools/bdf-converter.c
+++ b/nuttx/tools/bdf-converter.c
@@ -43,6 +43,7 @@
* Included Files
****************************************************************************/
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
diff --git a/nuttx/tools/cfgdefine.c b/nuttx/tools/cfgdefine.c
new file mode 100644
index 000000000..f026a186f
--- /dev/null
+++ b/nuttx/tools/cfgdefine.c
@@ -0,0 +1,323 @@
+/****************************************************************************
+ * tools/cfgdefine.c
+ *
+ * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+#include "cfgdefine.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+char line[LINESIZE+1];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* These are configuration variable name that are quoted by configuration tool
+ * but which must be unquoted when used in C code.
+ */
+
+static const char *dequote_list[] =
+{
+ /* NuttX */
+
+ "CONFIG_USER_ENTRYPOINT", /* Name of entry point function */
+ "CONFIG_EXECFUNCS_SYMTAB", /* Symbol table used by exec[l|v] */
+
+ /* NxWidgets/NxWM */
+
+ "CONFIG_NXWM_BACKGROUND_IMAGE", /* Name of bitmap image class */
+ "CONFIG_NXWM_STARTWINDOW_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_NXCONSOLE_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_CALIBRATION_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_HEXCALCULATOR_ICON", /* Name of bitmap image class */
+
+ NULL /* Marks the end of the list */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+ /* Skip over any spaces */
+
+static char *skip_space(char *ptr)
+{
+ while (*ptr && isspace((int)*ptr)) ptr++;
+ return ptr;
+}
+
+/* Find the end of a variable string */
+
+static char *find_name_end(char *ptr)
+{
+ while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
+ return ptr;
+}
+
+/* Find the end of a value string */
+
+static char *find_value_end(char *ptr)
+{
+ while (*ptr && !isspace((int)*ptr))
+ {
+ if (*ptr == '"')
+ {
+ do ptr++; while (*ptr && *ptr != '"');
+ if (*ptr) ptr++;
+ }
+ else
+ {
+ do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
+ }
+ }
+ return ptr;
+}
+
+/* Read the next line from the configuration file */
+
+static char *read_line(FILE *stream)
+{
+ char *ptr;
+
+ for (;;)
+ {
+ line[LINESIZE] = '\0';
+ if (!fgets(line, LINESIZE, stream))
+ {
+ return NULL;
+ }
+ else
+ {
+ ptr = skip_space(line);
+ if (*ptr && *ptr != '#' && *ptr != '\n')
+ {
+ return ptr;
+ }
+ }
+ }
+}
+
+/* Parse the line from the configuration file into a variable name
+ * string and a value string.
+ */
+
+static void parse_line(char *ptr, char **varname, char **varval)
+{
+ /* Skip over any leading spaces */
+
+ ptr = skip_space(ptr);
+
+ /* The first no-space is the beginning of the variable name */
+
+ *varname = skip_space(ptr);
+ *varval = NULL;
+
+ /* Parse to the end of the variable name */
+
+ ptr = find_name_end(ptr);
+
+ /* An equal sign is expected next, perhaps after some white space */
+
+ if (*ptr && *ptr != '=')
+ {
+ /* Some else follows the variable name. Terminate the variable
+ * name and skip over any spaces.
+ */
+
+ *ptr = '\0';
+ ptr = skip_space(ptr + 1);
+ }
+
+ /* Verify that the equal sign is present */
+
+ if (*ptr == '=')
+ {
+ /* Make sure that the variable name is terminated (this was already
+ * done if the name was followed by white space.
+ */
+
+ *ptr = '\0';
+
+ /* The variable value should follow =, perhaps separated by some
+ * white space.
+ */
+
+ ptr = skip_space(ptr + 1);
+ if (*ptr)
+ {
+ /* Yes.. a variable follows. Save the pointer to the start
+ * of the variable string.
+ */
+
+ *varval = ptr;
+
+ /* Find the end of the variable string and make sure that it
+ * is terminated.
+ */
+
+ ptr = find_value_end(ptr);
+ *ptr = '\0';
+ }
+ }
+}
+
+static char *dequote_value(const char *varname, char *varval)
+{
+ const char **dqnam;
+ char *dqval = varval;
+ int len;
+
+ if (dqval)
+ {
+ /* Check if the variable name is in the list of strings to be dequoated */
+
+ for (dqnam = dequote_list; *dqnam; dqnam++)
+ {
+ if (strcmp(*dqnam, varname) == 0)
+ {
+ break;
+ }
+ }
+
+ /* Did we find the variable name in the list of configuration variables
+ * to be dequoated?
+ */
+
+ if (*dqnam)
+ {
+ /* Yes... Check if there is a traiing quote */
+
+ len = strlen(dqval);
+ if (dqval[len-1] == '"')
+ {
+ /* Yes... replace it with a terminator */
+
+ dqval[len-1] = '\0';
+ len--;
+ }
+
+ /* Is there a leading quote? */
+
+ if (dqval[0] == '"')
+ {
+ /* Yes.. skip over the leading quote */
+
+ dqval++;
+ len--;
+ }
+
+ /* Handle the case where nothing is left after dequoting */
+
+ if (len <= 0)
+ {
+ dqval = NULL;
+ }
+ }
+ }
+
+ return dqval;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void generate_definitions(FILE *stream)
+{
+ char *varname;
+ char *varval;
+ char *ptr;
+
+ /* Loop until the entire file has been parsed. */
+
+ do
+ {
+ /* Read the next line from the file */
+
+ ptr = read_line(stream);
+ if (ptr)
+ {
+ /* Parse the line into a variable and a value field */
+
+ parse_line(ptr, &varname, &varval);
+
+ /* Was a variable name found? */
+
+ if (varname)
+ {
+ /* Yes.. dequote the value if necessary */
+
+ varval = dequote_value(varname, varval);
+
+ /* If no value was provided or if the special value 'n' was provided,
+ * then undefine the configuration variable.
+ */
+
+ if (!varval || strcmp(varval, "n") == 0)
+ {
+ printf("#undef %s\n", varname);
+ }
+
+ /* Simply define the configuration variable if it has the special
+ * value "y"
+ */
+
+ else if (strcmp(varval, "y") == 0)
+ {
+ printf("#define %s 1\n", varname);
+ }
+
+ /* Otherwise, use the value as provided */
+
+ else
+ {
+ printf("#define %s %s\n", varname, varval);
+ }
+ }
+ }
+ }
+ while (ptr);
+}
diff --git a/apps/namedapp/namedapp.h b/nuttx/tools/cfgdefine.h
index 7fcdf42dc..f76ba73fb 100644
--- a/apps/namedapp/namedapp.h
+++ b/nuttx/tools/cfgdefine.h
@@ -1,10 +1,8 @@
/****************************************************************************
- * apps/namedaps/namedapp.h
+ * tools/cfgdefine.h
*
- * Copyright (C) 2011 Uros Platise. All rights reserved.
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
- * Authors: Uros Platise <uros.platise@isotel.eu>
- * Gregory Nutt <gnutt@nuttx.org>
+ * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,44 +33,32 @@
*
****************************************************************************/
-#ifndef __APPS_NAMEDAPP_NAMEDAPP_H
-#define __APPS_NAMEDAPP_NAMEDAPP_H
+#ifndef __TOOLS_CFGDEFINE_H
+#define __TOOLS_CFGDEFINE_H
/****************************************************************************
* Included Files
****************************************************************************/
-#include <nuttx/config.h>
-#include <apps/apps.h>
+#include <stdio.h>
+#include <limits.h>
/****************************************************************************
- * Public Types
+ * Definitions
****************************************************************************/
+#define LINESIZE ( PATH_MAX > 256 ? PATH_MAX : 256 )
+
/****************************************************************************
* Public Data
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
-EXTERN const struct namedapp_s namedapps[];
+extern char line[LINESIZE+1];
/****************************************************************************
* Public Functions
****************************************************************************/
-EXTERN int number_namedapps(void);
-
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __APPS_NAMEDAPP_NAMEDAPP_H */
+void generate_definitions(FILE *stream);
+#endif /* __TOOLS_CFGDEFINE_H */
diff --git a/nuttx/tools/cfgparser.c b/nuttx/tools/cfgparser.c
index 1a35f7857..ac25bd26b 100644
--- a/nuttx/tools/cfgparser.c
+++ b/nuttx/tools/cfgparser.c
@@ -38,7 +38,9 @@
****************************************************************************/
#include <string.h>
+#include <stdlib.h>
#include <ctype.h>
+
#include "cfgparser.h"
/****************************************************************************
@@ -55,28 +57,7 @@ char line[LINESIZE+1];
* Private Data
****************************************************************************/
-/* These are configuration variable name that are quoted by configuration tool
- * but which must be unquoted when used in C code.
- */
-
-static const char *dequote_list[] =
-{
- /* NuttX */
-
- "CONFIG_USER_ENTRYPOINT", /* Name of entry point function */
-
- /* NxWidgets/NxWM */
-
- "CONFIG_NXWM_BACKGROUND_IMAGE", /* Name of bitmap image class */
- "CONFIG_NXWM_STARTWINDOW_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_NXCONSOLE_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_CALIBRATION_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_HEXCALCULATOR_ICON", /* Name of bitmap image class */
-
- NULL /* Marks the end of the list */
-};
-
- /****************************************************************************
+/****************************************************************************
* Private Functions
****************************************************************************/
@@ -203,69 +184,15 @@ static void parse_line(char *ptr, char **varname, char **varval)
}
}
-static char *dequote_value(const char *varname, char *varval)
-{
- const char **dqnam;
- char *dqval = varval;
- int len;
-
- if (dqval)
- {
- /* Check if the variable name is in the list of strings to be dequoated */
-
- for (dqnam = dequote_list; *dqnam; dqnam++)
- {
- if (strcmp(*dqnam, varname) == 0)
- {
- break;
- }
- }
-
- /* Did we find the variable name in the list of configuration variables
- * to be dequoated?
- */
-
- if (*dqnam)
- {
- /* Yes... Check if there is a traiing quote */
-
- len = strlen(dqval);
- if (dqval[len-1] == '"')
- {
- /* Yes... replace it with a terminator */
-
- dqval[len-1] = '\0';
- len--;
- }
-
- /* Is there a leading quote? */
-
- if (dqval[0] == '"')
- {
- /* Yes.. skip over the leading quote */
-
- dqval++;
- len--;
- }
-
- /* Handle the case where nothing is left after dequoting */
-
- if (len <= 0)
- {
- dqval = NULL;
- }
- }
- }
-
- return dqval;
-}
-
/****************************************************************************
* Public Functions
****************************************************************************/
-void parse_file(FILE *stream)
+void parse_file(FILE *stream, struct variable_s **list)
{
+ struct variable_s *curr;
+ struct variable_s *prev;
+ struct variable_s *next;
char *varname;
char *varval;
char *ptr;
@@ -283,40 +210,87 @@ void parse_file(FILE *stream)
parse_line(ptr, &varname, &varval);
- /* Was a variable name found? */
+ /* If the variable has not value (or the special value 'n'), then
+ * ignore it.
+ */
- if (varname)
+ if (!varval || strcmp(varval, "n") == 0)
{
- /* Yes.. dequote the value if necessary */
+ continue;
+ }
- varval = dequote_value(varname, varval);
+ /* Make sure that a variable name was found. */
- /* If no value was provided or if the special value 'n' was provided,
- * then undefine the configuration variable.
+ if (varname)
+ {
+ int varlen = strlen(varname) + 1;
+ int vallen = 0;
+
+ /* Get the size of the value, including the NUL terminating
+ * character.
*/
- if (!varval || strcmp(varval, "n") == 0)
+ if (varval)
{
- printf("#undef %s\n", varname);
+ vallen = strlen(varval) + 1;
}
- /* Simply define the configuration variable if it has the special
- * value "y"
+ /* Allocate memory to hold the struct variable_s with the
+ * variable name and the value.
*/
- else if (strcmp(varval, "y") == 0)
+ curr = (struct variable_s *)malloc(sizeof(struct variable_s) + varlen + vallen - 1);
+ if (curr)
{
- printf("#define %s 1\n", varname);
+ /* Add the variable to the list */
+
+ curr->var = &curr->storage[0];
+ strcpy(curr->var, varname);
+
+ curr->val = NULL;
+ if (varval)
+ {
+ curr->val = &curr->storage[varlen];
+ strcpy(curr->val, varval);
+ }
}
- /* Otherwise, use the value as provided */
+ prev = 0;
+ next = *list;
+ while (next && strcmp(next->var, curr->var) <= 0)
+ {
+ prev = next;
+ next = next->flink;
+ }
+ if (prev)
+ {
+ prev->flink = curr;
+ }
else
{
- printf("#define %s %s\n", varname, varval);
+ *list = curr;
}
+
+ curr->flink = next;
}
}
}
while (ptr);
}
+
+struct variable_s *find_variable(const char *varname, struct variable_s *list)
+{
+ while (list)
+ {
+ if (strcmp(varname, list->var) == 0)
+ {
+ return list;
+ }
+
+ list = list->flink;
+ }
+
+ return NULL;
+}
+
diff --git a/nuttx/tools/cfgparser.h b/nuttx/tools/cfgparser.h
index b1c4bae76..b1f421a68 100644
--- a/nuttx/tools/cfgparser.h
+++ b/nuttx/tools/cfgparser.h
@@ -50,6 +50,18 @@
#define LINESIZE ( PATH_MAX > 256 ? PATH_MAX : 256 )
/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct variable_s
+{
+ struct variable_s *flink;
+ char *var;
+ char *val;
+ char storage[1];
+};
+
+/****************************************************************************
* Public Data
****************************************************************************/
@@ -59,6 +71,7 @@ extern char line[LINESIZE+1];
* Public Functions
****************************************************************************/
-extern void parse_file(FILE *stream);
+void parse_file(FILE *stream, struct variable_s **list);
+struct variable_s *find_variable(const char *varname, struct variable_s *list);
#endif /* __TOOLS_CFGPARSER_H */
diff --git a/nuttx/tools/cmpconfig.c b/nuttx/tools/cmpconfig.c
index 2958acdc7..a5a539401 100644
--- a/nuttx/tools/cmpconfig.c
+++ b/nuttx/tools/cmpconfig.c
@@ -43,6 +43,8 @@
#include <ctype.h>
#include <errno.h>
+#include "cfgparser.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -51,14 +53,6 @@
* Private Types
****************************************************************************/
-struct variable_s
-{
- struct variable_s *flink;
- char *var;
- char *val;
- char storage[1];
-};
-
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -69,154 +63,11 @@ static void show_usage(const char *progname)
exit(EXIT_FAILURE);
}
-static char *skip_space(char *ptr)
-{
- while (*ptr && isspace((int)*ptr)) ptr++;
- return ptr;
-}
-
-static char *read_line(FILE *stream, char *line, int len)
-{
- char *ptr;
-
- for (;;)
- {
- line[len-1] = '\0';
- if (!fgets(line, len, stream))
- {
- return NULL;
- }
- else
- {
- ptr = skip_space(line);
- if (*ptr && *ptr != '#' && *ptr != '\n')
- {
- return ptr;
- }
- }
- }
-}
-
-static char *find_name_end(char *ptr)
-{
- while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
- return ptr;
-}
-
-static char *find_value_end(char *ptr)
-{
- while (*ptr && !isspace((int)*ptr))
- {
- if (*ptr == '"')
- {
- do ptr++; while (*ptr && *ptr != '"');
- if (*ptr) ptr++;
- }
- else
- {
- do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
- }
- }
- return ptr;
-}
-
-static void parse_line(char *ptr, char **varname, char **varval)
-{
- *varname = ptr;
- *varval = NULL;
-
- ptr = find_name_end(ptr);
- if (*ptr && *ptr != '=')
- {
- *ptr = '\0';
- ptr = skip_space(ptr + 1);
- }
-
- if (*ptr == '=')
- {
- *ptr = '\0';
- ptr = skip_space(ptr + 1);
- if (*ptr)
- {
- *varval = ptr;
- ptr = find_value_end(ptr);
- *ptr = '\0';
- }
- }
-}
-
-static void parse_file(FILE *stream, struct variable_s **list)
-{
- char line[10242];
- struct variable_s *curr;
- struct variable_s *prev;
- struct variable_s *next;
- char *varname;
- char *varval;
- char *ptr;
-
- do
- {
- ptr = read_line(stream, line, 1024);
- if (ptr)
- {
- parse_line(ptr, &varname, &varval);
- if (!varval || strcmp(varval, "n") == 0)
- {
- continue;
- }
-
- if (varname)
- {
- int varlen = strlen(varname) + 1;
- int vallen = 0;
-
- if (varval)
- {
- vallen = strlen(varval) + 1;
- }
-
- curr = (struct variable_s *)malloc(sizeof(struct variable_s) + varlen + vallen - 1);
- if (curr)
- {
- curr->var = &curr->storage[0];
- strcpy(curr->var, varname);
-
- curr->val = NULL;
- if (varval)
- {
- curr->val = &curr->storage[varlen];
- strcpy(curr->val, varval);
- }
- }
-
- prev = 0;
- next = *list;
- while (next && strcmp(next->var, curr->var) <= 0)
- {
- prev = next;
- next = next->flink;
- }
-
- if (prev)
- {
- prev->flink = curr;
- }
- else
- {
- *list = curr;
- }
- curr->flink = next;
- }
- }
- }
- while (ptr);
-}
-
static void compare_variables(struct variable_s *list1, struct variable_s *list2)
{
char *varval1;
char *varval2;
+ int result;
while (list1 || list2)
{
@@ -252,7 +103,7 @@ static void compare_variables(struct variable_s *list1, struct variable_s *list2
}
else
{
- int result = strcmp(list1->var, list2->var);
+ result = strcmp(list1->var, list2->var);
if (result < 0)
{
printf("file1: %s=%s\n", list1->var, varval1);
@@ -265,9 +116,9 @@ static void compare_variables(struct variable_s *list1, struct variable_s *list2
printf("file2: %s=%s\n\n", list2->var, varval2);
list2 = list2->flink;
}
- else
+ else /* if (result == 0) */
{
- int result = strcmp(varval1, varval2);
+ result = strcmp(varval1, varval2);
if (result != 0)
{
printf("file1: %s=%s\n", list1->var, varval1);
diff --git a/nuttx/tools/configure.bat b/nuttx/tools/configure.bat
new file mode 100644
index 000000000..7dc9ca116
--- /dev/null
+++ b/nuttx/tools/configure.bat
@@ -0,0 +1,127 @@
+@echo off
+
+rem tools/configure.bat
+rem
+rem Copyright (C) 2012 Gregory Nutt. All rights reserved.
+rem Author: Gregory Nutt <gnutt@nuttx.org>
+rem
+rem Redistribution and use in source and binary forms, with or without
+rem modification, are permitted provided that the following conditions
+rem are met:
+rem
+rem 1. Redistributions of source code must retain the above copyright
+rem notice, this list of conditions and the following disclaimer.
+rem 2. Redistributions in binary form must reproduce the above copyright
+rem notice, this list of conditions and the following disclaimer in
+rem the documentation and/or other materials provided with the
+rem distribution.
+rem 3. Neither the name NuttX nor the names of its contributors may be
+rem used to endorse or promote products derived from this software
+rem without specific prior written permission.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+rem FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+rem COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+rem OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+rem AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+rem LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+rem ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+rem POSSIBILITY OF SUCH DAMAGE.
+rem
+
+rem Parse command line arguments
+
+set debug=
+set fmt=-w
+set posix=
+set help=
+set appdir=
+set config=
+
+:ArgLoop
+if "%1"=="" goto :NoConfig
+if "%1"=="-h" goto :ShowUsage
+if "%1"=="-d" goto :SetDebug
+if "%1"=="-w" goto :SetWindows
+if "%1"=="-l" goto :SetPosix
+if "%1"=="-a" goto :SetAppDir
+
+set config=%1
+goto EndOfLoop
+
+:SetDebug
+set debug=-d
+goto :NextArg
+
+:SetWindows
+set fmt=-w
+goto :NextArg
+
+:SetWindows
+set fmt=-l
+goto :NextArg
+
+:SetAppDir
+shift
+set appdir=-a %1
+
+:NextArg
+shift
+goto :ArgLoop
+
+:EndOfLoop
+
+rem Check if we have to build configure.exe
+
+if exist configure.exe goto :HaveConfigureExe
+
+set cc=mingw32-gcc.exe
+set cflags=-Wall -Wstrict-prototypes -Wshadow -g -pipe -I. -DCONFIG_WINDOWS_NATIVE=y
+%cc% %cflags% -o configure.exe configure.c cfgparser.c
+if errorlevel 1 (
+ echo ERROR: %cc% failed
+ echo Is ming32-gcc.exe installed? Is it in the PATH variable?
+ goto End
+)
+
+:HaveConfigureExe
+configure.exe %debug% %fmt% %appdir% %config%
+if errorlevel 1 echo configure.exe failed
+goto End
+
+:NoConfig
+echo Missing ^<board-name^>/^<config-name^> argument
+
+:ShowUsage
+echo USAGE: %0 [-d] [-w] [-l] [-h] [-a ^<app-dir^>] ^<board-name^>\^<config-name^>
+echo\nWhere:
+echo ^<board-name^>:
+echo Identifies the board. This must correspond to a board directory
+echo under nuttx/configs/.
+echo ^<config-name^>:
+echo Identifies the specific configuratin for the selected ^<board-name^>.
+echo This must correspond to a sub-directory under the board directory at
+echo under nuttx/configs/^<board-name^>/.
+echo ^<-d^>:
+echo Enables debug output
+echo ^<-w^>:
+echo Informs the tool that it should use Windows style paths like C:\\Program Files
+echo instead of POSIX style paths are used like /usr/local/bin. Windows
+echo style paths are used by default.
+echo ^<-l^>:
+echo Informs the tool that it should use POSIX style paths like /usr/local/bin.
+echo By default, Windows style paths like C:\\Program Files are used.
+echo -a ^<app-dir^>:
+echo Informs the configuration tool where the application build
+echo directory. This is a relative path from the top-level NuttX
+echo build directory. But default, this tool will look in the usual
+echo places to try to locate the application directory: ../apps or
+echo ../apps-xx.yy where xx.yy is the NuttX version number.
+echo ^<-h^>:
+echo Prints this message and exits.
+
+:End
diff --git a/nuttx/tools/configure.c b/nuttx/tools/configure.c
new file mode 100644
index 000000000..9e82c3657
--- /dev/null
+++ b/nuttx/tools/configure.c
@@ -0,0 +1,890 @@
+/****************************************************************************
+ * tools/configure.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/stat.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "cfgparser.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define BUFFER_SIZE 1024
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_WINDOWS_NATIVE
+static char g_delim = '\\'; /* Delimiter to use when forming paths */
+static bool g_winpaths = true; /* True: Windows style paths */
+#else
+static char g_delim = '/'; /* Delimiter to use when forming paths */
+static bool g_winpaths = false; /* False: POSIX style paths */
+#endif
+static bool g_debug = false; /* Enable debug output */
+
+static const char *g_appdir = NULL; /* Relative path to the applicatin directory */
+static const char *g_boarddir = NULL; /* Name of board subdirectory */
+static char *g_configdir = NULL; /* Name of configuration subdirectory */
+
+static char *g_topdir = NULL; /* Full path to top-level NuttX build directory */
+static char *g_apppath = NULL; /* Full path to the applicatino directory */
+static char *g_configtop = NULL; /* Full path to the top-level configuration directory */
+static char *g_configpath = NULL; /* Full path to the configuration sub-directory */
+static char *g_verstring = "0.0"; /* Version String */
+
+static char *g_srcdefconfig = NULL; /* Source defconfig file */
+static char *g_srcmakedefs = NULL; /* Source Make.defs file */
+static char *g_srcappconfig = NULL ; /* Source appconfig file (optional) */
+static char *g_srcsetenvsh = NULL; /* Source setenv.sh file (optional) */
+static char *g_srcsetenvbat = NULL; /* Source setenv.bat file (optional) */
+
+static bool g_newconfig = false; /* True: New style configuration */
+static bool g_winnative = false; /* True: Windows native configuration */
+static bool g_needapppath = true; /* Need to add app path to the .config file */
+
+static char g_buffer[BUFFER_SIZE]; /* Scratch buffer for forming full paths */
+
+static struct variable_s *g_configvars = NULL;
+static struct variable_s *g_versionvars = NULL;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void show_usage(const char *progname, int exitcode)
+{
+ fprintf(stderr, "\nUSAGE: %s [-d] [-w] [-l] [-h] [-a <app-dir>] <board-name>[%c<config-name>]\n", progname, g_delim);
+ fprintf(stderr, "\nWhere:\n");
+ fprintf(stderr, " <board-name>:\n");
+ fprintf(stderr, " Identifies the board. This must correspond to a board directory\n");
+ fprintf(stderr, " under nuttx%cconfigs%c.\n", g_delim, g_delim);
+ fprintf(stderr, " <config-name>:\n");
+ fprintf(stderr, " Identifies the specific configuration for the selected <board-name>.\n");
+ fprintf(stderr, " This must correspond to a sub-directory under the board directory at\n");
+ fprintf(stderr, " under nuttx%cconfigs%c<board-name>%c.\n", g_delim, g_delim, g_delim);
+ fprintf(stderr, " <-d>:\n");
+ fprintf(stderr, " Enables debug output\n");
+ fprintf(stderr, " <-w>:\n");
+#ifdef CONFIG_WINDOWS_NATIVE
+ fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files\n");
+ fprintf(stderr, " instead of POSIX style paths are used like /usr/local/bin. Windows\n");
+ fprintf(stderr, " style paths are used by default.\n");
+#else
+ fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files.\n");
+ fprintf(stderr, " By default, POSIX style paths like /usr/local/bin are used.\n");
+#endif
+ fprintf(stderr, " <-l>:\n");
+#ifdef CONFIG_WINDOWS_NATIVE
+ fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin.\n");
+ fprintf(stderr, " By default, Windows style paths like C:\\Program Files are used.\n");
+#else
+ fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin\n");
+ fprintf(stderr, " instead of Windows style paths like C:\\Program Files are used. POSIX\n");
+ fprintf(stderr, " style paths are used by default.\n");
+#endif
+ fprintf(stderr, " -a <app-dir>:\n");
+ fprintf(stderr, " Informs the configuration tool where the application build\n");
+ fprintf(stderr, " directory. This is a relative path from the top-level NuttX\n");
+ fprintf(stderr, " build directory. But default, this tool will look in the usual\n");
+ fprintf(stderr, " places to try to locate the application directory: ..%capps or\n", g_delim);
+ fprintf(stderr, " ..%capps-xx.yy where xx.yy is the NuttX version number.\n", g_delim);
+ fprintf(stderr, " <-h>:\n");
+ fprintf(stderr, " Prints this message and exits.\n");
+ exit(exitcode);
+}
+
+static void debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (g_debug)
+ {
+ va_start(ap, fmt);
+ (void)vprintf(fmt, ap);
+ va_end(ap);
+ }
+}
+
+static void parse_args(int argc, char **argv)
+{
+ char *ptr;
+ int ch;
+
+ /* Parse command line options */
+
+ g_debug = false;
+
+ while ((ch = getopt(argc, argv, ":a:dwlh")) > 0)
+ {
+ switch (ch)
+ {
+ case 'a' :
+ g_appdir = optarg;
+ break;
+
+ case 'd' :
+ g_debug = true;
+ break;
+
+ case 'w' :
+ g_delim = '/';
+ g_winpaths = true;
+ break;
+
+ case 'l' :
+ g_delim = '\\';
+ g_winpaths = false;
+ break;
+
+ case 'h' :
+ show_usage(argv[0], EXIT_SUCCESS);
+
+ case '?' :
+ fprintf(stderr, "ERROR: Unrecognized option: %c\n", optopt);
+ show_usage(argv[0], EXIT_FAILURE);
+
+ case ':' :
+ fprintf(stderr, "ERROR: Missing option argument, option: %c\n", optopt);
+ show_usage(argv[0], EXIT_FAILURE);
+
+ break;
+ fprintf(stderr, "ERROR: Unexpected option: %c\n", ch);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+ }
+
+ /* There should be exactly one argument following the options */
+
+ if (optind >= argc)
+ {
+ fprintf(stderr, "ERROR: Missing <board-name>%c<config-name>\n", g_delim);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+
+ /* The required option should be the board directory name and the
+ * configuration directory name separated by '/' or '\'. Either is
+ * acceptable in this context.
+ */
+
+ g_boarddir = argv[optind];
+ optind++;
+
+ ptr = strchr(g_boarddir, '/');
+ if (!ptr)
+ {
+ ptr = strchr(g_boarddir, '\\');
+ }
+
+ if (!ptr)
+ {
+ fprintf(stderr, "ERROR: Invalid <board-name>%c<config-name>\n", g_delim);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+
+ *ptr++ = '\0';
+ g_configdir = ptr;
+
+ if (optind < argc)
+ {
+ fprintf(stderr, "Unexpected garbage at the end of the line\n");
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+}
+
+static void verify_directory(const char *directory)
+{
+ struct stat buf;
+
+ if (stat(directory, &buf) < 0)
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", directory, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (!S_ISDIR(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static bool verify_optiondir(const char *directory)
+{
+ struct stat buf;
+
+ if (stat(directory, &buf) < 0)
+ {
+ /* It may be okay if the dirctory does not exist */
+
+ /* It may be okay if the file does not exist */
+
+ int errcode = errno;
+ if (errcode == ENOENT)
+ {
+ debug("verify_optiondir: stat of %s failed: %s\n", directory, strerror(errno));
+ return false;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", directory, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!S_ISDIR(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory);
+ exit(EXIT_FAILURE);
+ }
+
+ return true;
+}
+
+static bool verify_file(const char *path)
+{
+ struct stat buf;
+
+ if (stat(path, &buf) < 0)
+ {
+ /* It may be okay if the file does not exist */
+
+ int errcode = errno;
+ if (errcode == ENOENT)
+ {
+ debug("verify_file: stat of %s failed: %s\n", path, strerror(errno));
+ return false;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", path, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!S_ISREG(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a regular file\n", path);
+ exit(EXIT_FAILURE);
+ }
+
+ return true;
+}
+
+static void get_topdir(void)
+{
+ /* Get and verify the top-level NuttX directory */
+
+ if (getcwd(g_buffer, BUFFER_SIZE) == NULL)
+ {
+ fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ g_topdir = strdup(dirname(g_buffer));
+ debug("get_topdir: Checking topdir=%s\n", g_topdir);
+ verify_directory(g_topdir);
+}
+
+static void config_search(const char *boarddir)
+{
+ DIR *dir;
+ struct dirent *dp;
+ struct stat buf;
+ char *parent;
+ char *child;
+
+ /* Skip over any leading '/' or '\\'. This happens on the first second
+ * call because the starting boarddir is ""
+ */
+
+ if (boarddir[0] == g_delim)
+ {
+ boarddir++;
+ }
+
+ /* Get the full directory path and open it */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_configtop, g_delim, boarddir);
+ dir = opendir(g_buffer);
+ if (!dir)
+ {
+ fprintf(stderr, "ERROR: Could not open %s: %s\n",
+ g_buffer, strerror(errno));
+ return;
+ }
+
+ /* Make a copy of the path to the directory */
+
+ parent = strdup(g_buffer);
+
+ /* Vist each entry in the directory */
+
+ while ((dp = readdir (dir)) != NULL)
+ {
+ /* Ignore directory entries that start with '.' */
+
+ if (dp->d_name[0] == '.')
+ {
+ continue;
+ }
+
+ /* Get a properly terminated copy of d_name (if d_name is long it may
+ * not include a NUL terminator.\ */
+
+ child = strndup(dp->d_name, NAME_MAX);
+
+ /* Get the full path to d_name and stat the file/directory */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", parent, g_delim, child);
+ if (stat(g_buffer, &buf) < 0)
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n",
+ g_buffer, strerror(errno));
+ free(child);
+ continue;
+ }
+
+ /* If it is a directory, the recurse */
+
+ if (S_ISDIR(buf.st_mode))
+ {
+ char *tmppath;
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", boarddir, g_delim, child);
+ tmppath = strdup(g_buffer);
+ config_search(tmppath);
+ free(tmppath);
+ }
+
+ /* If it is a regular file named 'defconfig' then we have found a
+ * configuration directory. We could terminate the serach in this case
+ * because we do not expect sub-directories within configuration
+ * directories.
+ */
+
+ else if (S_ISREG(buf.st_mode) && strcmp("defconfig", child) == 0)
+ {
+ fprintf(stderr, " %s\n", boarddir);
+ }
+
+ free(child);
+ }
+
+ free(parent);
+ closedir(dir);
+}
+
+static void enumerate_configs(void)
+{
+ fprintf(stderr, "Options for <board-name>[%c<config-name>] include:\n\n", g_delim);
+ config_search("");
+}
+
+static void check_configdir(void)
+{
+ /* Get the path to the top level configuration directory */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cconfigs", g_topdir, g_delim);
+ debug("check_configdir: Checking configtop=%s\n", g_buffer);
+
+ verify_directory(g_buffer);
+ g_configtop = strdup(g_buffer);
+
+ /* Get and verify the path to the selected configuration */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cconfigs%c%s%c%s",
+ g_topdir, g_delim, g_delim, g_boarddir, g_delim, g_configdir);
+ debug("check_configdir: Checking configpath=%s\n", g_buffer);
+
+ if (!verify_optiondir(g_buffer))
+ {
+ fprintf(stderr, "ERROR: No configuration at %s\n", g_buffer);
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_configpath = strdup(g_buffer);
+}
+
+static void read_configfile(void)
+{
+ FILE *stream;
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
+ stream = fopen(g_buffer, "r");
+ if (!stream)
+ {
+ fprintf(stderr, "ERROR: failed to open %s for reading: %s\n",
+ g_buffer, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ parse_file(stream, &g_configvars);
+ fclose(stream);
+}
+
+static void read_versionfile(void)
+{
+ FILE *stream;
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.version", g_topdir, g_delim);
+ stream = fopen(g_buffer, "r");
+ if (!stream)
+ {
+ /* It may not be an error if there is no .version file */
+
+ debug("Failed to open %s for reading: %s\n",
+ g_buffer, strerror(errno));
+ }
+ else
+ {
+ parse_file(stream, &g_versionvars);
+ fclose(stream);
+ }
+}
+
+static void get_verstring(void)
+{
+ struct variable_s *var;
+
+ if (g_versionvars)
+ {
+ var = find_variable("CONFIG_VERSION_STRING", g_versionvars);
+ if (var && var->val)
+ {
+ g_verstring = strdup(var->val);
+ }
+ }
+
+ debug("get_verstring: Version string=%s\n", g_verstring);
+}
+
+static bool verify_appdir(const char *appdir)
+{
+ /* Does this directory exist? */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, appdir);
+ debug("verify_appdir: Checking apppath=%s\n", g_buffer);
+ if (verify_optiondir(g_buffer))
+ {
+ /* Yes.. Use this application directory path */
+
+ g_appdir = strdup(appdir);
+ g_apppath = strdup(g_buffer);
+ return true;
+ }
+
+ debug("verify_appdir: apppath=%s does not exist\n", g_buffer);
+ return false;
+}
+
+static void check_appdir(void)
+{
+ char tmp[16];
+
+ /* Get and verify the full path to the application directory */
+ /* Was the appdir provided on the command line? */
+
+ debug("check_appdir: Command line appdir=%s\n",
+ g_appdir ? g_appdir : "<null>");
+
+ if (!g_appdir)
+ {
+ /* No, was the path provided in the configuration? */
+
+ struct variable_s *var = find_variable("CONFIG_APP_DIR", g_configvars);
+ if (var)
+ {
+ debug("check_appdir: Config file appdir=%s\n",
+ var->val ? var->val : "<null>");
+
+ /* Yes.. does this directory exist? */
+
+ if (var->val && verify_appdir(var->val))
+ {
+ /* We are using the CONFIG_APP_DIR setting already
+ * in the defconfig file.
+ */
+
+ g_needapppath = false;
+ return;
+ }
+ }
+
+ /* Now try some canned locations */
+
+ /* Try ../apps-xx.yy where xx.yy is the version string */
+
+ snprintf(tmp, 16, ".%capps-%s", g_delim, g_verstring);
+ debug("check_appdir: Try appdir=%s\n", tmp);
+ if (verify_appdir(tmp))
+ {
+ return;
+ }
+
+ /* Try ../apps with no version */
+
+ snprintf(tmp, 16, "..%capps", g_delim);
+ debug("check_appdir: Try appdir=%s\n", tmp);
+ if (verify_appdir(tmp))
+ {
+ return;
+ }
+
+ /* Try ../apps-xx.yy where xx.yy are the NuttX version number */
+
+ fprintf(stderr, "ERROR: Could not find the path to the application directory\n");
+ exit(EXIT_FAILURE);
+ }
+ else
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, g_appdir);
+ if (!verify_appdir(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Command line path to application directory does not exist\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+static void check_configuration(void)
+{
+ struct variable_s *var;
+
+ /* Check if this the new style configuration based on kconfig-fontends */
+
+ var = find_variable("CONFIG_NUTTX_NEWCONFIG", g_configvars);
+ if (var && var->val && strcmp("y", var->val) == 0)
+ {
+ debug("check_configuration: New style configuration\n");
+ g_newconfig = true;
+ }
+
+ /* Check if this is a Windows native configuration */
+
+ var = find_variable("CONFIG_WINDOWS_NATIVE", g_configvars);
+ if (var && var->val && strcmp("y", var->val) == 0)
+ {
+ debug("check_configuration: Windows native configuration\n");
+ g_winnative = true;
+ }
+
+ /* All configurations must provide a defconfig and Make.defs file */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: No configuration in %s\n", g_configpath);
+ fprintf(stderr, " No defconfig file found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcdefconfig = strdup(g_buffer);
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Configuration corrupted in %s\n", g_configpath);
+ fprintf(stderr, " No Make.defs file found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcmakedefs = strdup(g_buffer);
+
+ /* Windows native configurations may provide setenv.bat; POSIX
+ * configurations may provide a setenv.sh.
+ */
+
+ if (g_winnative)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (verify_file(g_buffer))
+ {
+ g_srcsetenvbat = strdup(g_buffer);
+ }
+ }
+ else
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (verify_file(g_buffer))
+ {
+ g_srcsetenvsh = strdup(g_buffer);
+ }
+ }
+
+ /* Old style configurations MUST provide an appconfig file */
+
+ if (!g_newconfig)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cappconfig", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Configuration corrupted in %s\n", g_configpath);
+ fprintf(stderr, " Required appconfig file not found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcappconfig = strdup(g_buffer);
+ }
+}
+
+static void copy_file(const char *srcpath, const char *destpath, mode_t mode)
+{
+ int nbytesread;
+ int nbyteswritten;
+ int rdfd;
+ int wrfd;
+
+ /* Open the source file for reading */
+
+ rdfd = open(srcpath, O_RDONLY);
+ if (rdfd < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for reading: %s\n", srcpath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Now open the destination for writing*/
+
+ wrfd = open(destpath, O_WRONLY|O_CREAT|O_TRUNC, mode);
+ if (wrfd < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for writing: %s\n", destpath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Now copy the file */
+
+ for (;;)
+ {
+ do
+ {
+ nbytesread = read(rdfd, g_buffer, BUFFER_SIZE);
+ if (nbytesread == 0)
+ {
+ /* End of file */
+
+ close(rdfd);
+ close(wrfd);
+ return;
+ }
+ else if (nbytesread < 0)
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+ fprintf(stderr, "ERROR: Read failure: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ while (nbytesread <= 0);
+
+ do
+ {
+ nbyteswritten = write(wrfd, g_buffer, nbytesread);
+ if (nbyteswritten >= 0)
+ {
+ nbytesread -= nbyteswritten;
+ }
+ else
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+ fprintf(stderr, "ERROR: Write failure: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ while (nbytesread > 0);
+ }
+}
+
+static void substitute(char *str, int ch1, int ch2)
+{
+ for (; *str; str++)
+ {
+ if (*str == ch1)
+ {
+ *str = ch2;
+ }
+ }
+}
+
+static void configure(void)
+{
+ char *destconfig;
+
+ /* Copy the defconfig file as .config */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_topdir, g_delim);
+ destconfig = strdup(g_buffer);
+ debug("configure: Copying from %s to %s\n", g_srcdefconfig, destconfig);
+ copy_file(g_srcdefconfig, destconfig, 0644);
+
+ /* Copy the Make.defs file as Make.defs */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcmakedefs, g_buffer);
+ copy_file(g_srcmakedefs, g_buffer, 0644);
+
+ /* Copy the setenv.sh file if have one and need one */
+
+ if (g_srcsetenvsh)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcsetenvsh, g_buffer);
+ copy_file(g_srcsetenvsh, g_buffer, 0755);
+ }
+
+ /* Copy the setenv.bat file if have one and need one */
+
+ if (g_srcsetenvbat)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcsetenvbat, g_buffer);
+ copy_file(g_srcsetenvbat, g_buffer, 0644);
+ }
+
+ /* Copy the appconfig file to ../apps/.config if have one and need one */
+
+ if (g_srcappconfig)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_apppath, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcappconfig, g_buffer);
+ copy_file(g_srcappconfig, g_buffer, 0644);
+ }
+
+ /* If we did not use the CONFIG_APPS_DIR that was in the defconfig config file,
+ * then append the correct application information to the tail of the .config
+ * file
+ */
+
+ if (g_needapppath)
+ {
+ FILE *stream;
+ char *appdir = strdup(g_appdir);
+
+ /* One complexity is if we are using Windows paths, but the configuration
+ * needs POSIX paths (or vice versa).
+ */
+
+ if (g_winpaths != g_winnative)
+ {
+ /* Not the same */
+
+ if (g_winpaths)
+ {
+ /* Using Windows paths, but the configuration wants POSIX paths */
+
+ substitute(appdir, '\\', '/');
+ }
+ else
+ {
+ /* Using POSIX paths, but the configuration wants Windows paths */
+
+ substitute(appdir, '/', '\\');
+ }
+ }
+
+ /* Open the file for appending */
+
+ stream = fopen(destconfig, "a");
+ if (!stream)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for append mode mode: %s\n",
+ destconfig, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stream, "\n# Application configuration\n\n");
+ fprintf(stream, "CONFIG_APPS_DIR=\"%s\"\n", appdir);
+ fclose(stream);
+ free(appdir);
+ }
+
+ free(destconfig);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv, char **envp)
+{
+ debug("main: Checking arguments\n");
+ parse_args(argc, argv);
+
+ debug("main: Checking Nuttx Directories\n");
+ get_topdir();
+ check_configdir();
+
+ debug("main: Reading the configuration/version files\n");
+ read_configfile();
+ read_versionfile();
+ get_verstring();
+
+ debug("main: Checking Configuration Directory\n");
+ check_configuration();
+
+ debug("main: Checking Application Directories\n");
+ check_appdir();
+ debug("main: Using apppath=%s\n", g_apppath ? g_apppath : "<null>");
+
+ debug("main: Configuring\n");
+ configure();
+ return EXIT_SUCCESS;
+}
diff --git a/nuttx/tools/configure.sh b/nuttx/tools/configure.sh
index ffa997178..89f2e2fbc 100755
--- a/nuttx/tools/configure.sh
+++ b/nuttx/tools/configure.sh
@@ -125,7 +125,6 @@ else
fi
src_config="${configpath}/defconfig"
-tmp_config="${TOPDIR}/.configX"
dest_config="${TOPDIR}/.config"
if [ ! -r "${src_config}" ]; then
@@ -201,7 +200,7 @@ if [ "X${have_setenv}" = "Xy" ]; then
{ echo "Failed to copy ${src_setenv}" ; exit 8 ; }
chmod 755 "${dest_setenv}"
fi
-install "${src_config}" "${tmp_config}" || \
+install "${src_config}" "${dest_config}" || \
{ echo "Failed to copy \"${src_config}\"" ; exit 9 ; }
# If we did not use the CONFIG_APPS_DIR that was in the defconfig config file,
@@ -209,14 +208,14 @@ install "${src_config}" "${tmp_config}" || \
# file
if [ "X${defappdir}" = "Xy" ]; then
- sed -i -e "/^CONFIG_APPS_DIR/d" "${tmp_config}"
- echo "" >> "${tmp_config}"
- echo "# Application configuration" >> "${tmp_config}"
- echo "" >> "${tmp_config}"
+ sed -i -e "/^CONFIG_APPS_DIR/d" "${dest_config}"
+ echo "" >> "${dest_config}"
+ echo "# Application configuration" >> "${dest_config}"
+ echo "" >> "${dest_config}"
if [ "X${winnative}" = "Xy" ]; then
- echo "CONFIG_APPS_DIR=\"$winappdir\"" >> "${tmp_config}"
+ echo "CONFIG_APPS_DIR=\"$winappdir\"" >> "${dest_config}"
else
- echo "CONFIG_APPS_DIR=\"$posappdir\"" >> "${tmp_config}"
+ echo "CONFIG_APPS_DIR=\"$posappdir\"" >> "${dest_config}"
fi
fi
@@ -232,9 +231,3 @@ if [ ! -z "${appdir}" -a "X${newconfig}" != "Xy" ]; then
{ echo "Failed to copy ${configpath}/appconfig" ; exit 10 ; }
fi
fi
-
-# install the final .configX only if it differs from any existing
-# .config file.
-
-install "${tmp_config}" "${dest_config}"
-rm -f "${tmp_config}"
diff --git a/nuttx/tools/kconfig.bat b/nuttx/tools/kconfig.bat
new file mode 100755
index 000000000..db01e7515
--- /dev/null
+++ b/nuttx/tools/kconfig.bat
@@ -0,0 +1,131 @@
+@echo off
+
+rem tools/kconfig.bat
+rem
+rem Copyright (C) 2012 Gregory Nutt. All rights reserved.
+rem Author: Gregory Nutt <gnutt@nuttx.org>
+rem
+rem Redistribution and use in source and binary forms, with or without
+rem modification, are permitted provided that the following conditions
+rem are met:
+rem
+rem 1. Redistributions of source code must retain the above copyright
+rem notice, this list of conditions and the following disclaimer.
+rem 2. Redistributions in binary form must reproduce the above copyright
+rem notice, this list of conditions and the following disclaimer in
+rem the documentation and/or other materials provided with the
+rem distribution.
+rem 3. Neither the name NuttX nor the names of its contributors may be
+rem used to endorse or promote products derived from this software
+rem without specific prior written permission.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+rem FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+rem COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+rem OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+rem AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+rem LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+rem ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+rem POSSIBILITY OF SUCH DAMAGE.
+rem
+
+rem Remember the state of the PATH variable on entry
+
+set oldpath=%PATH%
+
+rem Handle command line options
+
+set action=%1
+shift
+if "%action%"=="" goto :MissingArgument
+
+set appsdir=..\apps
+set cygwindir=C:\Cygwin
+
+:ArgLoop
+
+if "%1"=="" goto :CheckArguments
+
+if "%1"=="-a" (
+ shift
+ set appsdir=%1
+ goto :NextArg
+)
+
+if "%1"=="-c" (
+ shift
+ set cygwindir=%1
+ goto :NextArg
+)
+
+echo ERROR: Unrecognized option: %1
+goto :ShowUsage
+
+:NextArg
+shift
+goto :ArgLoop
+
+rem Verify that all of the paths are valid
+
+:CheckArguments
+if exist "%appsdir%" goto :CheckCygwinDir
+
+echo ERROR: %appsdir% does not exist
+goto :ShowUsage
+
+:CheckCygwinDir
+
+if exist "%cygwindir%" goto :SetPath
+
+echo ERROR: %cygwindir% does not exist
+goto :ShowUsage
+
+rem Setup some required environment variables and PATH settings
+
+:SetPath
+set PATH=%cygwindir%\usr\local\bin;%cygwindir%\usr\bin;%cygwindir%\bin;%PATH%
+set APPSDIR=%appsdir%
+
+rem Execute the requested action
+
+if "%action%"=="config" goto :DoConfig
+if "%action%"=="oldconfig" goto :DoOldConfig
+if "%action%"=="menuconfig" goto :DoMenuConfig
+
+echo ERROR: Unrecognized action: %action%
+goto :ShowUsage
+
+:DoConfig
+kconfig-conf Kconfig
+goto End
+
+:DoOldConfig
+kconfig-conf --oldconfig Kconfig
+goto End
+
+:DoMenuConfig
+kconfig-mconf Kconfig
+goto End
+
+:MissingArgument
+
+echo ERROR: Missing required argument
+
+:ShowUsage
+echo USAGE: %0 ^<action^> [-a ^<appsdir^>] [-c ^<cygwindir^>]
+echo Where:
+echo ^<action^> is one of config, oldconf, or menuconfig
+echo ^<appsdir^> is the relative path to the apps\ directory.
+echo This defaults to ..\apps
+echo ^<cygwindir^> is the relative path to the Cygwin installation
+echo directory. This defaults to C:\Cygwin
+
+rem Restore the original PATH settings
+
+:End
+set PATH=%oldpath%
+
diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c
index 3e55f5097..d8d09df34 100644
--- a/nuttx/tools/mkconfig.c
+++ b/nuttx/tools/mkconfig.c
@@ -1,7 +1,7 @@
/****************************************************************************
* tools/mkconfig.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
#include <stdlib.h>
#include <errno.h>
-#include "cfgparser.h"
+#include "cfgdefine.h"
/****************************************************************************
* Pre-processor Definitions
@@ -99,7 +99,7 @@ int main(int argc, char **argv, char **envp)
printf("#ifndef __INCLUDE_NUTTX_CONFIG_H\n");
printf("#define __INCLUDE_NUTTX_CONFIG_H\n\n");
printf("/* Architecture-specific options *************************/\n\n");
- parse_file(stream);
+ generate_definitions(stream);
printf("\n/* Sanity Checks *****************************************/\n\n");
printf("/* If this is an NXFLAT, external build, then make sure that\n");
printf(" * NXFLAT support is enabled in the base code.\n");
@@ -116,7 +116,7 @@ int main(int argc, char **argv, char **envp)
printf(" * configured (at present, NXFLAT is the only supported binary.\n");
printf(" * format).\n");
printf(" */\n\n");
- printf("#if !defined(CONFIG_NXFLAT) && !defined(CONFIG_ELF)\n");
+ printf("#if !defined(CONFIG_NXFLAT) && !defined(CONFIG_ELF) && !defined(CONFIG_BUILTIN)\n");
printf("# undef CONFIG_BINFMT_DISABLE\n");
printf("# define CONFIG_BINFMT_DISABLE 1\n");
printf("#endif\n\n");
@@ -213,14 +213,14 @@ int main(int argc, char **argv, char **envp)
printf("# undef CONFIG_FS_FAT\n");
printf("# undef CONFIG_FS_ROMFS\n");
printf("# undef CONFIG_FS_NXFFS\n");
- printf("# undef CONFIG_APPS_BINDIR\n");
+ printf("# undef CONFIG_FS_BINFS\n");
printf("# undef CONFIG_NFS\n");
printf("#endif\n\n");
printf("/* Check if any readable and writable filesystem (OR USB storage) is supported */\n\n");
printf("#undef CONFIG_FS_READABLE\n");
printf("#undef CONFIG_FS_WRITABLE\n");
printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBMSC) || \\\n");
- printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS)\n");
+ printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_FS_BINFS) || defined(CONFIG_NFS)\n");
printf("# define CONFIG_FS_READABLE 1\n");
printf("#endif\n\n");
printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBMSC) || defined(CONFIG_FS_NXFFS) || \\\n");
diff --git a/nuttx/tools/mksyscall.c b/nuttx/tools/mksyscall.c
index a75e82d28..1d172a2a1 100644
--- a/nuttx/tools/mksyscall.c
+++ b/nuttx/tools/mksyscall.c
@@ -61,11 +61,11 @@ static FILE *g_stubstream;
* Private Functions
****************************************************************************/
-static bool is_vararg(const char *type, int index, int nparms)
+static bool is_vararg(const char *type, int ndx, int nparms)
{
if (strcmp(type,"...") == 0)
{
- if (index != (nparms-1))
+ if (ndx != (nparms-1))
{
fprintf(stderr, "%d: ... is not the last in the argument list\n", g_lineno);
exit(11);
@@ -75,8 +75,10 @@ static bool is_vararg(const char *type, int index, int nparms)
fprintf(stderr, "%d: Need one parameter before ...\n", g_lineno);
exit(14);
}
+
return true;
}
+
return false;
}
diff --git a/nuttx/tools/mkversion.c b/nuttx/tools/mkversion.c
index 32068df38..c6b00c5e5 100644
--- a/nuttx/tools/mkversion.c
+++ b/nuttx/tools/mkversion.c
@@ -41,7 +41,7 @@
#include <stdlib.h>
#include <errno.h>
-#include "cfgparser.h"
+#include "cfgdefine.h"
/****************************************************************************
* Definitions
@@ -98,7 +98,7 @@ int main(int argc, char **argv, char **envp)
printf("/* version.h -- Autogenerated! Do not edit. */\n\n");
printf("#ifndef __INCLUDE_NUTTX_VERSION_H\n");
printf("#define __INCLUDE_NUTTX_VERSION_H\n\n");
- parse_file(stream);
+ generate_definitions(stream);
printf("\n#define CONFIG_VERSION ((CONFIG_VERSION_MAJOR << 8) | (CONFIG_VERSION_MINOR))\n\n");
printf("#endif /* __INCLUDE_NUTTX_VERSION_H */\n");
fclose(stream);