APIs Exported by Architecture-Specific Logic to NuttX

void up_initialize(void)

Called once during OS initialization after the basic OS services have been initialized. The architecture specific details of initializing the OS will be handled here. Such things as setting up interrupt service routines, starting the clock, and registering device are some of the things that are different for each processor and hardware platform.

up_initialize() is called after the OS initialized but before the init process has been started and before the libraries have been initialized. OS services and driver services are available.

void up_idle(void)

The logic that will be executed when their is no other ready-to-run task. This is processor idle time and will continue until some interrupt occurs to cause a context switch from the idle task.

Processing in this state may be processor-specific. e.g., this is where power management operations might be performed.

void up_initial_state(FAR struct tcb_s *tcb)

A new thread is being started and a new TCB has been created. This function is called to initialize the processor specific portions of the new TCB.

This function must setup the initial architecture registers and/or stack so that execution will begin at tcb->start on the next context switch.

This function may also need to set up processor registers so that the new thread executes with the correct privileges. If CONFIG_BUILD_PROTECTED or CONFIG_BUILD_KERNEL have been selected in the NuttX configuration, then special initialization may need to be performed depending on the task type specified in the TCB’s flags field: Kernel threads will require kernel-mode privileges; User tasks and pthreads should have only user-mode privileges. If neither CONFIG_BUILD_PROTECTED nor CONFIG_BUILD_KERNEL have been selected, then all threads should have kernel-mode privileges.

STATUS up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)

Allocate a stack for a new thread and setup up stack-related information in the TCB.

The following TCB fields must be initialized:

  • adj_stack_size: Stack size after adjustment for hardware, processor, etc. This value is retained only for debug purposes.

  • stack_alloc_ptr: Pointer to allocated stack

  • stack_base_ptr: Adjusted stack base pointer after the TLS Data and Arguments has been removed from the stack allocation.

Parameters:
  • tcb – The TCB of new task.

  • stack_size – The requested stack size. At least this much must be allocated.

  • ttype

    The thread type. This may be one of following (defined in include/nuttx/sched.h):

    • TCB_FLAG_TTYPE_TASK: Normal user task

    • TCB_FLAG_TTYPE_PTHREAD: User pthread

    • TCB_FLAG_TTYPE_KERNEL: Kernel thread

    This thread type is normally available in the flags field of the TCB, however, there are certain contexts where the TCB may not be fully initialized when up_create_stack is called.

    If CONFIG_BUILD_PROTECTED or CONFIG_BUILD_KERNEL are defined, then this thread type may affect how the stack is allocated. For example, kernel thread stacks should be allocated from protected kernel memory. Stacks for user tasks and threads must come from memory that is accessible to user code.

STATUS up_use_stack(FAR struct tcb_s *tcb, FAR void *stack, size_t stack_size)

Setup up stack-related information in the TCB using pre-allocated stack memory. This function is called only from nxtask_init() when a task or kernel thread is started (never for pthreads).

The following TCB fields must be initialized:

  • adj_stack_size: Stack size after adjustment for hardware, processor, etc. This value is retained only for debug purposes.

  • stack_alloc_ptr: Pointer to allocated stack

  • stack_base_ptr: Adjusted stack base pointer after the TLS Data and Arguments has been removed from the stack allocation.

Parameters:
  • tcb – The TCB of new task.

  • stack_size – The allocated stack size.

NOTE: Unlike up_stack_create() and up_stack_release, this function does not require the task type (ttype) parameter. The TCB flags will always be set to provide the task type to up_use_stack() if the information needs that information.

FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size)

Allocate a stack frame in the TCB’s stack to hold thread-specific data. This function may be called any time 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 directly. 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.

  • stack_base_ptr: Adjusted stack base pointer after the TLS Data and Arguments has been removed from the stack allocation.

Here is the diagram after some allocation(tls, arg):

                 +-------------+ <-stack_alloc_ptr(lowest)
                 |  TLS Data   |
                 +-------------+
                 |  Arguments  |
stack_base_ptr-> +-------------+\
                 |  Available  | +
                 |    Stack    | |
              |  |             | |
              |  |             | +->adj_stack_size
              v  |             | |
                 |             | |
                 |             | +
                 +-------------+/
Parameters:
  • tcb – The TCB of new task.

  • frame_size – The size of the stack frame to allocate.

Returns:

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

void up_release_stack(FAR struct tcb_s *dtcb)

