@CHIP-RTOS - RTOS Overview
IPC@CHIP® Documentation Index
API services split into the following groups:
Task Control Services
RTX_Create_Task() Create and start a task
RTX_Param_Task() Create and start a task with parameters
RTX_Create_Task_Without_Run() Create a task
RTX_Param_Task_Without_Run() Create a task with parameters
RTX_End_Execution() End execution of a task
RTX_Kill_Task() Kill a task
RTX_Restart_Task() Trigger start of task execution
RTX_Delete_Task() Remove a task from the system
RTX_Get_TaskID() Get ID of the current task
RTX_Change_TaskPrio() Change the priority of a task
RTX_Sleep_Time() Sleep for a specified time
RTX_Sleep_Long() Sleep for a long time
RTX_Sleep_Fine() Sleep for a specified RTI count
RTX_Sleep_Request() Sleep until a wake request
RTX_Wakeup() Wake a task which is sleeping
RTX_Suspend_Task() Suspend a task
RTX_Resume_Task() Resume a task
RTX_Access_Filesystem() Enable file access for the calling task
RTX_Get_Task_State() Get state of a task (task monitoring)
RTX_Get_Task_State_Ext() Get state of a task
RTX_Get_Task_List() Get list of tasks in system
RTX_Start_Task_Monitor() Start task monitoring
RTX_Stop_Task_Monitor() Stop task monitoring
Top of list
The @CHIP-RTOS API provides two types of semaphores:
The counting and resource semaphores provide automatic timeout. Tasks can specify the maximum time for waiting on a semaphore. The tasks wait in FIFO order for a resource. A semaphore is created with the RTX_Create_Sem() API. The @CHIP-RTOS needs a unique four byte semaphore name and on success returns a new semaphore ID (or handle) to the caller. This handle is needed for the other semaphore services.
Using a counting semaphore:
A counting semaphore is created by specifying an initial count greater or equal to zero in the call to RTX_Create_Sem(). If a semaphore is initialized with a value n, it can be used to control access to n resources, e.g. a counting semaphore with the initial value three assures that no more than three tasks can own a resource at any one time. Access to a resource controlled by a counting semaphore is acquired with a call to RTX_Wait_Sem() or RTX_Get_Sem(). If the resource is available the @CHIP-RTOS gives it to the task immediately. When the task is finished using the resource, it signals its release by calling RTX_Signal_Sem().
Using a resource semaphore:
A resource semaphore is created by specifying an initial count of -1 in the call of RTX_Create_Sem(). The @CHIP-RTOS creates a resource semaphore and automatically gives it an initial value of one indicating that the resource is free. A resource is reserved by calling RTX_Reserve_Sem() with the semaphore ID returned by RTX_Create_Sem(). The resource is released with a call to RTX_Release_Sem().
RTX_Create_Sem() Create a semaphore
RTX_Delete_Sem() Delete a semaphore
RTX_Get_Sem() Get access to semaphore (no wait)
RTX_Wait_Sem() Wait on a semaphore (optional timeout)
--- Resource Semaphore API ----
RTX_Free_Sem() Free a resource semaphore
RTX_Release_Sem() Release a resource semaphore
RTX_Reserve_Sem() Get a resource semaphore
--- Counting Semaphore API ----
RTX_Signal_Sem() Signal a counting semaphore
Top of list
Time / Date Services
RTX_Get_TimeDate() Get system time and date
RTX_Get_TimeDate_us() Get system time and date with high resolution
RTX_time() Get number of seconds elapsed since 00:00:00 January 1 1970
RTX_Set_TimeDate() Set system time and date
RTX_Set_TimeDate_us() Set system time and date with high resolution
RTX_stime() Set number of seconds elapsed since 00:00:00 January 1 1970
RTX_Get_System_Ticks() Get system clock ms (output param)
RTX_GetTickCount() Return system clock ms
RTX_Get_RTI_Ticks() Get RTI tick count
RTX_GetTick_us() Get system time in us
RTX_GetFineTick() Get high resolution system time
Top of list
RTX_Fine_Timer() Install a high resolution timer procedure
RTX_Remove_Timer() Remove a timer procedure
RTX_Start_Timer() Start periodic execution of callback
RTX_Stop_Timer() Stop periodic execution of callback
RTX_Timer_Delay() Set delay time for next callback
The @CHIP-RTOS implements timer procedures using kernel objects, of which there are a limited number. The sum of semaphores plus event groups plus timer procedures is limited to this maximum count since all three of these objects require use of a kernel object.
The kernel executes periodic user timer procedures at a specified time interval. Timer
callbacks execute in the system's top priority AMXK kernel task. Consequently,
your timer procedure must be as short as practical without any waiting or endless loops
in order to not interfere with other system activities.
Avoid the usage of large C-library functions such as printf(). However, any
of the following kernel services are reasonable to call from within a timer
This list is not exhaustive.
Top of list
The Event Manager provides a set of event flags which can be associated with specific events in your system. These event flags are provided in groups with 16 event flags per group. The number of event groups which can be created is limited by the total number of kernel objects available. One kernel object is expended to create a semaphore, event group or timer procedure.
The Event Manager is useful when two or more tasks will wait for the same event, e.g. waiting for the start of a motor. An event flag is defined to represent the state of the motor (off or on). When tasks must wait for the motor, they do so by calling the Event Manager requesting a wait until the motor control event flag indicates that the motor is on. When the motor control task or timer procedure detects that the motor is on, it signals the event with a call to the Event Manager. The Event Manager then wakes up all tasks which are waiting for the motor to be on. For further explanations read the function description in the API call specifications.
RTX_Create_EventGroup() Create an event group
RTX_Delete_EventGroup() Delete an event group
RTX_Signal_Events() Signal one or more events in a group
RTX_Wait_For_Event() Wait for all/any of a set of events in a group
RTX_Get_EventGroup_State() Read current state of events in a group
RTX_Get_Saved_Events() Get saved event flags
RTX_Find_EventGroup() Find Event Group by name
Top of list
Message Exchange Manager
An often cited example of using Message Exchange is a print request queue. Assume that there are two different server tasks (consumers), each of which is connected to a different printer. There are some other tasks (producers) which want to asynchronously use one of the two servers for printing and they don't care which of the two printers is used. The solution is to synchronize those requests: The producer tasks send their requests (messages) to the Message Exchange Manager. The two server tasks waiting for messages take a message (if any) from the message queue and execute the requested print job.
The Message Exchange Manager uses a Message Exchange to deliver messages. A Message Exchange consists of four mailboxes into which messages can be deposited. The mailboxes are ordered according to priority (0-3), where mailbox 0 has the highest priority. The maximum depth of a mailbox is specified when the Message Exchange is created, which indicates the maximum number of messages which can be stored in that particular mailbox.
Messages are delivered to the mailboxes of the Message Exchange in message envelopes. The system's maximum number of available messages envelopes is 64 (or 128 for SC1x3/SC2x). The maximum number of message exchanges is 10 (or 32 for SC1x3/SC2x). The maximum message length is 12 bytes. (Note: Larger messages can be implemented with a pointer and a length parameter in the message.) Any task or timer procedure can send a message to a Message Exchange. The sender indicates the priority of its message (0-3), thereby identifying the mailbox into which the message will be delivered.
Any task or timer procedure can request a message from a Message Exchange, but only tasks are allowed to wait for the arrival of a message, if none is available. A task can specify the maximum time that it is willing to wait for a message. When more than one message is available at the exchange, a task requesting a message will be given the message at the head of the higest priority non-empty mailbox FIFO (of which there are four).
The task also specifies a priority at which it should receive the next message, allowing either for that task to cut in line ahead of other tasks that were waiting at the same message exchange or to yield to other tasks that later come looking for a message with a higher wait priority (lower numeric value). So conceptually, there are 2**16 FIFO priority queues at each Message Exchange where tasks wait for a message. When a message becomes available, this message will be handed to the first task waiting in the highest priority non-empty task wait queue.
What can be confusing here is that there are two concepts of priority involved here with Message Exchanges (neither of which is related to task priority).
Message Exchange Services:
RTX_Create_Msg() Create a Message Exchange
RTX_Delete_Msg() Delete a Message Exchange
RTX_Send_Msg() Send a message to a Message Exchange
RTX_Get_Msg() Get a message, if any (no wait)
RTX_Wait_For_Msg() Wait for message to arrive (optional timeout)
RTX_Find_Msg() Find a Message Exchange, specified by name
Top of list
Global Data Registry
When a program wants to communicate with one other program, a Message Exchange could have been used to easily accomplish this. When one program wants to make information available to an unspecified number of client programs, the Message Exchange mechanism becomes less attractive. The program providing the information must keep pumping messages into the Message Exchange, one message for each new client that may come along.
The mechanism provided by these data publication API allow a program to broadcast its data to what ever number of programs care to access the published data.
For visibility, the MEM console command lists entries in this global data registry by name.
Global Data Registry API:
RTX_Publish() Post a global data entry
RTX_GetPublication() Get a global data entry
Top of list
End of document