Piccolo OS Plus 1.01
A feature rich extension of Piccolo OS
The Piccolo OS Plus APIs

Detailed Description

Here are the Piccolo_Plus APIs, grouped by family function

The initializers

These are literally the beginning and the end.

piccolo_init() is called before any other Piccolo function. piccolo_start() begins the piccolo scheduler execution, and never returns.

void piccolo_init ()
 Initialize the piccolo run time environment. More...
 
void piccolo_start ()
 Start the Piccolo Task scheduler. More...
 

Task creation and execution control

These are the functions for creating and ending tasks, and controlling their execution. Once a task is running, it can yield the processor to the next task voluntarily. It can also suspend execution (sleep) for a time and allow other tasks to execute.

Note
To send a signal to a task, the sender must have the pointer to the task returned by piccolo_create_task().
piccolo_os_task_tpiccolo_create_task (void(*pointer_to_task_function)(void))
 Create a new task and initialize its stack. More...
 
void piccolo_end_task ()
 Ends the current task, never returns. More...
 
static void piccolo_yield (void)
 Yields the processor to another task. More...
 
void piccolo_syscall (void)
 Same as piccolo_yield. More...
 
void piccolo_sleep (uint32_t sleep_time_ms)
 sleeps for a specified number of milliseconds More...
 
void piccolo_sleep_until (absolute_time_t until)
 sleeps until an absolute time. More...
 

Task Signals

