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

  • adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of the stack pointer.

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

  • adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of the stack pointer.

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.

  • 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.

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_unblock_task(FAR struct tcb_s *tcb)

A task is currently in an inactive task list but has been prepped to execute. Move the TCB to the ready-to-run list, 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 tcb to be unblocked. This tcb is in one of the waiting tasks lists. It must be moved to the ready-to-run list and, if it is the highest priority ready to run tasks, executed.

void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state)

The currently executing task at the head of the ready to run list must be stopped. Save its context and move it to the inactive list specified by task_state. This function is called only from the NuttX scheduling logic. Interrupts will always be disabled when this function is called.

Parameters:
  • tcb – Refers to a task in the ready-to-run list (normally the task at the head of the list). It must be stopped, its context saved and moved into one of the waiting task lists. If it was the task at the head of the ready-to-run list, then a context switch to the new ready to run task must be performed.

  • task_state – Specifies which waiting task list should be hold the blocked task TCB.

void up_release_pending(void)

When tasks become ready-to-run but cannot run because pre-emption is disabled, they are placed into a pending task list. This function releases and makes ready-to-run all of the tasks that have collected in the pending task list. This can cause a context switch if a new task is placed at the head of the ready to run list.

This function is called only from the NuttX scheduling logic when pre-emption is re-enabled. Interrupts will always be disabled when this function is called.

void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority)

Called when the priority of a running or ready-to-run task changes and the reprioritization will cause a context switch. Two cases:

  1. The priority of the currently running task drops and the next task in the ready to run list has priority.

  2. An idle, ready to run task’s priority has been raised above the the priority of the current, running task and it now has the priority.

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

Parameters:
  • tcb – The TCB of the task that has been reprioritized

  • priority – The new task priority

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_assert(FAR const char *filename, int linenum)

Assertions 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.

int up_putc(int ch)

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