队列:实用程序服务和数据结构
隊列:實用程序服務和數據結構
Queues: utility services and data structures
隊列實用程序服務
Nucleus RTOS有四個API調用,它們提供與隊列相關的實用函數:重置隊列、返回有關隊列的信息、返回應用程序中的隊列數量以及返回指向應用程序中所有隊列的指針。前三個在Nucleus SE中實現。
重置隊列
此API調用將隊列恢復到其未使用的初始狀態。隊列中存儲的所有消息都將丟失。隊列上掛起的所有任務都將恢復,并收到返回代碼NUSE_queue_WAS_RESET。
Nucleus RTOS API Call for Resetting a Queue
Service call prototype:
STATUS NU_Reset_Queue(NU_QUEUE *queue;
Parameters:
queue – pointer to user-define queue control block
Returns:
NU_SUCCESS – the call was completed successfully
NU_INVALID_QUEUE – the queue
pointer is not valid
Nucleus SE API Call for Resetting a Queue
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
STATUS NUSE_Queue_Reset(NUSE_QUEUE queue);
Parameters:
queue – the index (ID) of the queue to be reset
Returns:
NUSE_SUCCESS – the call was completed successfully
NUSE_INVALID_QUEUE – the queue index is not valid
Nucleus SE Implementation of Queue Reset
在參數檢查之后,NUSE_Queue_Reset()API函數的最初部分代碼非常簡單。頭和尾索引以及隊列的消息計數都設置為零。
啟用阻塞時,其他代碼負責喚醒任何掛起的任務,因此:
while (NUSE_Queue_Blocking_Count[queue] != 0){ U8 index; /* check whether any tasks are blocked / / on this queue */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_QUEUE_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Queue_Blocking_Count[queue]–;}#if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK);#endif
隊列上掛起的每個任務都標記為“就緒”,掛起返回代碼NUSE_queue_WAS_RESET。此過程完成后,如果正在使用優先級調度程序,則會調用NUSE_Reschedule(),因為一個或多個優先級較高的任務可能已準備就緒,需要允許其運行。
隊列信息
此服務調用獲取有關隊列的信息選擇。Nucleus SE實現與Nucleus RTOS的不同之處在于,它返回的信息較少,因為不支持對象命名、可變消息大小和掛起順序,并且可能無法啟用任務掛起。
Nucleus RTOS API Call for Queue Information
Service call prototype:
STATUS NU_Queue_Information(NU_QUEUE *queue, CHAR *name,
VOID **start_address,UNSIGNED *queue_size, UNSIGNED
*available,
UNSIGNED *messages, OPTION *message_type,
UNSIGNED *message_size, OPTION *suspend_type,
UNSIGNED *tasks_waiting, NU_TASK **first_task);
Parameters:
queue – pointer to the user-supplied queue control block
name – pointer to an 8-character
destination area for the message-queue’s name
start_address – a pointer to a
pointer, which will receive the address of the start of the queue’s data area
queue_size – a pointer to a
variable for holding the total number of UNSIGNED data
elements in the queue
available – a pointer to a
variable for holding the number of available UNSIGNED data
elements in the queue
messages – a pointer to a
variable for holding the number of messages currently in the queue
message_type – pointer to a
variable for holding the type of messages supported by the queue; valid message
types are NU_FIXED_SIZE and NU_ VARIABLE_SIZE
message_size – pointer to a
variable for holding the number of UNSIGNED data
elements in each queue message; if the queue supports variable-length messages,
this number is the maximum message size
suspend_type – pointer to a
variable for holding the task suspend type. Valid task suspend types are NU_FIFO and NU_PRIORITY
tasks_waiting – a pointer to a
variable which will receive the number of tasks suspended on this queue
first_task – a pointer to a task
pointer; the pointer of the first suspended task is placed in this task pointer
Returns:
NU_SUCCESS – the call was completed successfully
NU_INVALID_QUEUE – the queue
pointer is not valid
Nucleus
SE API Call for Queue Information
This API call supports the key functionality of the Nucleus RTOS
API.
Service call prototype:
STATUS
NUSE_Queue_Information(NUSE_QUEUE queue,
ADDR *start_address, U8 *queue_size, U8 *available, U8
*messages, U8 *tasks_waiting, NUSE_TASK *first_task);
Parameters:
queue – the index of the queue about which information is being
requested
start_address – a pointer to a
variable of type ADDR ,
which will receive the address of the start of the queue’s data area
queue_size – a pointer to a
variable of type U8 ,
which will receive the total number of messages for which the queue has capacity
available – a pointer to a
variable of type U8 ,
which will receive the number of messages for which the queue has currently
remaining capacity
messages – a pointer to a
variable of type U8 ,
which will receive the number of messages currently in the queue
tasks_waiting – a pointer to a
variable which will receive the number of tasks suspended on this queue
(nothing returned if task suspend is disabled)
first_task – a pointer to a
variable of type NUSE_TASK which
will receive the index of the first suspended task (nothing returned if task
suspend is disabled)
Returns:
NUSE_SUCCESS – the call was completed successfully
NUSE_INVALID_QUEUE – the queue
index is not valid
NUSE_INVALID_POINTER – one or
more of the pointer parameters is invalid
Nucleus
SE Implementation of Queue Information
The implementation of this API call is quite straightforward:
*start_address = NUSE_Queue_Data[queue];*queue_size = NUSE_Queue_Size[queue];*available = NUSE_Queue_Size[queue] - NUSE_Queue_Items[queue];*messages = NUSE_Queue_Items[queue];#if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Queue_Blocking_Count[queue]; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif
函數返回隊列狀態。然后,如果啟用了阻塞API調用,則返回等待的任務數和第一個任務的索引(否則這兩個參數設置為0)。
獲取隊列數
此服務調用返回應用程序中配置的隊列數。在Nucleus RTOS中,這將隨時間而變化,返回的值將表示當前的隊列數,而在Nucleus SE中,返回的值在構建時設置,不能更改。
Nucleus RTOS API Call for Queue Count
Service call prototype:
UNSIGNED NU_Established_Queues(VOID);
Parameters:
None
Returns:
The number of created queues in the system.
Nucleus SE API Call for Queue Count
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
U8 NUSE_Queue_Count(void);
Parameters:
None
Returns:
The number of configured queues in the application
隊列計數的Nucleus SE實現
這個API調用的實現非常簡單:返回#define symbol NUSE_QUEUE_NUMBER的值。
數據結構
隊列使用五到六個數據結構—全部在RAM和ROM中—與其他Nucleus SE對象一樣,這些數據結構是一系列表,根據配置的隊列數量和選擇的選項進行包含和標注。
我強烈建議應用程序代碼不要直接訪問這些數據結構,而是使用提供的API函數。這避免了與Nucleus SE未來版本的不兼容和不必要的副作用,并簡化了將應用程序移植到Nucleus RTOS的過程。這里包含數據結構的詳細信息,以便更容易地理解服務調用代碼的工作方式和調試。
內核RAM數據
這些數據結構包括:
NUSE_Queue_Head[]–這是一個U8類型的數組,每個配置的隊列有一個條目,它表示指向消息隊列前面的指針。它用作NUSE_Queue_Data[]中地址的索引(見下文)。
NUSE_Queue_Tail[]–這是一個U8類型的數組,每個配置的隊列有一個條目,它表示指向消息隊列末尾的指針。它用作NUSE_Queue_Data[]中地址的索引(見下文)。
NUSE_Queue_Items[]–這是一個U8類型的數組,每個配置的隊列有一個條目,表示隊列中當前消息數的計數。這個數據可以說是多余的,因為它的值可以從head和tail索引中派生出來,但是存儲計數可以簡化代碼。
NUSE_Queue_Blocking_Count[]–此類型的U8數組包含每個隊列上阻塞的任務數。此數組僅在啟用阻止API調用支持時存在。
當Nucleus SE啟動時,這些數據結構都由NUSE_Init_Queue()初始化為零。這是合乎邏輯的,因為它將每個隊列呈現為空(未使用)。未來的文章將全面描述Nucleus SE的啟動過程。
以下是nuse_init.c文件中這些數據結構的定義:
RAM U8 NUSE_Queue_Head[NUSE_QUEUE_NUMBER];RAM U8 NUSE_Queue_Tail[NUSE_QUEUE_NUMBER];RAM U8 NUSE_Queue_Items[NUSE_QUEUE_NUMBER];#if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Queue_Blocking_Count[NUSE_QUEUE_NUMBER];#endif
用戶RAM
用戶負責為每個配置的隊列提供一個RAM區域用于數據存儲。這個RAM區域的大小必須容納ADDR類型的數組,隊列中的每條消息都有一個條目。
ROM數據
這些數據結構包括:
NUSE_Queue_Data[]–這是一個ADDR類型的數組,每個配置的隊列有一個條目,它表示每個隊列的數據區指針(在上面的用戶RAM中討論過)。
NUSE_Queue_Size[]–這是一個U8類型的數組,每個配置的隊列有一個條目,表示每個隊列可以容納的消息數。
這些數據結構都在nuse_config.c中聲明和初始化(當然是靜態的),因此:
ROM ADDR NUSE_Queue_Data[NUSE_QUEUE_NUMBER] ={ / addresses of queue data areas ------ /};ROM U8 NUSE_Queue_Size[NUSE_QUEUE_NUMBER] ={ / queue sizes ------ */};
Queue Data Footprint
Like all kernel objects in Nucleus SE, the amount of data memory
required for queues is readily predictable.
The ROM data footprint (in bytes) for all the queues in an
application may be computed thus:
NUSE_QUEUE_NUMBER * (sizeof(ADDR) + 1)
The kernel RAM data footprint (in bytes) for all the queues in
an application, when blocking API calls is enabled, may be computed thus:
NUSE_QUEUE_NUMBER* 3
Otherwise it is:
NUSE_QUEUE_NUMBER* 4
The amount of user RAM (in bytes) required for the queue with
index queue is:
NUSE_Queue_Size[queue]* sizeof(ADDR)
Unimplemented API Calls
Four queue API calls found in Nucleus RTOS are not implemented
in Nucleus SE:
Create Queue
This API call creates a queue. It is not needed with Nucleus SE,
as queues are created statically.
Service call prototype:
STATUS NU_Create_Queue(NU_QUEUE *queue, char *name,
VOID *start_address, UNSIGNED queue_size, OPTION
message_type, UNSIGNED message_size, OPTION suspend_type);
Parameters:
queue – pointer to a user-supplied queue control block; this
will be used as a “handle” for the queue in other API calls
name – pointers to a 7-character, null-terminated name for the queue
start_address – starting address for the queue
message_type – type of message
supported by the queue; may be NU_FIXED_SIZE or NU_VARIABLE_SIZE
message_size – if the queue supports fixed size messages, this parameter specifies the exact size of each message; otherwise, if the queue supports variable sized messages, this is the maximum message size suspend_type – specifies how
tasks suspend on the queue. Valid options for this parameter are NU_FIFOand NU_PRIORITY , which represent
First-In-First-Out (FIFO) and priority-order task suspension, respectively
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the
queue control block pointer is NULL or already in use
NU_INVALID_MEMORY – indicates the
memory area specified by the start_address is invalid
NU_INVALID_MESSAGE – indicates
that the message_type parameter is invalid
NU_INVALID_SIZE – indicates that
either the message size is greater than the queue size, or that the queue size or message size is zero
NU_INVALID_SUSPEND – indicates
that the suspend_type parameter is invalid
Delete Queue
This API call deletes a previously created queue. It is not needed with Nucleus SE, as queues are created statically and cannot be deleted.
Service call prototype:
STATUS NU_Delete_Queue(NU_QUEUE *queue);
Parameters:
queue – pointer to queue control block
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the
queue pointer is invalid
Queue Pointers
This API call builds a sequential list of pointers to all queues
in the system. It is not needed with Nucleus SE, as queues are identified by a simple index, not a pointer, and it would be redundant.
Service call prototype:
UNSIGNED NU_Queue_Pointers(NU_QUEUE **pointer_list,
UNSIGNED maximum_pointers);
Parameters:
pointer_list – pointer to an array of NU_QUEUE pointers;
this array will be filled with pointers to established queues in the system
maximum_pointers – the maximum
number of pointers to place in the array
Returns:
The number of NU_QUEUE pointers placed into the array
Broadcast to Queue
This API call broadcasts a message to all tasks waiting for a message from the specified queue. It is not implemented with Nucleus SE, as it would have added excessive complexity.
Service call prototype:
STATUS NU_Broadcast_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend);
Parameters:
queue – pointer to queue control block
message – pointer to the broadcast message
size – the number of UNSIGNED data elements in the message. If the queue supports variable-length messages, this parameter must be
equal to or less than the message size supported by the queue. If the queue supports fixed-size messages, this parameter must be exactly the same as the message size supported by the queue
suspend – specifies whether or not to suspend the calling task if the queue is already full; valid options for this parameter are NU_NO_SUSPEND , NU_SUSPEND or a timeout value.
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the queue pointer is invalid
NU_INVALID_POINTER – indicates
that the message pointer is NULL
NU_INVALID_SIZE – Indicates that the message size specified is not compatible with the size specified when the queue was created
NU_INVALID_SUSPEND – indicates
that suspend attempted from a non-task thread
NU_QUEUE_FULL – indicates that
there is insufficient space in the queue for the message
NU_TIMEOUT – indicates the queue
is still full after the timeout has expired
NU_QUEUE_DELETED – queue was
deleted while task was suspended
NU_QUEUE_RESET – queue was reset
while the task was suspended
與Nucleus RTOS的兼容性
對于Nucleus SE的各個方面,我的目標是盡可能保持與Nucleus RTOS的高級別應用程序代碼兼容性。隊列也不例外,從用戶的角度來看,它們的實現方式與Nucleus RTOS中的方式大致相同。有一些不兼容的地方,我認為這樣的不兼容是可以接受的,因為生成的代碼更容易理解,或者更有可能提高內存效率。否則,Nucleus RTOS API調用幾乎可以直接映射到Nucleus SE調用上。未來的一篇文章將包括關于為Nucleus RTOS用戶使用Nucleus SE的更多信息。
對象標識符
在Nucleus RTOS中,所有對象都由具有特定數據類型的數據結構(控制塊)來描述。指向此控制塊的指針用作隊列的標識符。在Nucleus SE中,我決定需要一種不同的方法來提高內存效率,所有的內核對象都由RAM和/或ROM中的許多表來描述,這些表的大小由配置的每個對象類型的數量決定。特定對象的標識符只是這些表的索引。因此,我將NUSE_QUEUE定義為等同于U8;此類型的變量(而不是指針)將用作隊列標識符。這是一個小的不兼容性,如果代碼被移植到Nucleus RTOS或從Nucleus RTOS移植過來,就很容易處理這個問題。對象標識符通常只是存儲和傳遞,而不是以任何方式操作。
Nucleus RTOS還支持隊列命名。這些名稱僅用于基于目標的調試工具。為了節省內存,我把它們從Nucleus SE中省略了。
消息大小和可變性
在Nucleus RTOS中,隊列可以配置為處理由任意數量的無符號數據元素組成的消息。在Nucleus SE中,隊列被簡化,只支持單個ADDR消息。管道在Nucleus SE中更為靈活,可能為某些應用程序提供了替代隊列的有用方法;本系列的下兩篇文章將介紹管道。
Nucleus RTOS還支持具有可變大小消息的隊列,其中僅在創建時指定最大大小。Nucleus SE不支持可變大小的消息。
隊列大小
Nucleus SE中隊列中的消息數被限制為256條,因為所有索引變量和常量都是U8類型。Nucleus RTOS不受此限制。
未實現的API調用
Nucleus RTOS支持10個服務調用來處理隊列。其中4個在Nucleus SE中沒有實現。
總結
以上是生活随笔為你收集整理的队列:实用程序服务和数据结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 管道:介绍和基本服务
- 下一篇: 嵌入式Linux的OTA更新,基础知识和