Each task has a built in signal channel which can be used for inter-task synchronization. A channel can hold a specified number of signals. (The maximum is a #define value which can be as large as 2^31). Signals are only events which contain no data and do not occupy any memory. Signals can be sent to a task by another task, or by interrupt service handlers or timer or alarm callback routines. (Though only tasks ought to try blocking!)

piccolo_os_task_tpiccolo_get_task_id ()
 Get the ID (task struct address) of the running task. More...
 
int32_t piccolo_send_signal (piccolo_os_task_t *toTask)
 Send a signal to the specified task. More...
 
int32_t piccolo_send_signal_blocking (piccolo_os_task_t *toTask)
 Send a signal to the specified task. If the signal channel is full, block until it is not. More...
 
int32_t piccolo_send_signal_blocking_timeout (piccolo_os_task_t *toTask, uint32_t timeout_ms)
 Send a signal to a specified task. If the channel is full, block with a timeout until it is not. More...
 
int32_t piccolo_get_signal ()
 Attempt to get a signal. More...
 
int32_t piccolo_get_signal_blocking ()
 Get a signal. If none are available, block until one arrives. More...
 
int32_t piccolo_get_signal_blocking_timeout (uint32_t timeout_ms)
 Attempt to get a signal. If none are available, block with a timeout until one arrives. More...
 
int32_t piccolo_get_signal_all ()
 Get all the signals available. More...
 
int32_t piccolo_get_signal_all_blocking ()
 Get all the signals available. If none are available, block until one arrives. More...
 
int32_t piccolo_get_signal_all_blocking_timeout (uint32_t timeout_ms)
 Get all the signals available. If none are available, block with a timeout until one arrives. More...
 

Function Documentation

◆ piccolo_create_task()

piccolo_os_task_t * piccolo_create_task ( void(*)(void)  pointer_to_task_function)

Create a new task and initialize its stack.

Parameters
pointer_to_task_functionThe task function to call initially
Returns
Task identifier (Pointer to task structure) or 0 if create failed

Allocates a new task and initializes its stack to the start of the given function. Inserts the task at the end of the scheduler task list. Can be called to create a new task while the scheduler is running. (In other words, a running task can create another task at runtime.)

◆ piccolo_end_task()

void piccolo_end_task ( void  )

Ends the current task, never returns.

Marks the current task as dead (ZOMBIE) and yields, so the scheduler can remove it. (The scheduler must do this, since we cannot free the memory for a task while it is running!). The scheduler will immediately remove a ZOMBIE task from the scheduler chain, add it to the zombies list and signal the garbage collector to return the task space to free memory.

Note
A task that executes a return will also be ended.

◆ piccolo_get_signal()

int32_t piccolo_get_signal ( )
inline

Attempt to get a signal.

Returns
1 if signal received, 0 if none were available

◆ piccolo_get_signal_all()

int32_t piccolo_get_signal_all ( )
inline

Get all the signals available.

Returns
Number of signals received, 0 if none were available

Empties the signal channel if signals were available.

◆ piccolo_get_signal_all_blocking()

int32_t piccolo_get_signal_all_blocking ( )
inline

Get all the signals available. If none are available, block until one arrives.

Returns
Number of signals received

Empties the signal channel.

◆ piccolo_get_signal_all_blocking_timeout()

int32_t piccolo_get_signal_all_blocking_timeout ( uint32_t  timeout_ms)
inline

Get all the signals available. If none are available, block with a timeout until one arrives.

Parameters
timeout_msTime in ms to wait for a signal to arrive
Returns
Number of signals received, 0 if timeout occurred.

Empties the signal channel.

◆ piccolo_get_signal_blocking()

int32_t piccolo_get_signal_blocking ( )
inline

Get a signal. If none are available, block until one arrives.

Returns
1 for number of signals received.

◆ piccolo_get_signal_blocking_timeout()

int32_t piccolo_get_signal_blocking_timeout ( uint32_t  timeout_ms)
inline

Attempt to get a signal. If none are available, block with a timeout until one arrives.

Parameters
timeout_msnon zero if timeout enabled on blocking
Returns
Number of signals received. Will be zero if timeout occurred.

◆ piccolo_get_task_id()

piccolo_os_task_t * piccolo_get_task_id ( )

Get the ID (task struct address) of the running task.

Returns
piccolo_os_task_t* Task ID of the current task.

Return the task ID of the running task. Useful for telling callback routines (or other tasks) where to send signals.

Note
Will return the core number before piccolo_start is running on that core. But if you don't call this except inside a task, you will always get a valid task ID.

◆ piccolo_init()

void piccolo_init ( )

Initialize the piccolo run time environment.

Set the scheduler task list to empty and set up the context switching, interrupt handlers, interrupt priorities and interlocks (spinlocks) for the scheduler.

Note
Also called internally on Core 1 when multi-core is enabled. On core1 only the interrupt priorities are set, and all the "one time" stuff is skipped.

◆ piccolo_send_signal()

int32_t piccolo_send_signal ( piccolo_os_task_t toTask)
inline

Send a signal to the specified task.

Parameters
toTaskpointer to task to send to
Returns
1 if signal sent. <0 if no room

Send a signal to the designated task. If there is space the signal is sent. If there is no room for the signal, return the error.

◆ piccolo_send_signal_blocking()

int32_t piccolo_send_signal_blocking ( piccolo_os_task_t toTask)
inline

Send a signal to the specified task. If the signal channel is full, block until it is not.

Parameters
toTaskpointer to task to send to
Returns
1 to indicate success.

Send a signal to the designated task. If there is space the signal is sent. If there is no room for the signal, block until space is available.

◆ piccolo_send_signal_blocking_timeout()

int32_t piccolo_send_signal_blocking_timeout ( piccolo_os_task_t toTask,
uint32_t  timeout_ms 
)
inline

Send a signal to a specified task. If the channel is full, block with a timeout until it is not.

Parameters
toTaskpointer to task to send to
timeout_msmaximum time in ms to wait if the channel is full.
Returns
1 if signal sent. <0 if a timeout occurred while waiting for space in the channel.

Send a signal to the designated task. If there is space the signal is sent. If there is no room for the signal, wait until the timeout expires or space is available.

◆ piccolo_sleep()

void piccolo_sleep ( uint32_t  sleep_time_ms)

sleeps for a specified number of milliseconds

Parameters
sleep_time_msnumber of milliseconds to sleep;

The scheduler marks the task as blocked and suspends its execution until the delay has expired.

◆ piccolo_sleep_until()

void piccolo_sleep_until ( absolute_time_t  until)

sleeps until an absolute time.

Parameters
untilabsolute time to wake up

Set the wakeup time for the task and mark it as sleeping for the scheduler. Then suspend execution until the scheduler wakes up the task.

◆ piccolo_start()

void piccolo_start ( )

Start the Piccolo Task scheduler.

Returns
Never!

Start the second processor if multi-core mode is enabled. Switch to handler mode and begin the round robin scheduler.

The scheduler starts with the task after the last task run by either core and looks for a task which is not running (on the other core) and not blocked. Along the way it checks if sleeping tasks or tasks blocked for signaling should be unblocked. The first task found ready to run gets run, with the preemption timer reset and armed if preemption is enabled. After the task yields or is preempted, the scheduler checks if it has ended. (Marked as a zombie.) If so, the task is removed from the scheduler's task list and sent to the garbage collector to free the task's memory.

If no task is ready to run, an idle task will be started to sleep for the minimum of PICCOLO_OS_MAX_IDLE or the smallest time remaining of any timeout. Sleep is the Pico sleep routine, so the core goes to sleep for power reduction. If PICCOLO_OS_MAX_IDLE is set to zero, idle will not run.

If PICCOLO_OS_NO_IDLE_FOR_SIGNALS is true (the default), the idle task will not be run if any task is blocked waiting to send or receive a signal in order to minimize system response time. Setting PICCOLO_OS_NO_IDLE_FOR_SIGNALS to false will improve power consumption but potentially delay the response of any task waiting for a signal. This may make good sense for low power applications without serious response time concerns.

Note
Runs on both cores if multi-core is enabled

◆ piccolo_syscall()

void piccolo_syscall ( void  )

Same as piccolo_yield.

◆ piccolo_yield()

static void piccolo_yield ( void  )
static

Yields the processor to another task.

The scheduler will switch to the next ready task in a "round robin" manner.