A task has been stopped. Free all stack related resources retained int the defunct TCB.

Parameters:
  • dtcb – The TCB containing information about the stack to be released.

  • ttype

    The thread type. This may be one of following (defined in include/nuttx/sched.h):

    • TCB_FLAG_TTYPE_TASK: Normal user task

    • TCB_FLAG_TTYPE_PTHREAD: User pthread

    • TCB_FLAG_TTYPE_KERNEL: Kernel thread

    This thread type is normally available in the flags field of the TCB, however, there are certain error recovery contexts where the TCB may not be fully initialized when up_release_stack is called.

    If CONFIG_BUILD_PROTECTED or CONFIG_BUILD_KERNEL are defined, then this thread type may affect how the stack is freed. For example, kernel thread stacks may have been allocated from protected kernel memory. Stacks for user tasks and threads must have come from memory that is accessible to user

void up_switch_context(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)

A task is currently in the ready-to-run list but has been preppe to execute. Restore its context, and start execution.

This function is called only from the NuttX scheduling logic. Interrupts will always be disabled when this function is called.

Parameters:
  • tcb – Refers to the head task of the ready-to-run list which will be executed.

  • rtcb – Refers to the running task which will be blocked.

noreturn_function
void up_exit(int status) noreturn_function;

This function causes the currently executing task to cease to exist. This is a special case of task_delete().

Unlike other UP APIs, this function may be called directly from user programs in various states. The implementation of this function should disable interrupts before performing scheduling operations.

void up_dump_register(FAR void *dumpregs)

Register dump may be handled in an architecture-specific way.

void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver)

This function is called by the OS when one or more signal handling actions have been queued for execution. The architecture specific code must configure things so that the ‘sigdeliver’ callback is executed on the thread specified by ‘tcb’ as soon as possible.

This function may be called from interrupt handling logic.

This operation should not cause the task to be unblocked nor should it cause any immediate execution of sigdeliver. Typically, a few cases need to be considered:

  1. This function may be called from an interrupt handler During interrupt processing, all xcptcontext structures should be valid for all tasks. That structure should be modified to invoke sigdeliver() either on return from (this) interrupt or on some subsequent context switch to the recipient task.

  2. If not in an interrupt handler and the tcb is NOT the currently executing task, then again just modify the saved xcptcontext structure for the recipient task so it will invoke sigdeliver when that task is later resumed.

  3. If not in an interrupt handler and the tcb IS the currently executing task – just call the signal handler now.

void up_allocate_heap(FAR void **heap_start, size_t *heap_size)

This function will be called to dynamically set aside the heap region.

For the kernel build (CONFIG_BUILD_PROTECTED=y or CONFIG_BUILD_KERNEL=y) with both kernel- and user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the size of the unprotected, user-space heap. If a protected kernel-space heap is provided, the kernel heap must be allocated (and protected) by an analogous up_allocate_kheap().

bool up_interrupt_context(void)

Return true if we are currently executing in the interrupt handler context.

void up_disable_irq(int irq)

Disable the IRQ specified by ‘irq’ On many architectures, there are three levels of interrupt enabling: (1) at the global level, (2) at the level of the interrupt controller, and (3) at the device level. In order to receive interrupts, they must be enabled at all three levels.

This function implements enabling of the device specified by ‘irq’ at the interrupt controller level if supported by the architecture (up_irq_save() supports the global level, the device level is hardware specific).

If the architecture does not support up_disable_irq, CONFIG_ARCH_NOINTC should be defined in the NuttX configuration file. Since this API cannot be supported on all architectures, it should be avoided in common implementations where possible.

void up_enable_irq(int irq)

This function implements disabling of the device specified by ‘irq’ at the interrupt controller level if supported by the architecture (up_irq_restore() supports the global level, the device level is hardware specific).

If the architecture does not support up_disable_irq, CONFIG_ARCH_NOINTC should be defined in the NuttX configuration file. Since this API cannot be supported on all architectures, it should be avoided in common implementations where possible.

void up_prioritize_irq(int irq)

Set the priority of an IRQ.

If the architecture supports up_enable_irq, CONFIG_ARCH_IRQPRIO should be defined in the NuttX configuration file. Since this API cannot be supported on all architectures, it should be avoided in common implementations where possible.

void up_putc(int ch)

This is a debug interface exported by the architecture-specific logic. Output one character on the console