summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-09-03 18:36:43 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-09-03 18:36:43 -0600
commit5bb4b088cd539cf96ed1e08ae7bb4c5973cd5d33 (patch)
treeacce15ae06fa96cd5de565d1aa1690f5e8716de9
parentc6e48b65d0729bc4fffbf57dac4fb8c97a35fd63 (diff)
downloadnuttx-5bb4b088cd539cf96ed1e08ae7bb4c5973cd5d33.tar.gz
nuttx-5bb4b088cd539cf96ed1e08ae7bb4c5973cd5d33.tar.bz2
nuttx-5bb4b088cd539cf96ed1e08ae7bb4c5973cd5d33.zip
Add capability to perform initial board initialization on a separate worker thread.
-rw-r--r--nuttx/configs/sama5d4-ek/kernel/defconfig3
-rw-r--r--nuttx/sched/Kconfig34
-rw-r--r--nuttx/sched/init/os_bringup.c113
3 files changed, 133 insertions, 17 deletions
diff --git a/nuttx/configs/sama5d4-ek/kernel/defconfig b/nuttx/configs/sama5d4-ek/kernel/defconfig
index b92fab7ae..1df0c099f 100644
--- a/nuttx/configs/sama5d4-ek/kernel/defconfig
+++ b/nuttx/configs/sama5d4-ek/kernel/defconfig
@@ -419,6 +419,9 @@ CONFIG_NAME_MAX=32
# RTOS hooks
#
CONFIG_BOARD_INITIALIZE=y
+CONFIG_BOARD_INITTHREAD=y
+CONFIG_BOARD_INITTHREAD_STACKSIZE=2048
+CONFIG_BOARD_INITTHREAD_PRIORITY=240
# CONFIG_SCHED_STARTHOOK is not set
# CONFIG_SCHED_ATEXIT is not set
# CONFIG_SCHED_ONEXIT is not set
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index 5068a4e96..12752da75 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -651,6 +651,40 @@ config BOARD_INITIALIZE
phase may be used, for example, to initialize board-specific
device drivers.
+if BOARD_INITIALIZE
+
+config BOARD_INITTHREAD
+ bool "Board initialization thread"
+ default n
+ ---help---
+ Some initialization operations cannot be performed on the start-up,
+ initialization thread. That is because the initialization thread
+ cannot wait for event. If waiting is required as part of the board
+ initialization then this option must be selected. Waiting may be
+ required, for example, to mount a file system or or initialize a
+ device such as an SD card.
+
+if BOARD_INITTHREAD
+
+config BOARD_INITTHREAD_STACKSIZE
+ int "Board initialization thread stack size"
+ default 2048
+ ---help---
+ The size of the stack to allocate when starting the board
+ initialization thread.
+
+config BOARD_INITTHREAD_PRIORITY
+ int "Board initialization thread priority"
+ default 240
+ ---help---
+ The priority of the board initialization thread. This priority is
+ not a critical setting. No other application threads will be
+ started until the board initialization is completed. Hence, there
+ is very little competition for the CPU.
+
+endif # BOARD_INITTHREAD
+endif # BOARD_INITIALIZE
+
config SCHED_STARTHOOK
bool "Enable startup hook"
default n
diff --git a/nuttx/sched/init/os_bringup.c b/nuttx/sched/init/os_bringup.c
index f85a33ef1..23eaed044 100644
--- a/nuttx/sched/init/os_bringup.c
+++ b/nuttx/sched/init/os_bringup.c
@@ -260,10 +260,11 @@ static inline void os_workqueues(void)
#endif /* CONFIG_SCHED_WORKQUEUE */
/****************************************************************************
- * Name: os_init_thread
+ * Name: os_start_application
*
* Description:
- * Start the application initialization thread.
+ * Execute the board initialization function (if so configured) and start
+ * the application initialization thread.
*
* Input Parameters:
* None
@@ -274,18 +275,26 @@ static inline void os_workqueues(void)
****************************************************************************/
#if defined(CONFIG_INIT_ENTRYPOINT)
-static inline void os_init_thread(void)
+static inline void os_do_appstart(void)
{
int taskid;
- svdbg("Starting init thread\n");
+#ifdef CONFIG_BOARD_INITIALIZE
+ /* Perform any last-minute, board-specific initialization, if so
+ * configured.
+ */
- /* Start the application initialization ask. In a flat build, this is
+ board_initialize();
+#endif
+
+ /* Start the application initialization task. In a flat build, this is
* entrypoint is given by the definitions, CONFIG_USER_ENTRYPOINT. In
* the protected build, however, we must get the address of the
* entrypoint from the header at the beginning of the user-space blob.
*/
+ svdbg("Starting init thread\n");
+
#ifdef CONFIG_BUILD_PROTECTED
DEBUGASSERT(USERSPACE->us_entrypoint != NULL);
taskid = task_create("init", SCHED_PRIORITY_DEFAULT,
@@ -301,10 +310,23 @@ static inline void os_init_thread(void)
}
#elif defined(CONFIG_INIT_FILEPATH)
-static inline void os_init_thread(void)
+static inline void os_do_appstart(void)
{
int ret;
+#ifdef CONFIG_BOARD_INITIALIZE
+ /* Perform any last-minute, board-specific initialization, if so
+ * configured.
+ */
+
+ board_initialize();
+#endif
+
+ /* Start the application initialization program from a program in a
+ * mounted file system. Presumably the file system was mounted as part
+ * of the board_initialize() operation.
+ */
+
svdbg("Starting init task: %s\n", CONFIG_USER_INITPATH);
ret = exec(CONFIG_USER_INITPATH, NULL, CONFIG_INIT_SYMTAB,
@@ -313,7 +335,7 @@ static inline void os_init_thread(void)
}
#elif defined(CONFIG_INIT_NONE)
-# define os_init_thread()
+# define os_do_appstart()
#else
# error "Cannot start initialization thread"
@@ -321,6 +343,71 @@ static inline void os_init_thread(void)
#endif
/****************************************************************************
+ * Name: os_start_task
+ *
+ * Description:
+ * This is the framework for a short duration worker thread. It off-loads
+ * the board initialization and application start-up from the limited
+ * start-up, initialization thread to a more robust kernel thread.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BOARD_INITTHREAD
+static int os_start_task(int argc, FAR char **argv)
+{
+ /* Do the board/application initialization and exit */
+
+ os_do_appstart();
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: os_start_application
+ *
+ * Description:
+ * Execute the board initialization function (if so configured) and start
+ * the application initialization thread. This will be done either on the
+ * thread of execution of the caller or on a separate thread of execution
+ * if so configured.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void os_start_application(void)
+{
+#ifdef CONFIG_BOARD_INITTHREAD
+ int taskid;
+
+ /* Do the board/application initialization on a separate thread of
+ * execution.
+ */
+
+ taskid = kernel_thread("AppBringUp", CONFIG_BOARD_INITTHREAD_PRIORITY,
+ CONFIG_BOARD_INITTHREAD_STACKSIZE,
+ (main_t)os_start_task, (FAR char * const *)NULL);
+ ASSERT(taskid > 0);
+
+#else
+ /* Do the board/application initialization on this thread of execution. */
+
+ os_do_appstart();
+
+#endif
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -384,20 +471,12 @@ int os_bringup(void)
os_workqueues();
- /* Perform any last-minute, board-specific initialization, if so
- * configured.
- */
-
-#ifdef CONFIG_BOARD_INITIALIZE
- board_initialize();
-#endif
-
/* Once the operating system has been initialized, the system must be
* started by spawning the user initialization thread of execution. This
- * is the first user-mode thread.
+ * will be the first user-mode thread.
*/
- os_init_thread();
+ os_start_application();
/* We an save a few bytes by discarding the IDLE thread's environment. */