diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-03-21 17:35:08 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-03-21 17:35:08 +0000 |
commit | aee2b5f63b4eef1751605731688fd80d20593b81 (patch) | |
tree | 936c832a3c90c8ba410bcd050d0c97c4cfdb7cb0 | |
parent | 55a46f0500f36567ce352048454534135aff92f2 (diff) | |
download | px4-nuttx-aee2b5f63b4eef1751605731688fd80d20593b81.tar.gz px4-nuttx-aee2b5f63b4eef1751605731688fd80d20593b81.tar.bz2 px4-nuttx-aee2b5f63b4eef1751605731688fd80d20593b81.zip |
Add a up_stack_frame() interface to allocate a frame of data on a task's stack.
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5768 42af7a65-404d-4744-a932-0658087f49c3
23 files changed, 1554 insertions, 101 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 7f6a2b421..3c427ff29 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4407,5 +4407,7 @@ thread, use the kernel allocator so that the kernel thread stacks are protected from user application meddling (2013-03-20). * arch/arm/src/armv[6|7]-m/up_scall.c: Fix parameter passing for - all system call inline functions with > 3 parameters (2013-03-20) - + all system call inline functions with > 3 parameters (2013-03-20) + * arch/*/src/common/up_stackframe.c and include/nuttx/arch.h: Add + and new interface to set aside memory on the stack. This will be + used at least in the kernel build to hold task arguments 2013-03-21). diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index 709c5a3a6..2fa0b2a71 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -78,22 +78,23 @@ <a href="#upinitialstate">4.1.3 <code>up_initial_state()</code></a><br> <a href="#upcreatestack">4.1.4 <code>up_create_stack()</code></a><br> <a href="#upusestack">4.1.5 <code>up_use_stack()</code></a><br> - <a href="#upreleasestack">4.1.6 <code>up_release_stack()</code></a><br> - <a href="#upunblocktask">4.1.7 <code>up_unblock_task()</code></a><br> - <a href="#upblocktask">4.1.8 <code>up_block_task()</code></a><br> - <a href="#upreleasepending">4.1.9 <code>up_release_pending()</code></a><br> - <a href="#upreprioritizertr">4.1.10 <code>up_reprioritize_rtr()</code></a><br> - <a href="#_exit">4.1.11 <code>_exit()</code></a><br> - <a href="#upassert">4.1.12 <code>up_assert()</code></a><br> - <a href="#upschedulesigaction">4.1.13 <code>up_schedule_sigaction()</code></a><br> - <a href="#upallocateheap">4.1.14 <code>up_allocate_heap()</code></a><br> - <a href="#upinterruptcontext">4.1.15 <code>up_interrupt_context()</code></a><br> - <a href="#updisableirq">4.1.16 <code>up_disable_irq()</code></a><br> - <a href="#upenableirq">4.1.17 <code>up_enable_irq()</code></a><br> - <a href="#upprioritizeirq">4.1.18 <code>up_prioritize_irq()</code></a></br> - <a href="#upputc">4.1.19 <code>up_putc()</code></a></br> - <a href="#systemtime">4.1.20 System Time and Clock</a><br> - <a href="#addrenv">4.1.21 Address Environments</a> + <a href="#upstackframe">4.1.6 <code>up_stack_frame()</code></a><br> + <a href="#upreleasestack">4.1.7 <code>up_release_stack()</code></a><br> + <a href="#upunblocktask">4.1.8 <code>up_unblock_task()</code></a><br> + <a href="#upblocktask">4.1.9 <code>up_block_task()</code></a><br> + <a href="#upreleasepending">4.1.10 <code>up_release_pending()</code></a><br> + <a href="#upreprioritizertr">4.1.11 <code>up_reprioritize_rtr()</code></a><br> + <a href="#_exit">4.1.12 <code>_exit()</code></a><br> + <a href="#upassert">4.1.13 <code>up_assert()</code></a><br> + <a href="#upschedulesigaction">4.1.14 <code>up_schedule_sigaction()</code></a><br> + <a href="#upallocateheap">4.1.15 <code>up_allocate_heap()</code></a><br> + <a href="#upinterruptcontext">4.1.16 <code>up_interrupt_context()</code></a><br> + <a href="#updisableirq">4.1.17 <code>up_disable_irq()</code></a><br> + <a href="#upenableirq">4.1.18 <code>up_enable_irq()</code></a><br> + <a href="#upprioritizeirq">4.1.19 <code>up_prioritize_irq()</code></a></br> + <a href="#upputc">4.1.20 <code>up_putc()</code></a></br> + <a href="#systemtime">4.1.21 System Time and Clock</a><br> + <a href="#addrenv">4.1.22 Address Environments</a> </ul> <a href="#exports">4.2 APIs Exported by NuttX to Architecture-Specific Logic</a> <ul> @@ -1702,7 +1703,58 @@ The system can be re-made subsequently by just typing <code>make</code>. The TCB flags will always be set to provide the task type to <code>up_use_stack()</code> if the information needs that information. </p> -<h3><a name="upreleasestack">4.1.6 <code>up_release_stack()</code></a></h3> + +<h3><a name="upstackframe">4.1.6 <code>up_stack_frame()</code></a></h3> +<p><b>Prototype</b>: <code>FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size);</code></p> + +<p> + <b>Description</b>. + Allocate a stack frame in the TCB's stack to hold thread-specific data. + This function may be called anytime after <code>up_create_stack()</code> or <code>up_use_stack()</code> have been called but before the task has been started. +</p> +<p> + Thread data may be kept in the stack (instead of in the TCB) if it is accessed by the user code directory. + This includes such things as <code>argv[]</code>. + The stack memory is guaranteed to be in the same protection domain as the thread. +</p> +<p> + The following TCB fields will be re-initialized: +</p> +<ul> + <li> + <code>adj_stack_size</code>: Stack size after removal of the stack frame from the stack. + </li> + <li> + <code>adj_stack_ptr</code>: Adjusted initial stack pointer after the frame has been removed from the stack. + This will still be the initial value of the stack pointer when the task is started. + </li> +</ul> +<p> + This API is <i>NOT</i> required if <code>CONFIG_NUTTX_KERNEL</code> is undefined or if <code>CONFIG_CUSTOM_STACK</code> is defined. +</p> +<p><b>Input Parameters:</b></p> +<ul> + <li> + <p> + <code>tcb</code>: + The TCB of new task. + </p> + </li> + <li> + <p> + <code>frame_size</code>: + The size of the stack frame to allocate. + </p> + </li> +</ul> +<p> + <b>Returned Value:</b> + A pointer to bottom of the allocated stack frame. + NULL will be returned on any failures. + The alignment of the returned value is the same as the alignment of the stack itself +</p> + +<h3><a name="upreleasestack">4.1.7 <code>up_release_stack()</code></a></h3> <p><b>Prototype</b>: <code>void up_release_stack(FAR struct tcb_s *dtcb);</code></p> <p><b>Description</b>. @@ -1718,6 +1770,7 @@ The system can be re-made subsequently by just typing <code>make</code>. <p> <code>dtcb</code>: The TCB containing information about the stack to be released. + </p> </li> <li> <p> @@ -1740,7 +1793,7 @@ The system can be re-made subsequently by just typing <code>make</code>. </li> </ul> -<h3><a name="upunblocktask">4.1.7 <code>up_unblock_task()</code></a></h3> +<h3><a name="upunblocktask">4.1.8 <code>up_unblock_task()</code></a></h3> <p><b>Prototype</b>: <code>void up_unblock_task(FAR struct tcb_s *tcb);</code></p> <p><b>Description</b>. @@ -1763,7 +1816,7 @@ The system can be re-made subsequently by just typing <code>make</code>. </li> </ul> -<h3><a name="upblocktask">4.1.8 <code>up_block_task()</code></a></h3> +<h3><a name="upblocktask">4.1.9 <code>up_block_task()</code></a></h3> <p><b>Prototype</b>: <code>void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state);</code></p> <p><b>Description</b>. @@ -1789,7 +1842,7 @@ The system can be re-made subsequently by just typing <code>make</code>. </li> </ul> -<h3><a name="upreleasepending">4.1.9 <code>up_release_pending()</code></a></h3> +<h3><a name="upreleasepending">4.1.10 <code>up_release_pending()</code></a></h3> <p><b>Prototype</b>: <code>void up_release_pending(void);</code></p> <p><b>Description</b>. @@ -1806,7 +1859,7 @@ The system can be re-made subsequently by just typing <code>make</code>. function is called. </p> -<h3><a name="upreprioritizertr">4.1.10 <code>up_reprioritize_rtr()</code></a></h3> +<h3><a name="upreprioritizertr">4.1.11 <code>up_reprioritize_rtr()</code></a></h3> <p><b>Prototype</b>: <code>void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority);</code></p> <p><b>Description</b>. @@ -1841,7 +1894,7 @@ The system can be re-made subsequently by just typing <code>make</code>. </li> </ul> -<h3><a name="_exit">4.1.11 <code>_exit()</code></a></h3> +<h3><a name="_exit">4.1.12 <code>_exit()</code></a></h3> <p><b>Prototype</b>: <code>void _exit(int status) noreturn_function;</code></p> <p><b>Description</b>. @@ -1855,7 +1908,7 @@ The system can be re-made subsequently by just typing <code>make</code>. before performing scheduling operations. </p> -<h3><a name="upassert">4.1.12 <code>up_assert()</code></a></h3> +<h3><a name="upassert">4.1.13 <code>up_assert()</code></a></h3> <p><b>Prototype</b>:<br> <code>void up_assert(FAR const uint8_t *filename, int linenum);</code></br> <code>void up_assert_code(FAR const uint8_t *filename, int linenum, int error_code);</code></br> @@ -1866,7 +1919,7 @@ The system can be re-made subsequently by just typing <code>make</code>. way. </p> -<h3><a name="upschedulesigaction">4.1.13 <code>up_schedule_sigaction()</code></a></h3> +<h3><a name="upschedulesigaction">4.1.14 <code>up_schedule_sigaction()</code></a></h3> <p><b>Prototype</b>: <code>void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver);</code> </p> @@ -1913,7 +1966,7 @@ The system can be re-made subsequently by just typing <code>make</code>. is defined. </p> -<h3><a name="upallocateheap">4.1.14 <code>up_allocate_heap()</code></a></h3> +<h3><a name="upallocateheap">4.1.15 <code>up_allocate_heap()</code></a></h3> <p><b>Prototype</b>: <code>void up_allocate_heap(FAR void **heap_start, size_t *heap_size);</code></p> <p><b>Description</b>. @@ -1924,14 +1977,14 @@ The system can be re-made subsequently by just typing <code>make</code>. If a protected kernel-space heap is provided, the kernel heap must be allocated (and protected) by an analogous <code>up_allocate_kheap()</code>. </p> -<h3><a name="upinterruptcontext">4.1.15 <code>up_interrupt_context()</code></a></h3> +<h3><a name="upinterruptcontext">4.1.16 <code>up_interrupt_context()</code></a></h3> <p><b>Prototype</b>: <code>bool up_interrupt_context(void)</code></p> <p><b>Description</b>. Return true if we are currently executing in the interrupt handler context. </p> -<h3><a name="updisableirq">4.1.16 <code>up_disable_irq()</code></a></h3> +<h3><a name="updisableirq">4.1.17 <code>up_disable_irq()</code></a></h3> <p><b>Prototype</b>:</p> <ul><pre> #ifndef CONFIG_ARCH_NOINTC @@ -1958,7 +2011,7 @@ The system can be re-made subsequently by just typing <code>make</code>. avoided in common implementations where possible. </p> -<h3><a name="upenableirq">4.1.17 <code>up_enable_irq()</code></a></h3> +<h3><a name="upenableirq">4.1.18 <code>up_enable_irq()</code></a></h3> <p><b>Prototype</b>:</p> <ul><pre> #ifndef CONFIG_ARCH_NOINTC @@ -1979,7 +2032,7 @@ The system can be re-made subsequently by just typing <code>make</code>. avoided in common implementations where possible. </p> -<h3><a name="upprioritizeirq">4.1.18 <code>up_prioritize_irq()</code></a></h3> +<h3><a name="upprioritizeirq">4.1.19 <code>up_prioritize_irq()</code></a></h3> <p><b>Prototype</b>:</p> <ul><pre> #ifdef CONFIG_ARCH_IRQPRIO @@ -1996,7 +2049,7 @@ The system can be re-made subsequently by just typing <code>make</code>. avoided in common implementations where possible. </p> -<h3><a name="upputc">4.1.19 <code>up_putc()</code></a></h3> +<h3><a name="upputc">4.1.20 <code>up_putc()</code></a></h3> <p><b>Prototype</b>: <code>int up_putc(int ch);</code></p> <p><b>Description</b>. @@ -2004,9 +2057,9 @@ The system can be re-made subsequently by just typing <code>make</code>. Output one character on the console </p> -<h3><a name="systemtime">4.1.20 System Time and Clock</a></h3> +<h3><a name="systemtime">4.1.21 System Time and Clock</a></h3> -<h4>4.1.20.1 Basic System Timer</h4> +<h4>4.1.21.1 Basic System Timer</h4> <p><b>System Timer</b> In most implementations, system time is provided by a timer interrupt. @@ -2089,7 +2142,7 @@ else In this way, the timer interval is controlled from interrupt-to-interrupt to produce an average frequency of exactly 100Hz. </p> -<h4>4.1.20.1 Hardware</h4> +<h4>4.1.21.2 Hardware</h4> <p> To enable hardware module use the following configuration options: <p> @@ -2144,7 +2197,7 @@ else </li> </ul> -<h4>4.1.20.2 System Tick and Time</h4> +<h4>4.1.21.3 System Tick and Time</h4> <p> The system tick is represented by:: </p> @@ -2167,7 +2220,7 @@ else To retrieve that variable use: </p> -<h3><a name="addrenv">4.1.21 Address Environments</a></h3> +<h3><a name="addrenv">4.1.22 Address Environments</a></h3> <p> CPUs that support memory management units (MMUs) may provide <i>address environments</i> within which tasks and their child threads execute. @@ -2191,27 +2244,27 @@ else </p> <ul> <li> - <a href="#up_addrenv_create">4.1.21.1 <code>up_addrenv_create()</code></a>: + <a href="#up_addrenv_create">4.1.22.1 <code>up_addrenv_create()</code></a>: Create an address environment. </li> <li> - <a href="#up_addrenv_vaddr">4.1.21.2 <code>up_addrenv_vaddr()</code></a>: + <a href="#up_addrenv_vaddr">4.1.22.2 <code>up_addrenv_vaddr()</code></a>: Returns the virtual base address of the address environment. </li> <li> - <a href="#up_addrenv_select">4.1.21.3 <code>up_addrenv_select()</code></a>: + <a href="#up_addrenv_select">4.1.22.3 <code>up_addrenv_select()</code></a>: Instantiate an address environment. </li> <li> - <a href="#up_addrenv_restore">4.1.21.4 <code>up_addrenv_restore()</code></a>: + <a href="#up_addrenv_restore">4.1.22.4 <code>up_addrenv_restore()</code></a>: Restore an address environment. </li> <li> - <a href="#up_addrenv_destroy">4.1.21.5 <code>up_addrenv_destroy()</code></a>: + <a href="#up_addrenv_destroy">4.1.22.5 <code>up_addrenv_destroy()</code></a>: Destroy an address environment. </li> <li> - <a href="#up_addrenv_assign">4.1.21.6 <code>up_addrenv_assign()</code></a>: + <a href="#up_addrenv_assign">4.1.22.6 <code>up_addrenv_assign()</code></a>: Assign an address environment to a TCB. </li> </ul> @@ -2224,12 +2277,12 @@ else </p> <ul> <li> - <a href="#up_addrenv_share">4.1.21.7 <code>up_addrenv_share()</code></a>: + <a href="#up_addrenv_share">4.1.22.7 <code>up_addrenv_share()</code></a>: Clone the address environment assigned to one TCB to another. This operation is done when a pthread is created that share's the same address environment. </li> <li> - <a href="#up_addrenv_release">4.1.21.8 <code>up_addrenv_release()</code></a>: + <a href="#up_addrenv_release">4.1.22.8 <code>up_addrenv_release()</code></a>: Release the TCB's reference to an address environment when a task/thread exits. </li> </ul> @@ -2237,7 +2290,7 @@ else </ol> -<h4><a name="up_addrenv_create">4.1.21.1 <code>up_addrenv_create()</code></a></h4> +<h4><a name="up_addrenv_create">4.1.22.1 <code>up_addrenv_create()</code></a></h4> <p><b>Prototype</b>:</p> <ul> <code>int up_addrenv_create(size_t envsize, FAR task_addrenv_t *addrenv);</code> @@ -2257,7 +2310,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_vaddr">4.1.21.2 <code>up_addrenv_vaddr()</code></a></h4> +<h4><a name="up_addrenv_vaddr">4.1.22.2 <code>up_addrenv_vaddr()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_vaddr(FAR task_addrenv_t addrenv, FAR void **vaddr);</code> @@ -2277,7 +2330,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_select">4.1.21.3 <code>up_addrenv_select()</code></a></h4> +<h4><a name="up_addrenv_select">4.1.22.3 <code>up_addrenv_select()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_select(task_addrenv_t addrenv, hw_addrenv_t *oldenv);</code> @@ -2301,7 +2354,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_restore">4.1.21.4 <code>up_addrenv_restore()</code></a></h4> +<h4><a name="up_addrenv_restore">4.1.22.4 <code>up_addrenv_restore()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_restore(hw_addrenv_t oldenv);</code> @@ -2320,7 +2373,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_destroy">4.1.21.5 <code>up_addrenv_destroy()</code></a></h4> +<h4><a name="up_addrenv_destroy">4.1.22.5 <code>up_addrenv_destroy()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_destroy(task_addrenv_t addrenv);</code> @@ -2338,7 +2391,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_assign">4.1.21.6 <code>up_addrenv_assign()</code></a></h4> +<h4><a name="up_addrenv_assign">4.1.22.6 <code>up_addrenv_assign()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_assign(task_addrenv_t addrenv, FAR struct tcb_s *tcb);</code> @@ -2357,7 +2410,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_share">4.1.21.7 <code>up_addrenv_share()</code></a></h4> +<h4><a name="up_addrenv_share">4.1.22.7 <code>up_addrenv_share()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_share(FAR const struct tcb_s *ptcb, FAR struct tcb_s *ctcb);</code> @@ -2377,7 +2430,7 @@ else Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h4><a name="up_addrenv_release">4.1.21.8 <code>up_addrenv_release()</code></a></h4> +<h4><a name="up_addrenv_release">4.1.22.8 <code>up_addrenv_release()</code></a></h4> <p><b>Prototype</b>:<p> <ul> <code>int up_addrenv_release(FAR struct tcb_s *tcb);</code> diff --git a/nuttx/arch/arm/src/common/up_stackframe.c b/nuttx/arch/arm/src/common/up_stackframe.c new file mode 100644 index 000000000..3720d334a --- /dev/null +++ b/nuttx/arch/arm/src/common/up_stackframe.c @@ -0,0 +1,144 @@ +/**************************************************************************** + * arch/arm/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* 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 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/arm/src/lpc17xx/Make.defs b/nuttx/arch/arm/src/lpc17xx/Make.defs index 469165387..0fec22d12 100644 --- a/nuttx/arch/arm/src/lpc17xx/Make.defs +++ b/nuttx/arch/arm/src/lpc17xx/Make.defs @@ -68,7 +68,7 @@ CMN_ASRCS += up_memcpy.S endif ifeq ($(CONFIG_NUTTX_KERNEL),y) -CMN_CSRCS += up_mpu.c up_task_start.c up_pthread_start.c +CMN_CSRCS += up_mpu.c up_task_start.c up_pthread_start.c up_stackframe.c ifneq ($(CONFIG_DISABLE_SIGNALS),y) CMN_CSRCS += up_signal_handler.c endif diff --git a/nuttx/arch/arm/src/sam3u/Make.defs b/nuttx/arch/arm/src/sam3u/Make.defs index 16ca22401..4abca3b2c 100644 --- a/nuttx/arch/arm/src/sam3u/Make.defs +++ b/nuttx/arch/arm/src/sam3u/Make.defs @@ -60,7 +60,7 @@ CMN_ASRCS += up_memcpy.S endif ifeq ($(CONFIG_NUTTX_KERNEL),y) -CMN_CSRCS += up_mpu.c up_task_start.c up_pthread_start.c +CMN_CSRCS += up_mpu.c up_task_start.c up_pthread_start.c up_stackframe.c ifneq ($(CONFIG_DISABLE_SIGNALS),y) CMN_CSRCS += up_signal_handler.c endif diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c index 3986106d8..b8033fdd5 100644 --- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c +++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c @@ -1517,7 +1517,6 @@ static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt) DEBUGASSERT(privep && privep->ep.priv); priv = (FAR struct stm32_usbdev_s *)privep->ep.priv; - DEBUGASSERT(priv->ep0state == EP0STATE_SETUP_OUT); ullvdbg("EP0: bcnt=%d\n", bcnt); usbtrace(TRACE_READ(EP0), bcnt); diff --git a/nuttx/arch/avr/src/avr/up_stackframe.c b/nuttx/arch/avr/src/avr/up_stackframe.c new file mode 100644 index 000000000..39253e2b5 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_stackframe.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/avr/src/avr/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint8_t)); +} diff --git a/nuttx/arch/avr/src/avr32/up_stackframe.c b/nuttx/arch/avr/src/avr32/up_stackframe.c new file mode 100644 index 000000000..08c4cf51e --- /dev/null +++ b/nuttx/arch/avr/src/avr32/up_stackframe.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/avr/src/avr32/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* The AVR32 stack must be aligned at word (4 byte) boundaries. If necessary + * frame_size must be rounded up to the next boundary + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/hc/src/common/up_stackframe.c b/nuttx/arch/hc/src/common/up_stackframe.c new file mode 100644 index 000000000..0daa4f7da --- /dev/null +++ b/nuttx/arch/hc/src/common/up_stackframe.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/hc/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* The CPU12 stack should be aligned at half-word (2 byte) boundaries. If + * necessary frame_size must be rounded up to the next boundary + */ + +#define STACK_ALIGNMENT 2 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/mips/src/common/up_createstack.c b/nuttx/arch/mips/src/common/up_createstack.c index 6109797a3..e2a73fc7d 100644 --- a/nuttx/arch/mips/src/common/up_createstack.c +++ b/nuttx/arch/mips/src/common/up_createstack.c @@ -60,14 +60,14 @@ */ #ifdef CONFIG_LIBC_FLOATINGPOINT -# define CONFIG_STACK_ALIGNMENT 8 +# define STACK_ALIGNMENT 8 #else -# define CONFIG_STACK_ALIGNMENT 4 +# define STACK_ALIGNMENT 4 #endif /* Stack alignment macros */ -#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) #define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) #define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) diff --git a/nuttx/arch/mips/src/common/up_stackframe.c b/nuttx/arch/mips/src/common/up_stackframe.c new file mode 100644 index 000000000..9b473ecc6 --- /dev/null +++ b/nuttx/arch/mips/src/common/up_stackframe.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * arch/mips/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ +/* MIPS requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +# define STACK_ALIGNMENT 8 +#else +# define STACK_ALIGNMENT 4 +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/mips/src/common/up_usestack.c b/nuttx/arch/mips/src/common/up_usestack.c index b636a51d7..934ac8ed1 100644 --- a/nuttx/arch/mips/src/common/up_usestack.c +++ b/nuttx/arch/mips/src/common/up_usestack.c @@ -50,6 +50,26 @@ #include "up_internal.h" /**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* MIPS requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +# define STACK_ALIGNMENT 8 +#else +# define STACK_ALIGNMENT 4 +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** * Private Types ****************************************************************************/ @@ -107,21 +127,20 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) tcb->stack_alloc_ptr = stack; - /* MIPS uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. + /* MIPS uses a push-down stack: the stack grows toward loweraddresses in + * memory. The stack pointer register, points to the lowest, valid work + * address (the "top" of the stack). Items on the stack are referenced + * as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The MIPS stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* The MIPS stack must be aligned at word (4 byte) or double word (8 byte) + * boundaries. If necessary top_of_stack must be rounded down to the + * next boundary */ - top_of_stack &= ~3; + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; /* Save the adjusted stack values in the struct tcb_s */ diff --git a/nuttx/arch/rgmp/src/nuttx.c b/nuttx/arch/rgmp/src/nuttx.c index 79f97fcfc..f218b3f18 100644 --- a/nuttx/arch/rgmp/src/nuttx.c +++ b/nuttx/arch/rgmp/src/nuttx.c @@ -168,6 +168,31 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) return OK; } +#ifdef CONFIG_NUTTX_KERNEL +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = (frame_size + 3) & ~3; + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} +#endif + void up_release_stack(struct tcb_s *dtcb, uint8_t ttype) { /* Is there a stack allocated? */ diff --git a/nuttx/arch/sh/src/common/up_stackframe.c b/nuttx/arch/sh/src/common/up_stackframe.c new file mode 100644 index 000000000..b1ef4c6b4 --- /dev/null +++ b/nuttx/arch/sh/src/common/up_stackframe.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/sh/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ +/* The SH stack must be aligned at word (4 byte) boundaries. If necessary + * frame_size must be rounded up to the next boundary + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/sh/src/common/up_usestack.c b/nuttx/arch/sh/src/common/up_usestack.c index bcce3261c..e0f348045 100644 --- a/nuttx/arch/sh/src/common/up_usestack.c +++ b/nuttx/arch/sh/src/common/up_usestack.c @@ -107,18 +107,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) tcb->stack_alloc_ptr = stack; - /* The Arm7Tdmi uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. + /* The SH family uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the + * lowest, valid work address (the "top" of the stack). Items on the + * stack are referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The Arm7Tdmi stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* The SH stack must be aligned at word (4 byte) boundaries. If necessary + * top_of_stack must be rounded down to the next boundary */ top_of_stack &= ~3; diff --git a/nuttx/arch/sim/src/up_stackframe.c b/nuttx/arch/sim/src/up_stackframe.c new file mode 100644 index 000000000..4d62e6ec0 --- /dev/null +++ b/nuttx/arch/sim/src/up_stackframe.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/sim/src/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* Use a stack alignment of 4 bytes. If necessary frame_size must be rounded + * up to the next boundary + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/x86/src/i486/up_stackframe.c b/nuttx/arch/x86/src/i486/up_stackframe.c new file mode 100644 index 000000000..ea4edc07a --- /dev/null +++ b/nuttx/arch/x86/src/i486/up_stackframe.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * arch/x86/src/i486/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* The initial stack point is aligned at word (4 byte) boundaries. If + * necessary frame_size must be rounded up to the next boundary to retain + * this alignment. + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/z16/src/common/up_createstack.c b/nuttx/arch/z16/src/common/up_createstack.c index 2bd3a8951..69a413bde 100644 --- a/nuttx/arch/z16/src/common/up_createstack.c +++ b/nuttx/arch/z16/src/common/up_createstack.c @@ -171,18 +171,16 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) memset(tcb->stack_alloc_ptr, 0xaa, stack_size); #endif - /* The ZNeo uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. + /* The ZNeo uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the + * lowest, valid work address (the "top" of the stack). Items on + * the stack are referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The ZNeo stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* Align the stack to word (4 byte) boundaries. This is probably + * a greater alignement than is required. */ top_of_stack &= ~3; diff --git a/nuttx/arch/z16/src/common/up_stackframe.c b/nuttx/arch/z16/src/common/up_stackframe.c new file mode 100644 index 000000000..c11106542 --- /dev/null +++ b/nuttx/arch/z16/src/common/up_stackframe.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/z16/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ +/* Align the stack to word (4 byte) boundaries. This is probablya greater + * alignement than is required. + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/z16/src/common/up_usestack.c b/nuttx/arch/z16/src/common/up_usestack.c index 7b5effc45..eb725b7fb 100644 --- a/nuttx/arch/z16/src/common/up_usestack.c +++ b/nuttx/arch/z16/src/common/up_usestack.c @@ -107,18 +107,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) tcb->stack_alloc_ptr = stack; - /* The Arm7Tdmi uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. + /* The ZNEO uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the + * lowest, valid work address (the "top" of the stack). Items on + * the stack are referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The Arm7Tdmi stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* Align the stack to word (4 byte) boundaries. This is probably + * a greater alignement than is required. */ top_of_stack &= ~3; diff --git a/nuttx/arch/z80/src/common/up_stackframe.c b/nuttx/arch/z80/src/common/up_stackframe.c new file mode 100644 index 000000000..01a7b0881 --- /dev/null +++ b/nuttx/arch/z80/src/common/up_stackframe.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/z80/src/common/up_stackframe.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/types.h> +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ +/* The Z80 stack does not need to be aligned. Here is is aligned at word + * (4 byte) boundary. + */ + +#define STACK_ALIGNMENT 4 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/nuttx/arch/z80/src/common/up_usestack.c b/nuttx/arch/z80/src/common/up_usestack.c index 095b4f5d5..414040ec2 100644 --- a/nuttx/arch/z80/src/common/up_usestack.c +++ b/nuttx/arch/z80/src/common/up_usestack.c @@ -106,18 +106,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) tcb->stack_alloc_ptr = stack; - /* The Arm7Tdmi uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. + /* The Z80 uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the + * lowest, valid work address (the "top" of the stack). Items on + * the stack are* referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The Arm7Tdmi stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* The Z80 stack does not need to be aligned. Here is is aligned at + * word (4 byte) boundary. */ top_of_stack &= ~3; diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h index 18df38b52..6595b3911 100644 --- a/nuttx/include/nuttx/arch.h +++ b/nuttx/include/nuttx/arch.h @@ -204,7 +204,8 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype); * initial value of the stack pointer. * * Inputs: - * - tcb: The TCB of new task + * - tcb: The TCB of new task + * - stack: The new stack to be used. * - stack_size: The allocated stack size. * * NOTE: Unlike up_stack_create() and up_stack_release, this function @@ -219,6 +220,42 @@ int up_use_stack(FAR struct tcb_s *tcb, FAR void *stack, size_t stack_size); #endif /**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directory. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +#if !defined(CONFIG_CUSTOM_STACK) && defined(CONFIG_NUTTX_KERNEL) +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size); +#endif + +/**************************************************************************** * Name: up_release_stack * * Description: |