Пример #1
0
static inline void constructStackFrame(POSTASK_t task, void* stackPtr, POSTASKFUNC_t funcptr, void *funcarg)
{
  unsigned int   *stk, z;
  int r;

/*
 * Get aligned stack pointer, reserve 32 bytes.
 */

  z = (unsigned int)stackPtr;
  z = STACK_ALIGN_DOWN(z);
  stk = (unsigned int *)z;

/*
 * Put initial values to stack, including entry point address,
 * some detectable register values, status register (which
 * switches cpu to system mode during context switch) and
 * dummy place for exception stack pointer (see comments
 * assember files for this).
 */

  *(--stk) = (unsigned int)funcptr;     /* Entry Point          */
  *(--stk) = (unsigned int)posTaskExit; /* lr                   */

  for (r = 12; r >= 1; r--)
    *(--stk) = r;

  *(--stk) = (unsigned int)funcarg;     /* r0 : argument        */
  *(--stk) = (unsigned int)CPU_MODE;    /* CPSR                 */

  task->stackptr = (void *)stk;
}
Пример #2
0
int up_use_stack(_TCB *tcb, void *stack, size_t stack_size)
{
  size_t top_of_stack;
  size_t size_of_stack;

  if (tcb->stack_alloc_ptr)
    {
      sched_free(tcb->stack_alloc_ptr);
    }

  /* Save the stack allocation */

  tcb->stack_alloc_ptr = stack;

  /* The ARM 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 ARM stack must be aligned; 4 byte alignment for OABI and 8-byte
   * alignment for EABI. If necessary top_of_stack must be rounded down
   * to the next boundary
   */

  top_of_stack = STACK_ALIGN_DOWN(top_of_stack);

  /* The size of the stack in bytes is then the difference between
   * the top and the bottom of the stack (+4 because if the top
   * is the same as the bottom, then the size is one 32-bit element).
   * The size need not be aligned.
   */

  size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;

  /* Save the adjusted stack values in the _TCB */

  tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
  tcb->adj_stack_size = size_of_stack;

  return OK;
}
Пример #3
0
int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size)
{
    size_t top_of_stack;
    size_t size_of_stack;

    /* Is there already a stack allocated? */

    if (tcb->stack_alloc_ptr)
    {
        /* Yes.. Release the old stack allocation */

        up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK);
    }

    /* Save the new stack allocation */

    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.
     */

    top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;

    /* 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 = 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 */

    tcb->adj_stack_ptr  = (uint32_t *)top_of_stack;
    tcb->adj_stack_size = size_of_stack;

    return OK;
}
Пример #4
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  static bool first_task = true;

  /* Is there already a stack allocated of a different size?  Because of
   * alignment issues, stack_size might erroneously appear to be of a
   * different size.  Fortunately, this is not a critical operation.
   */

  if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
    {
      /* Yes.. Release the old stack */

      up_release_stack(tcb, ttype);
    }

  /* Do we need to allocate a new stack? */

  if (!tcb->stack_alloc_ptr)
    {
      /* Allocate the stack.  If DEBUG is enabled (but not stack debug),
       * then create a zeroed stack to make stack dumps easier to trace.
       */

#ifdef HAVE_KERNEL_HEAP
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
          tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size);
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

          tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);
        }

#ifdef CONFIG_DEBUG
      /* Was the allocation successful? */

      if (!tcb->stack_alloc_ptr)
        {
          sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size);
        }
#endif
    }

  /* Did we successfully allocate a stack? */

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;
      size_t size_of_stack;

      /* The ARM 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 ARM stack must be aligned; 4 byte alignment for OABI and
       * 8-byte alignment for EABI. If necessary top_of_stack must be
       * rounded down to the next boundary
       */

      top_of_stack = STACK_ALIGN_DOWN(top_of_stack);

      /* The size of the stack in bytes is then the difference between
       * the top and the bottom of the stack (+4 because if the top
       * is the same as the bottom, then the size is one 32-bit element).
       * The size need not be aligned.
       */

      size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;

      /* Save the adjusted stack values in the struct tcb_s */

      tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
      tcb->adj_stack_size = size_of_stack;

      /* If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#ifdef CONFIG_STACK_COLORATION
      up_stack_color(tcb->stack_alloc_ptr, tcb->adj_stack_size);
#endif

      if (first_task)
        {
          board_led_on(LED_STACKCREATED);
          first_task = false;
        }

      return OK;
    }

   return ERROR;
}
Пример #5
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  /* Is there already a stack allocated of a different size?  Because of
   * alignment issues, stack_size might erroneously appear to be of a
   * different size.  Fortunately, this is not a critical operation.
   */

  if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
    {
      /* Yes.. Release the old stack */

      up_release_stack(tcb, ttype);
    }

  /* Do we need to allocate a new stack? */
 
  if (!tcb->stack_alloc_ptr)
    {
      /* Allocate the stack.  If DEBUG is enabled (but not stack debug),
       * then create a zeroed stack to make stack dumps easier to trace.
       */

#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size);
#endif
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size);
#endif
        }

#ifdef CONFIG_DEBUG
      /* Was the allocation successful? */

      if (!tcb->stack_alloc_ptr)
        {
          sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size);
        }
#endif
    }

  /* Did we successfully allocate a stack? */

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;
      size_t size_of_stack;

      /* Yes.. If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
      memset(tcb->stack_alloc_ptr, 0xaa, stack_size);
#endif

      /* MIPS uses a push-down stack:  the stack grows toward lower
       * addresses in memory.  The stack pointer register points to the
       * lowest, valid working 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; for
       * floating point use, the stack must be aligned to 8-byte addresses.
       * If necessary top_of_stack must be rounded down to the next
       * boundary to meet these alignment requirements. 
       */

      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 */

      tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
      tcb->adj_stack_size = size_of_stack;

      up_ledon(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}
Пример #6
0
int up_create_stack(_TCB *tcb, size_t stack_size)
{
  if (tcb->stack_alloc_ptr &&
      tcb->adj_stack_size != stack_size)
    {
      sched_free(tcb->stack_alloc_ptr);
      tcb->stack_alloc_ptr = NULL;
    }

  if (!tcb->stack_alloc_ptr)
    {
#ifdef CONFIG_DEBUG
      tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size);
#else
      tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size);
#endif
    }

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;
      size_t size_of_stack;

      /* The ARM 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 ARM stack must be aligned; 4 byte alignment for OABI and
       * 8-byte alignment for EABI. If necessary top_of_stack must be
       * rounded down to the next boundary
       */

      top_of_stack = STACK_ALIGN_DOWN(top_of_stack);

      /* The size of the stack in bytes is then the difference between
       * the top and the bottom of the stack (+4 because if the top
       * is the same as the bottom, then the size is one 32-bit element).
       * The size need not be aligned.
       */

      size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;

      /* Save the adjusted stack values in the _TCB */

      tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
      tcb->adj_stack_size = size_of_stack;

      /* If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
      memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4);
#endif

      up_ledon(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}