| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103 |
- /*
- * Copyright (c) 2013-2023 Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * -----------------------------------------------------------------------------
- *
- * Project: CMSIS-RTOS RTX
- * Title: Message Queue functions
- *
- * -----------------------------------------------------------------------------
- */
- #include "rtx_lib.h"
- // OS Runtime Object Memory Usage
- #ifdef RTX_OBJ_MEM_USAGE
- osRtxObjectMemUsage_t osRtxMessageQueueMemUsage \
- __attribute__((section(".data.os.msgqueue.obj"))) =
- { 0U, 0U, 0U };
- #endif
- // ==== Helper functions ====
- /// Put a Message into Queue sorted by Priority (Highest at Head).
- /// \param[in] mq message queue object.
- /// \param[in] msg message object.
- static void MessageQueuePut (os_message_queue_t *mq, os_message_t *msg) {
- #if (EXCLUSIVE_ACCESS == 0)
- uint32_t primask = __get_PRIMASK();
- #endif
- os_message_t *prev, *next;
- if (mq->msg_last != NULL) {
- prev = mq->msg_last;
- next = NULL;
- while ((prev != NULL) && (prev->priority < msg->priority)) {
- next = prev;
- prev = prev->prev;
- }
- msg->prev = prev;
- msg->next = next;
- if (prev != NULL) {
- prev->next = msg;
- } else {
- mq->msg_first = msg;
- }
- if (next != NULL) {
- next->prev = msg;
- } else {
- mq->msg_last = msg;
- }
- } else {
- msg->prev = NULL;
- msg->next = NULL;
- mq->msg_first= msg;
- mq->msg_last = msg;
- }
- #if (EXCLUSIVE_ACCESS == 0)
- __disable_irq();
- mq->msg_count++;
- if (primask == 0U) {
- __enable_irq();
- }
- #else
- (void)atomic_inc32(&mq->msg_count);
- #endif
- }
- /// Get a Message from Queue with Highest Priority.
- /// \param[in] mq message queue object.
- /// \return message object or NULL.
- static os_message_t *MessageQueueGet (os_message_queue_t *mq) {
- #if (EXCLUSIVE_ACCESS == 0)
- uint32_t primask = __get_PRIMASK();
- #endif
- os_message_t *msg;
- uint32_t count;
- uint8_t flags;
- #if (EXCLUSIVE_ACCESS == 0)
- __disable_irq();
- count = mq->msg_count;
- if (count != 0U) {
- mq->msg_count--;
- }
- if (primask == 0U) {
- __enable_irq();
- }
- #else
- count = atomic_dec32_nz(&mq->msg_count);
- #endif
- if (count != 0U) {
- msg = mq->msg_first;
- while (msg != NULL) {
- #if (EXCLUSIVE_ACCESS == 0)
- __disable_irq();
- flags = msg->flags;
- msg->flags = 1U;
- if (primask == 0U) {
- __enable_irq();
- }
- #else
- flags = atomic_wr8(&msg->flags, 1U);
- #endif
- if (flags == 0U) {
- break;
- }
- msg = msg->next;
- }
- } else {
- msg = NULL;
- }
- return msg;
- }
- /// Remove a Message from Queue
- /// \param[in] mq message queue object.
- /// \param[in] msg message object.
- static void MessageQueueRemove (os_message_queue_t *mq, const os_message_t *msg) {
- if (msg->prev != NULL) {
- msg->prev->next = msg->next;
- } else {
- mq->msg_first = msg->next;
- }
- if (msg->next != NULL) {
- msg->next->prev = msg->prev;
- } else {
- mq->msg_last = msg->prev;
- }
- }
- /// Verify that Message Queue object pointer is valid.
- /// \param[in] mq message queue object.
- /// \return true - valid, false - invalid.
- static bool_t IsMessageQueuePtrValid (const os_message_queue_t *mq) {
- #ifdef RTX_OBJ_PTR_CHECK
- //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
- uint32_t cb_start = (uint32_t)&__os_msgqueue_cb_start__;
- uint32_t cb_length = (uint32_t)&__os_msgqueue_cb_length__;
- // Check the section boundaries
- if (((uint32_t)mq - cb_start) >= cb_length) {
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return FALSE;
- }
- // Check the object alignment
- if ((((uint32_t)mq - cb_start) % sizeof(os_message_queue_t)) != 0U) {
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return FALSE;
- }
- #else
- // Check NULL pointer
- if (mq == NULL) {
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return FALSE;
- }
- #endif
- return TRUE;
- }
- // ==== Library functions ====
- /// Destroy a Message Queue object.
- /// \param[in] mq message queue object.
- static void osRtxMessageQueueDestroy (os_message_queue_t *mq) {
- // Mark object as invalid
- mq->id = osRtxIdInvalid;
- // Free data memory
- if ((mq->flags & osRtxFlagSystemMemory) != 0U) {
- (void)osRtxMemoryFree(osRtxInfo.mem.mq_data, mq->mp_info.block_base);
- }
- // Free object memory
- if ((mq->flags & osRtxFlagSystemObject) != 0U) {
- #ifdef RTX_OBJ_PTR_CHECK
- (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
- #else
- if (osRtxInfo.mpi.message_queue != NULL) {
- (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
- } else {
- (void)osRtxMemoryFree(osRtxInfo.mem.common, mq);
- }
- #endif
- #ifdef RTX_OBJ_MEM_USAGE
- osRtxMessageQueueMemUsage.cnt_free++;
- #endif
- }
- EvrRtxMessageQueueDestroyed(mq);
- }
- #ifdef RTX_SAFETY_CLASS
- /// Delete a Message Queue safety class.
- /// \param[in] safety_class safety class.
- /// \param[in] mode safety mode.
- void osRtxMessageQueueDeleteClass (uint32_t safety_class, uint32_t mode) {
- os_message_queue_t *mq;
- os_thread_t *thread;
- uint32_t length;
- //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
- mq = (os_message_queue_t *)(uint32_t)&__os_msgqueue_cb_start__;
- length = (uint32_t)&__os_msgqueue_cb_length__;
- while (length >= sizeof(os_message_queue_t)) {
- if ( (mq->id == osRtxIdMessageQueue) &&
- ((((mode & osSafetyWithSameClass) != 0U) &&
- ((mq->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
- (((mode & osSafetyWithLowerClass) != 0U) &&
- ((mq->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)))) {
- while (mq->thread_list != NULL) {
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
- }
- osRtxMessageQueueDestroy(mq);
- }
- length -= sizeof(os_message_queue_t);
- mq++;
- }
- }
- #endif
- // ==== Post ISR processing ====
- /// Message Queue post ISR processing.
- /// \param[in] msg message object.
- static void osRtxMessageQueuePostProcess (os_message_t *msg) {
- //lint --e{954} "Pointer variable 'reg' is not pointing to const"
- os_message_queue_t *mq;
- os_message_t *msg0;
- os_thread_t *thread;
- uint32_t *reg;
- const void *ptr_src;
- void *ptr_dst;
- if (msg->flags != 0U) {
- // Remove Message
- //lint -e{9079} -e{9087} "cast between pointers to different object types"
- mq = *((os_message_queue_t **)(void *)&msg[1]);
- MessageQueueRemove(mq, msg);
- // Free memory
- msg->id = osRtxIdInvalid;
- (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
- // Check if Thread is waiting to send a Message
- if (mq->thread_list != NULL) {
- // Try to allocate memory
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- msg0 = osRtxMemoryPoolAlloc(&mq->mp_info);
- if (msg0 != NULL) {
- // Wakeup waiting Thread with highest Priority
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
- // Copy Message (R1: const void *msg_ptr, R2: uint8_t msg_prio)
- reg = osRtxThreadRegPtr(thread);
- //lint -e{923} "cast from unsigned int to pointer"
- ptr_src = (const void *)reg[1];
- (void)memcpy(&msg0[1], ptr_src, mq->msg_size);
- // Store Message into Queue
- msg0->id = osRtxIdMessage;
- msg0->flags = 0U;
- msg0->priority = (uint8_t)reg[2];
- MessageQueuePut(mq, msg0);
- EvrRtxMessageQueueInserted(mq, ptr_src);
- }
- }
- } else {
- // New Message
- //lint -e{9079} -e{9087} "cast between pointers to different object types"
- mq = (void *)msg->next;
- //lint -e{9087} "cast between pointers to different object types"
- ptr_src = (const void *)msg->prev;
- // Check if Thread is waiting to receive a Message
- if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
- EvrRtxMessageQueueInserted(mq, ptr_src);
- // Wakeup waiting Thread with highest Priority
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
- // Copy Message (R1: void *msg_ptr, R2: uint8_t *msg_prio)
- reg = osRtxThreadRegPtr(thread);
- //lint -e{923} "cast from unsigned int to pointer"
- ptr_dst = (void *)reg[1];
- (void)memcpy(ptr_dst, &msg[1], mq->msg_size);
- if (reg[2] != 0U) {
- //lint -e{923} -e{9078} "cast from unsigned int to pointer"
- *((uint8_t *)reg[2]) = msg->priority;
- }
- EvrRtxMessageQueueRetrieved(mq, ptr_dst);
- // Free memory
- msg->id = osRtxIdInvalid;
- (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
- } else {
- EvrRtxMessageQueueInserted(mq, ptr_src);
- MessageQueuePut(mq, msg);
- }
- }
- }
- // ==== Service Calls ====
- /// Create and Initialize a Message Queue object.
- /// \note API identical to osMessageQueueNew
- static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
- os_message_queue_t *mq;
- #ifdef RTX_SAFETY_CLASS
- const os_thread_t *thread = osRtxThreadGetRunning();
- uint32_t attr_bits;
- #endif
- void *mq_mem;
- uint32_t mq_size;
- uint32_t block_size;
- uint32_t size;
- uint8_t flags;
- const char *name;
- // Check parameters
- if ((msg_count == 0U) || (msg_size == 0U) ||
- ((__CLZ(msg_count) + __CLZ(msg_size)) < 32U)) {
- EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t);
- size = msg_count * block_size;
- // Process attributes
- if (attr != NULL) {
- name = attr->name;
- #ifdef RTX_SAFETY_CLASS
- attr_bits = attr->attr_bits;
- #endif
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
- mq = attr->cb_mem;
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
- mq_mem = attr->mq_mem;
- mq_size = attr->mq_size;
- #ifdef RTX_SAFETY_CLASS
- if ((attr_bits & osSafetyClass_Valid) != 0U) {
- if ((thread != NULL) &&
- ((thread->attr >> osRtxAttrClass_Pos) <
- (uint8_t)((attr_bits & osSafetyClass_Msk) >> osSafetyClass_Pos))) {
- EvrRtxMessageQueueError(NULL, (int32_t)osErrorSafetyClass);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- }
- #endif
- if (mq != NULL) {
- if (!IsMessageQueuePtrValid(mq) || (attr->cb_size != sizeof(os_message_queue_t))) {
- EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- } else {
- if (attr->cb_size != 0U) {
- EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- }
- if (mq_mem != NULL) {
- //lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7]
- if ((((uint32_t)mq_mem & 3U) != 0U) || (mq_size < size)) {
- EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- } else {
- if (mq_size != 0U) {
- EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- }
- } else {
- name = NULL;
- #ifdef RTX_SAFETY_CLASS
- attr_bits = 0U;
- #endif
- mq = NULL;
- mq_mem = NULL;
- }
- // Allocate object memory if not provided
- if (mq == NULL) {
- if (osRtxInfo.mpi.message_queue != NULL) {
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- mq = osRtxMemoryPoolAlloc(osRtxInfo.mpi.message_queue);
- #ifndef RTX_OBJ_PTR_CHECK
- } else {
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- mq = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_message_queue_t), 1U);
- #endif
- }
- #ifdef RTX_OBJ_MEM_USAGE
- if (mq != NULL) {
- uint32_t used;
- osRtxMessageQueueMemUsage.cnt_alloc++;
- used = osRtxMessageQueueMemUsage.cnt_alloc - osRtxMessageQueueMemUsage.cnt_free;
- if (osRtxMessageQueueMemUsage.max_used < used) {
- osRtxMessageQueueMemUsage.max_used = used;
- }
- }
- #endif
- flags = osRtxFlagSystemObject;
- } else {
- flags = 0U;
- }
- // Allocate data memory if not provided
- if ((mq != NULL) && (mq_mem == NULL)) {
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- mq_mem = osRtxMemoryAlloc(osRtxInfo.mem.mq_data, size, 0U);
- if (mq_mem == NULL) {
- if ((flags & osRtxFlagSystemObject) != 0U) {
- #ifdef RTX_OBJ_PTR_CHECK
- (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
- #else
- if (osRtxInfo.mpi.message_queue != NULL) {
- (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
- } else {
- (void)osRtxMemoryFree(osRtxInfo.mem.common, mq);
- }
- #endif
- #ifdef RTX_OBJ_MEM_USAGE
- osRtxMessageQueueMemUsage.cnt_free++;
- #endif
- }
- mq = NULL;
- } else {
- (void)memset(mq_mem, 0, size);
- }
- flags |= osRtxFlagSystemMemory;
- }
- if (mq != NULL) {
- // Initialize control block
- mq->id = osRtxIdMessageQueue;
- mq->flags = flags;
- mq->attr = 0U;
- mq->name = name;
- mq->thread_list = NULL;
- mq->msg_size = msg_size;
- mq->msg_count = 0U;
- mq->msg_first = NULL;
- mq->msg_last = NULL;
- #ifdef RTX_SAFETY_CLASS
- if ((attr_bits & osSafetyClass_Valid) != 0U) {
- mq->attr |= (uint8_t)((attr_bits & osSafetyClass_Msk) >>
- (osSafetyClass_Pos - osRtxAttrClass_Pos));
- } else {
- // Inherit safety class from the running thread
- if (thread != NULL) {
- mq->attr |= (uint8_t)(thread->attr & osRtxAttrClass_Msk);
- }
- }
- #endif
- (void)osRtxMemoryPoolInit(&mq->mp_info, msg_count, block_size, mq_mem);
- // Register post ISR processing function
- osRtxInfo.post_process.message = osRtxMessageQueuePostProcess;
- EvrRtxMessageQueueCreated(mq, mq->name);
- } else {
- EvrRtxMessageQueueError(NULL, (int32_t)osErrorNoMemory);
- }
- return mq;
- }
- /// Get name of a Message Queue object.
- /// \note API identical to osMessageQueueGetName
- static const char *svcRtxMessageQueueGetName (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueGetName(mq, NULL);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return NULL;
- }
- EvrRtxMessageQueueGetName(mq, mq->name);
- return mq->name;
- }
- /// Put a Message into a Queue or timeout if Queue is full.
- /// \note API identical to osMessageQueuePut
- static osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
- //lint --e{954} "Pointer variable 'reg' is not pointing to const"
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_message_t *msg;
- os_thread_t *thread;
- uint32_t *reg;
- void *ptr;
- osStatus_t status;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- #ifdef RTX_SAFETY_CLASS
- // Check running thread safety class
- thread = osRtxThreadGetRunning();
- if ((thread != NULL) &&
- ((thread->attr >> osRtxAttrClass_Pos) < (mq->attr >> osRtxAttrClass_Pos))) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorSafetyClass);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorSafetyClass;
- }
- #endif
- // Check if Thread is waiting to receive a Message
- if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
- EvrRtxMessageQueueInserted(mq, msg_ptr);
- // Wakeup waiting Thread with highest Priority
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osOK, TRUE);
- // Copy Message (R1: void *msg_ptr, R2: uint8_t *msg_prio)
- reg = osRtxThreadRegPtr(thread);
- //lint -e{923} "cast from unsigned int to pointer"
- ptr = (void *)reg[1];
- (void)memcpy(ptr, msg_ptr, mq->msg_size);
- if (reg[2] != 0U) {
- //lint -e{923} -e{9078} "cast from unsigned int to pointer"
- *((uint8_t *)reg[2]) = msg_prio;
- }
- EvrRtxMessageQueueRetrieved(mq, ptr);
- status = osOK;
- } else {
- // Try to allocate memory
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- msg = osRtxMemoryPoolAlloc(&mq->mp_info);
- if (msg != NULL) {
- // Copy Message
- (void)memcpy(&msg[1], msg_ptr, mq->msg_size);
- // Put Message into Queue
- msg->id = osRtxIdMessage;
- msg->flags = 0U;
- msg->priority = msg_prio;
- MessageQueuePut(mq, msg);
- EvrRtxMessageQueueInserted(mq, msg_ptr);
- status = osOK;
- } else {
- // No memory available
- if (timeout != 0U) {
- EvrRtxMessageQueuePutPending(mq, msg_ptr, timeout);
- // Suspend current Thread
- if (osRtxThreadWaitEnter(osRtxThreadWaitingMessagePut, timeout)) {
- osRtxThreadListPut(osRtxObject(mq), osRtxThreadGetRunning());
- } else {
- EvrRtxMessageQueuePutTimeout(mq);
- }
- status = osErrorTimeout;
- } else {
- EvrRtxMessageQueueNotInserted(mq, msg_ptr);
- status = osErrorResource;
- }
- }
- }
- return status;
- }
- /// Get a Message from a Queue or timeout if Queue is empty.
- /// \note API identical to osMessageQueueGet
- static osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_message_t *msg;
- os_thread_t *thread;
- const uint32_t *reg;
- const void *ptr;
- osStatus_t status;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- #ifdef RTX_SAFETY_CLASS
- // Check running thread safety class
- thread = osRtxThreadGetRunning();
- if ((thread != NULL) &&
- ((thread->attr >> osRtxAttrClass_Pos) < (mq->attr >> osRtxAttrClass_Pos))) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorSafetyClass);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorSafetyClass;
- }
- #endif
- // Get Message from Queue
- msg = MessageQueueGet(mq);
- if (msg != NULL) {
- MessageQueueRemove(mq, msg);
- // Copy Message
- (void)memcpy(msg_ptr, &msg[1], mq->msg_size);
- if (msg_prio != NULL) {
- *msg_prio = msg->priority;
- }
- EvrRtxMessageQueueRetrieved(mq, msg_ptr);
- // Free memory
- msg->id = osRtxIdInvalid;
- (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
- // Check if Thread is waiting to send a Message
- if (mq->thread_list != NULL) {
- // Try to allocate memory
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- msg = osRtxMemoryPoolAlloc(&mq->mp_info);
- if (msg != NULL) {
- // Wakeup waiting Thread with highest Priority
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osOK, TRUE);
- // Copy Message (R1: const void *msg_ptr, R2: uint8_t msg_prio)
- reg = osRtxThreadRegPtr(thread);
- //lint -e{923} "cast from unsigned int to pointer"
- ptr = (const void *)reg[1];
- (void)memcpy(&msg[1], ptr, mq->msg_size);
- // Store Message into Queue
- msg->id = osRtxIdMessage;
- msg->flags = 0U;
- msg->priority = (uint8_t)reg[2];
- MessageQueuePut(mq, msg);
- EvrRtxMessageQueueInserted(mq, ptr);
- }
- }
- status = osOK;
- } else {
- // No Message available
- if (timeout != 0U) {
- EvrRtxMessageQueueGetPending(mq, msg_ptr, timeout);
- // Suspend current Thread
- if (osRtxThreadWaitEnter(osRtxThreadWaitingMessageGet, timeout)) {
- osRtxThreadListPut(osRtxObject(mq), osRtxThreadGetRunning());
- } else {
- EvrRtxMessageQueueGetTimeout(mq);
- }
- status = osErrorTimeout;
- } else {
- EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
- status = osErrorResource;
- }
- }
- return status;
- }
- /// Get maximum number of messages in a Message Queue.
- /// \note API identical to osMessageQueueGetCapacity
- static uint32_t svcRtxMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueGetCapacity(mq, 0U);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return 0U;
- }
- EvrRtxMessageQueueGetCapacity(mq, mq->mp_info.max_blocks);
- return mq->mp_info.max_blocks;
- }
- /// Get maximum message size in a Memory Pool.
- /// \note API identical to osMessageQueueGetMsgSize
- static uint32_t svcRtxMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueGetMsgSize(mq, 0U);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return 0U;
- }
- EvrRtxMessageQueueGetMsgSize(mq, mq->msg_size);
- return mq->msg_size;
- }
- /// Get number of queued messages in a Message Queue.
- /// \note API identical to osMessageQueueGetCount
- static uint32_t svcRtxMessageQueueGetCount (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueGetCount(mq, 0U);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return 0U;
- }
- EvrRtxMessageQueueGetCount(mq, mq->msg_count);
- return mq->msg_count;
- }
- /// Get number of available slots for messages in a Message Queue.
- /// \note API identical to osMessageQueueGetSpace
- static uint32_t svcRtxMessageQueueGetSpace (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueGetSpace(mq, 0U);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return 0U;
- }
- EvrRtxMessageQueueGetSpace(mq, mq->mp_info.max_blocks - mq->msg_count);
- return (mq->mp_info.max_blocks - mq->msg_count);
- }
- /// Reset a Message Queue to initial empty state.
- /// \note API identical to osMessageQueueReset
- static osStatus_t svcRtxMessageQueueReset (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_message_t *msg;
- os_thread_t *thread;
- const uint32_t *reg;
- const void *ptr;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- #ifdef RTX_SAFETY_CLASS
- // Check running thread safety class
- thread = osRtxThreadGetRunning();
- if ((thread != NULL) &&
- ((thread->attr >> osRtxAttrClass_Pos) < (mq->attr >> osRtxAttrClass_Pos))) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorSafetyClass);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorSafetyClass;
- }
- #endif
- // Remove Messages from Queue
- for (;;) {
- // Get Message from Queue
- msg = MessageQueueGet(mq);
- if (msg == NULL) {
- break;
- }
- MessageQueueRemove(mq, msg);
- EvrRtxMessageQueueRetrieved(mq, NULL);
- // Free memory
- msg->id = osRtxIdInvalid;
- (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
- }
- // Check if Threads are waiting to send Messages
- if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
- do {
- // Try to allocate memory
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- msg = osRtxMemoryPoolAlloc(&mq->mp_info);
- if (msg != NULL) {
- // Wakeup waiting Thread with highest Priority
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
- // Copy Message (R1: const void *msg_ptr, R2: uint8_t msg_prio)
- reg = osRtxThreadRegPtr(thread);
- //lint -e{923} "cast from unsigned int to pointer"
- ptr = (const void *)reg[1];
- (void)memcpy(&msg[1], ptr, mq->msg_size);
- // Store Message into Queue
- msg->id = osRtxIdMessage;
- msg->flags = 0U;
- msg->priority = (uint8_t)reg[2];
- MessageQueuePut(mq, msg);
- EvrRtxMessageQueueInserted(mq, ptr);
- }
- } while ((msg != NULL) && (mq->thread_list != NULL));
- osRtxThreadDispatch(NULL);
- }
- EvrRtxMessageQueueResetDone(mq);
- return osOK;
- }
- /// Delete a Message Queue object.
- /// \note API identical to osMessageQueueDelete
- static osStatus_t svcRtxMessageQueueDelete (osMessageQueueId_t mq_id) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_thread_t *thread;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- #ifdef RTX_SAFETY_CLASS
- // Check running thread safety class
- thread = osRtxThreadGetRunning();
- if ((thread != NULL) &&
- ((thread->attr >> osRtxAttrClass_Pos) < (mq->attr >> osRtxAttrClass_Pos))) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorSafetyClass);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorSafetyClass;
- }
- #endif
- // Unblock waiting threads
- if (mq->thread_list != NULL) {
- do {
- thread = osRtxThreadListGet(osRtxObject(mq));
- osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
- } while (mq->thread_list != NULL);
- osRtxThreadDispatch(NULL);
- }
- osRtxMessageQueueDestroy(mq);
- return osOK;
- }
- // Service Calls definitions
- //lint ++flb "Library Begin" [MISRA Note 11]
- SVC0_3(MessageQueueNew, osMessageQueueId_t, uint32_t, uint32_t, const osMessageQueueAttr_t *)
- SVC0_1(MessageQueueGetName, const char *, osMessageQueueId_t)
- SVC0_4(MessageQueuePut, osStatus_t, osMessageQueueId_t, const void *, uint8_t, uint32_t)
- SVC0_4(MessageQueueGet, osStatus_t, osMessageQueueId_t, void *, uint8_t *, uint32_t)
- SVC0_1(MessageQueueGetCapacity, uint32_t, osMessageQueueId_t)
- SVC0_1(MessageQueueGetMsgSize, uint32_t, osMessageQueueId_t)
- SVC0_1(MessageQueueGetCount, uint32_t, osMessageQueueId_t)
- SVC0_1(MessageQueueGetSpace, uint32_t, osMessageQueueId_t)
- SVC0_1(MessageQueueReset, osStatus_t, osMessageQueueId_t)
- SVC0_1(MessageQueueDelete, osStatus_t, osMessageQueueId_t)
- //lint --flb "Library End"
- // ==== ISR Calls ====
- /// Put a Message into a Queue or timeout if Queue is full.
- /// \note API identical to osMessageQueuePut
- __STATIC_INLINE
- osStatus_t isrRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_message_t *msg;
- osStatus_t status;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- // Try to allocate memory
- //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
- msg = osRtxMemoryPoolAlloc(&mq->mp_info);
- if (msg != NULL) {
- // Copy Message
- (void)memcpy(&msg[1], msg_ptr, mq->msg_size);
- msg->id = osRtxIdMessage;
- msg->flags = 0U;
- msg->priority = msg_prio;
- // Register post ISR processing
- //lint -e{9079} -e{9087} "cast between pointers to different object types"
- *((const void **)(void *)&msg->prev) = msg_ptr;
- //lint -e{9079} -e{9087} "cast between pointers to different object types"
- *( (void **) &msg->next) = mq;
- osRtxPostProcess(osRtxObject(msg));
- EvrRtxMessageQueueInsertPending(mq, msg_ptr);
- status = osOK;
- } else {
- // No memory available
- EvrRtxMessageQueueNotInserted(mq, msg_ptr);
- status = osErrorResource;
- }
- return status;
- }
- /// Get a Message from a Queue or timeout if Queue is empty.
- /// \note API identical to osMessageQueueGet
- __STATIC_INLINE
- osStatus_t isrRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
- os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
- os_message_t *msg;
- osStatus_t status;
- // Check parameters
- if (!IsMessageQueuePtrValid(mq) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
- EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osErrorParameter;
- }
- // Get Message from Queue
- msg = MessageQueueGet(mq);
- if (msg != NULL) {
- // Copy Message
- memcpy(msg_ptr, &msg[1], mq->msg_size);
- if (msg_prio != NULL) {
- *msg_prio = msg->priority;
- }
- // Register post ISR processing
- //lint -e{9079} -e{9087} "cast between pointers to different object types"
- *((os_message_queue_t **)(void *)&msg[1]) = mq;
- osRtxPostProcess(osRtxObject(msg));
- EvrRtxMessageQueueRetrieved(mq, msg_ptr);
- status = osOK;
- } else {
- // No Message available
- EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
- status = osErrorResource;
- }
- return status;
- }
- // ==== Library functions ====
- /// Create a Message Queue for the Timer Thread.
- int32_t osRtxMessageQueueTimerSetup (void) {
- int32_t ret = -1;
- osRtxInfo.timer.mq = osRtxMessageQueueId(
- svcRtxMessageQueueNew(osRtxConfig.timer_mq_mcnt, sizeof(os_timer_finfo_t), osRtxConfig.timer_mq_attr)
- );
- if (osRtxInfo.timer.mq != NULL) {
- ret = 0;
- }
- return ret;
- }
- // ==== Public API ====
- /// Create and Initialize a Message Queue object.
- osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
- osMessageQueueId_t mq_id;
- EvrRtxMessageQueueNew(msg_count, msg_size, attr);
- if (IsException() || IsIrqMasked()) {
- EvrRtxMessageQueueError(NULL, (int32_t)osErrorISR);
- mq_id = NULL;
- } else {
- mq_id = __svcMessageQueueNew(msg_count, msg_size, attr);
- }
- return mq_id;
- }
- /// Get name of a Message Queue object.
- const char *osMessageQueueGetName (osMessageQueueId_t mq_id) {
- const char *name;
- if (IsException() || IsIrqMasked()) {
- name = svcRtxMessageQueueGetName(mq_id);
- } else {
- name = __svcMessageQueueGetName(mq_id);
- }
- return name;
- }
- /// Put a Message into a Queue or timeout if Queue is full.
- osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
- osStatus_t status;
- EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
- if (IsException() || IsIrqMasked()) {
- status = isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
- } else {
- status = __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
- }
- return status;
- }
- /// Get a Message from a Queue or timeout if Queue is empty.
- osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
- osStatus_t status;
- EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
- if (IsException() || IsIrqMasked()) {
- status = isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
- } else {
- status = __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
- }
- return status;
- }
- /// Get maximum number of messages in a Message Queue.
- uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
- uint32_t capacity;
- if (IsException() || IsIrqMasked()) {
- capacity = svcRtxMessageQueueGetCapacity(mq_id);
- } else {
- capacity = __svcMessageQueueGetCapacity(mq_id);
- }
- return capacity;
- }
- /// Get maximum message size in a Memory Pool.
- uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
- uint32_t msg_size;
- if (IsException() || IsIrqMasked()) {
- msg_size = svcRtxMessageQueueGetMsgSize(mq_id);
- } else {
- msg_size = __svcMessageQueueGetMsgSize(mq_id);
- }
- return msg_size;
- }
- /// Get number of queued messages in a Message Queue.
- uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
- uint32_t count;
- if (IsException() || IsIrqMasked()) {
- count = svcRtxMessageQueueGetCount(mq_id);
- } else {
- count = __svcMessageQueueGetCount(mq_id);
- }
- return count;
- }
- /// Get number of available slots for messages in a Message Queue.
- uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
- uint32_t space;
- if (IsException() || IsIrqMasked()) {
- space = svcRtxMessageQueueGetSpace(mq_id);
- } else {
- space = __svcMessageQueueGetSpace(mq_id);
- }
- return space;
- }
- /// Reset a Message Queue to initial empty state.
- osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
- osStatus_t status;
- EvrRtxMessageQueueReset(mq_id);
- if (IsException() || IsIrqMasked()) {
- EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR);
- status = osErrorISR;
- } else {
- status = __svcMessageQueueReset(mq_id);
- }
- return status;
- }
- /// Delete a Message Queue object.
- osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
- osStatus_t status;
- EvrRtxMessageQueueDelete(mq_id);
- if (IsException() || IsIrqMasked()) {
- EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR);
- status = osErrorISR;
- } else {
- status = __svcMessageQueueDelete(mq_id);
- }
- return status;
- }
|