Piccolo OS Plus 1.01
A feature rich extension of Piccolo OS
Data Structures | Macros | Enumerations | Functions | Variables
The Piccolo Plus Internals

Detailed Description

Data Structures

struct  piccolo_os_task_t
 Piccolo OS task data structure. More...
 
struct  piccolo_os_internals_t
 Piccolo OS internal data structure. More...
 

Macros

#define PICCOLO_OS_STACK_SIZE   1024
 Size of a task stack in 32 bit words. More...
 
#define PICCOLO_OS_THREAD_PSP   0xFFFFFFFD
 
#define PICCOLO_OS_TIME_SLICE   1000
 The OS time slice, in microseconds. More...
 
#define PICCOLO_OS_MAX_IDLE   700
 The maximum time that the scheduler will sleep in the idle task (in usec). More...
 
#define PICCOLO_OS_NO_IDLE_FOR_SIGNALS   true
 If true, the scheduler will not idle (sleep) if tasks are blocking for signals. More...
 
#define PICCOLO_OS_MULTICORE   true
 Enable/disable multi-core scheduling. More...
 
#define PICCOLO_OS_MAX_SIGNAL   10
 Signal channel size. (max is INT32_MAX) More...
 
#define PICCOLO_SPIN_LOCK_ID   PICO_SPINLOCK_ID_OS1
 

Enumerations

enum  piccolo_task_flag_values {
  PICCOLO_TASK_RUNNING = 0x1 , PICCOLO_TASK_ZOMBIE = 0x2 , PICCOLO_TASK_SLEEPING = 0x4 , PICCOLO_TASK_GET_SIGNAL_BLOCKED = 0x8 ,
  PICCOLO_TASK_SEND_SIGNAL_BLOCKED = 0x10 , PICCOLO_TASK_BLOCKING = (PICCOLO_TASK_SLEEPING | PICCOLO_TASK_GET_SIGNAL_BLOCKED | PICCOLO_TASK_SEND_SIGNAL_BLOCKED)
}
 

Functions

uint32_t * __piccolo_os_create_task (uint32_t *task_stack, void(*pointer_to_task_function)(void), uint32_t starting_argument)
 Initialize user task stack for execution. More...
 
int32_t __piccolo_send_signal (piccolo_os_task_t *task, bool block, uint32_t timeout_ms)
 Helper for send signal functions. More...
 
int32_t __piccolo_get_signal (bool block, uint32_t timeout_ms, bool get_all)
 Helper for get signal functions. More...
 
void __piccolo_garbage_man (void)
 Task to delete dead tasks. More...
 
void __piccolo_task_init (void)
 Switch the scheduler to handler mode. More...
 
void __piccolo_idle (int32_t uSec)
 Internal Idle "task" used by the scheduler to sleep the core. More...
 
void __piccolo_start_core1 (void)
 Core 1 code to initialize and immediately start the piccolo scheduler on core 1. More...
 

Variables

**struct piccolo_os_task_t piccolo_os_task_t
 

Data Structure Documentation

◆ piccolo_os_task_t

struct piccolo_os_task_t

Piccolo OS task data structure.

Data Fields
struct piccolo_os_task_t * next_task

next task in scheduler chain

struct piccolo_os_task_t * prev_task

previous task in scheduler chain

volatile uint32_t signal_in

input values for the task's input signal channel

uint32_t signal_limit

maximum number of signals (+1) the task can queue

volatile uint32_t signal_out

output values for the task's input signal channel

uint32_t stack[PICCOLO_OS_STACK_SIZE]

the task stack space

uint32_t * stack_ptr

the task stack pointer

volatile uint32_t task_flags

Task Status

struct piccolo_os_task_t * task_sending_to

task that this one if blocked trying to signal

absolute_time_t wakeup

end of sleep time or timeout

◆ piccolo_os_internals_t

struct piccolo_os_internals_t

Piccolo OS internal data structure.

Data Fields
volatile piccolo_os_task_t * current_task

last task started on either core for round-robin scheduling

piccolo_os_task_t * garbage_man

Garbage collector task (so schedulers can signal him)

spin_lock_t * piccolo_lock

spin lock instance

piccolo_os_task_t * task_list_head

pointer to the first task in scheduler list

piccolo_os_task_t * task_list_tail

pointer to the last task in scheduler list

volatile piccolo_os_task_t * this_task[2]

this_task[i] points to task being run on core i.

piccolo_os_task_t * zombies

(singly linked) list of dead tasks for garbage collection

Macro Definition Documentation

◆ PICCOLO_OS_MAX_IDLE

#define PICCOLO_OS_MAX_IDLE   700

The maximum time that the scheduler will sleep in the idle task (in usec).

This will influence the latency for tasks waking up for signals, for example. Setting this to zero will disable the idle task.

◆ PICCOLO_OS_MAX_SIGNAL

#define PICCOLO_OS_MAX_SIGNAL   10

Signal channel size. (max is INT32_MAX)

The number of signals which can be queued in a signal channel (+1). It can be set smaller for testing or special purposes.

Remarks
Remember that signals do not use any memory, so there is no penalty for a large number here.

◆ PICCOLO_OS_MULTICORE

#define PICCOLO_OS_MULTICORE   true

Enable/disable multi-core scheduling.

◆ PICCOLO_OS_NO_IDLE_FOR_SIGNALS

#define PICCOLO_OS_NO_IDLE_FOR_SIGNALS   true

If true, the scheduler will not idle (sleep) if tasks are blocking for signals.

If set to false, the scheduler will run the idle task for the minimum of PICCOLO_OS_MAX_IDLE or the smallest time remaining for any task with a timeout running. This will improve power consumption but potentially delay the response of any task waiting for a signal. This may make good sense for applications without serious response time concerns.

◆ PICCOLO_OS_STACK_SIZE

#define PICCOLO_OS_STACK_SIZE   1024

Size of a task stack in 32 bit words.

Note
Must be even, for exception frame stack alignment!

◆ PICCOLO_OS_THREAD_PSP

#define PICCOLO_OS_THREAD_PSP   0xFFFFFFFD

Exception return behavior value

◆ PICCOLO_OS_TIME_SLICE

#define PICCOLO_OS_TIME_SLICE   1000

The OS time slice, in microseconds.

Setting time slice to zero will disable preemptive scheduling!

◆ PICCOLO_SPIN_LOCK_ID

#define PICCOLO_SPIN_LOCK_ID   PICO_SPINLOCK_ID_OS1

Piccolo spin lock to use

Enumeration Type Documentation

◆ piccolo_task_flag_values

Enumerator
PICCOLO_TASK_RUNNING 

Task is running.

PICCOLO_TASK_ZOMBIE 

Task has ended and should be removed by the scheduler.

PICCOLO_TASK_SLEEPING 

Task has a timeout running.

PICCOLO_TASK_GET_SIGNAL_BLOCKED 

Task blocked getting signal.

PICCOLO_TASK_SEND_SIGNAL_BLOCKED 

Task block sending signal.

PICCOLO_TASK_BLOCKING 

Mask to detect task blocked for some reason.

Function Documentation

◆ __piccolo_garbage_man()

void __piccolo_garbage_man ( void  )

Task to delete dead tasks.

The task is created during the scheduler start-up on core 0. When it runs, it tries to free the space for all the dead tasks on the zombies list. (The scheduler cannot call free(), because it is an interrupt handler and would break the mutex that protects free() and malloc()).

◆ __piccolo_get_signal()

int32_t __piccolo_get_signal ( bool  block,
uint32_t  timeout_ms,
bool  get_all 
)

Helper for get signal functions.

Parameters
blocktrue if blocking on send
timeout_msnon zero if timeout enabled on blocking
get_allif true, get ALL signals available. Otherwise just get one.
Returns
Number of signals received. Can be zero on timeout or non-blocking

Get a signal for the current task. Return the number received. If there are no signals available, return zero unless blocking was requested. If blocking is necessary, start a timeout as well if one was requested.

Note
With only ONE receiver, we do not have to lock anything.

◆ __piccolo_idle()

void __piccolo_idle ( int32_t  uSec)

Internal Idle "task" used by the scheduler to sleep the core.

Parameters
uSecthe number of microseconds to sleep

Enter sleep mode and then "yield" back to the scheduler. Entry and parameter passing is set up in a dummy stack frame before switching context.

Note
Can be running on both cores with different sleep times

◆ __piccolo_os_create_task()

uint32_t * __piccolo_os_create_task ( uint32_t *  task_stack,
void(*)(void)  pointer_to_task_function,
uint32_t  starting_argument 
)

Initialize user task stack for execution.

Parameters
task_stackpointer to the END of the task stack (array).
pointer_to_task_functionthe function to execute.
starting_argumentunsigned integer argument for function
Returns
"Current" stack pointer for the task.

We setup the initial stack frame with:

  • "software saved" LR set to PICCOLO_OS_THREAD_PSP so that exception return works correctly.
  • PC Set to the task starting point (function entry)
  • Exception frame LR set to piccolo_end_task() in case the task exits or returns

PICCOLO_OS_THREAD_PSP means:

Note
The starting argument is placed in R0, but this is only used internally for the totally fake idle task.

◆ __piccolo_send_signal()

int32_t __piccolo_send_signal ( piccolo_os_task_t task,
bool  block,
uint32_t  timeout_ms 
)

Helper for send signal functions.

Parameters
taskpointer to task to send to
blocktrue if blocking on send
timeout_msnon zero if timeout enabled on blocking
Returns
1 if signal sent. <0 if no room, or timeout occurred on blocking

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 unless blocking was requested. If blocking is necessary, start a timeout as well, if one was requested.

Note
Since multiple senders are allowed, we must use the spinlock.

◆ __piccolo_start_core1()

void __piccolo_start_core1 ( void  )

Core 1 code to initialize and immediately start the piccolo scheduler on core 1.

Remember that the piccolo_init() checks the core number and does not setup the data structures or the interrupt vector table if it is not core 0. piccolo_start() takes similar precautions. The scheduler will run on both cores at once.

◆ __piccolo_task_init()

void __piccolo_task_init ( void  )

Switch the scheduler to handler mode.

After a reset, the processor is in thread mode. Switch to handler mode, so that the Piccolo OS kernel runs in handler mode, and to ensure the correct return from an exception/interrupt later when switching to a task. We make a dummy stack and arrange to route the service call exception back to ourselves!

Variable Documentation

◆ piccolo_os_task_t