diff --git a/rtos/Mail.h b/rtos/Mail.h index 66499d80c7..af9ce312e7 100644 --- a/rtos/Mail.h +++ b/rtos/Mail.h @@ -70,7 +70,7 @@ public: * * @note You cannot call this function from ISR context. */ - Mail() { }; + Mail() = default; /** Check if the mail queue is empty. * @@ -114,15 +114,47 @@ public: /** Allocate a memory block of type T, optionally blocking. * - * @param millisec Timeout value, or osWaitForever. + * @param rel_time Timeout value, or Kernel::wait_for_u32_forever. * * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context if the millisec parameter is set to 0. */ + T *alloc_for(Kernel::Clock::duration_u32 rel_time) + { + return _pool.alloc_for(rel_time); + } + + /** Allocate a memory block of type T, optionally blocking. + * + * @param millisec Timeout value, or osWaitForever. + * + * @return Pointer to memory block that you can fill with mail or nullptr in case error. + * + * @note You may call this function from ISR context if the millisec parameter is set to 0. + * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. + */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") T *alloc_for(uint32_t millisec) { - return _pool.alloc_for(millisec); + return alloc_for(std::chrono::duration(millisec)); + } + + /** Allocate a memory block of type T, blocking. + * + * @param abs_time Absolute timeout time, referenced to Kernel::Clock. + * + * @return Pointer to memory block that you can fill with mail or nullptr in case error. + * + * @note You cannot call this function from ISR context. + * @note the underlying RTOS may have a limit to the maximum wait time + * due to internal 32-bit computations, but this is guaranteed to work if the + * wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, + * the wait will time out earlier than specified. + */ + T *alloc_until(Kernel::Clock::time_point abs_time) + { + return _pool.alloc_until(abs_time); } /** Allocate a memory block of type T, blocking. @@ -136,10 +168,13 @@ public: * due to internal 32-bit computations, but this is guaranteed to work if the * wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, * the wait will time out earlier than specified. + * @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` + * rather than `Kernel::get_ms_count() + 5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.") T *alloc_until(uint64_t millisec) { - return _pool.alloc_until(millisec); + return alloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); } /** Allocate a memory block of type T, and set memory block to zero. @@ -156,6 +191,19 @@ public: return _pool.calloc(); } + /** Allocate a memory block of type T, optionally blocking, and set memory block to zero. + * + * @param rel_time Timeout value, or Kernel::wait_for_u32_forever. + * + * @return Pointer to memory block that you can fill with mail or nullptr in case error. + * + * @note You may call this function from ISR context if the rel_time parameter is set to 0. + */ + T *calloc_for(Kernel::Clock::duration_u32 rel_time) + { + return _pool.alloc_for(rel_time); + } + /** Allocate a memory block of type T, optionally blocking, and set memory block to zero. * * @param millisec Timeout value, or osWaitForever. @@ -163,10 +211,29 @@ public: * @return Pointer to memory block that you can fill with mail or nullptr in case error. * * @note You may call this function from ISR context if the millisec parameter is set to 0. + * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") T *calloc_for(uint32_t millisec) { - return _pool.calloc_for(millisec); + return calloc_for(std::chrono::duration(millisec)); + } + + /** Allocate a memory block of type T, blocking, and set memory block to zero. + * + * @param abs_time Absolute timeout time, referenced to Kernel::Clock. + * + * @return Pointer to memory block that you can fill with mail or nullptr in case error. + * + * @note You cannot call this function from ISR context. + * @note the underlying RTOS may have a limit to the maximum wait time + * due to internal 32-bit computations, but this is guaranteed to work if the + * wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, + * the wait will time out earlier than specified. + */ + T *calloc_until(Kernel::Clock::time_point abs_time) + { + return _pool.calloc_until(abs_time); } /** Allocate a memory block of type T, blocking, and set memory block to zero. @@ -180,10 +247,13 @@ public: * due to internal 32-bit computations, but this is guaranteed to work if the * wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, * the wait will time out earlier than specified. + * @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` + * rather than `Kernel::get_ms_count() + 5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.") T *calloc_until(uint64_t millisec) { - return _pool.calloc_until(millisec); + return calloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); } /** Put a mail in the queue. @@ -201,7 +271,26 @@ public: /** Get a mail from the queue. * - * @param millisec Timeout value (default: osWaitForever). + * @param millisec Timeout value. + * + * @return Event that contains mail information or error code. + * @retval osEventMessage Message received. + * @retval osOK No mail is available (and no timeout was specified). + * @retval osEventTimeout No mail has arrived during the given timeout period. + * @retval osErrorParameter A parameter is invalid or outside of a permitted range. + * + * @note You may call this function from ISR context if the millisec parameter is set to 0. + * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. + */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") + osEvent get(uint32_t millisec) + { + return get(std::chrono::duration(millisec)); + } + + /** Get a mail from the queue. + * + * @param rel_time Timeout value (default: Kernel::wait_for_u32_forever). * * @return Event that contains mail information and status code. The status code * is stored in the status member: @@ -212,9 +301,9 @@ public: * * @note You may call this function from ISR context if the millisec parameter is set to 0. */ - osEvent get(uint32_t millisec = osWaitForever) + osEvent get(Kernel::Clock::duration_u32 rel_time = Kernel::wait_for_u32_forever) { - osEvent evt = _queue.get(millisec); + osEvent evt = _queue.get(rel_time); if (evt.status == osEventMessage) { evt.status = osEventMail; } diff --git a/rtos/MemoryPool.h b/rtos/MemoryPool.h index 88bf1b23cf..81456eddd6 100644 --- a/rtos/MemoryPool.h +++ b/rtos/MemoryPool.h @@ -94,15 +94,38 @@ public: return (T *)osMemoryPoolAlloc(_id, 0); } + /** Allocate a memory block from a memory pool, without blocking. + @return address of the allocated memory block or nullptr in case of no memory available. + + @note You may call this function from ISR context. + */ + T *try_alloc(void) + { + return (T *)osMemoryPoolAlloc(_id, 0); + } + /** Allocate a memory block from a memory pool, optionally blocking. @param millisec timeout value (osWaitForever to wait forever) @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context if the millisec parameter is set to 0. + @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") T *alloc_for(uint32_t millisec) { - return (T *)osMemoryPoolAlloc(_id, millisec); + return alloc_for(std::chrono::duration(millisec)); + } + + /** Allocate a memory block from a memory pool, optionally blocking. + @param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever) + @return address of the allocated memory block or nullptr in case of no memory available. + + @note You may call this function from ISR context if the rel_time parameter is set to 0. + */ + T *alloc_for(Kernel::Clock::duration_u32 rel_time) + { + return (T *)osMemoryPoolAlloc(_id, rel_time.count()); } /** Allocate a memory block from a memory pool, blocking. @@ -114,21 +137,38 @@ public: due to internal 32-bit computations, but this is guaranteed to work if the wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, the wait will time out earlier than specified. + @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` + rather than `Kernel::get_ms_count() + 5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.") T *alloc_until(uint64_t millisec) { - uint64_t now = Kernel::get_ms_count(); - uint32_t delay; - if (now >= millisec) { - delay = 0; - } else if (millisec - now >= osWaitForever) { - delay = osWaitForever - 1; - } else { - delay = millisec - now; - } - return alloc_for(delay); + return alloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); } + /** Allocate a memory block from a memory pool, blocking. + @param abs_time absolute timeout time, referenced to Kernel::Clock. + @return address of the allocated memory block or nullptr in case of no memory available. + + @note You cannot call this function from ISR context. + @note the underlying RTOS may have a limit to the maximum wait time + due to internal 32-bit computations, but this is guaranteed to work if the + wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, + the wait will time out earlier than specified. + */ + T *alloc_until(Kernel::Clock::time_point abs_time) + { + Kernel::Clock::time_point now = Kernel::Clock::now(); + Kernel::Clock::duration_u32 rel_time; + if (now >= abs_time) { + rel_time = rel_time.zero(); + } else if (abs_time - now > Kernel::wait_for_u32_max) { + rel_time = Kernel::wait_for_u32_max; + } else { + rel_time = abs_time - now; + } + return alloc_for(rel_time); + } /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero. @return address of the allocated memory block or nullptr in case of no memory available. @@ -148,10 +188,23 @@ public: @return address of the allocated memory block or nullptr in case of no memory available. @note You may call this function from ISR context if the millisec parameter is set to 0. + @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") T *calloc_for(uint32_t millisec) { - T *item = alloc_for(millisec); + return calloc_for(std::chrono::duration(millisec)); + } + + /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero. + @param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever) + @return address of the allocated memory block or nullptr in case of no memory available. + + @note You may call this function from ISR context if the rel_time parameter is set to 0. + */ + T *calloc_for(Kernel::Clock::duration_u32 rel_time) + { + T *item = alloc_for(rel_time); if (item != nullptr) { memset(item, 0, sizeof(T)); } @@ -167,10 +220,28 @@ public: due to internal 32-bit computations, but this is guaranteed to work if the wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, the wait will time out earlier than specified. + @deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` + rather than `Kernel::get_ms_count() + 5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.") T *calloc_until(uint64_t millisec) { - T *item = alloc_until(millisec); + return alloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); + } + + /** Allocate a memory block from a memory pool, blocking, and set memory block to zero. + @param abs_time absolute timeout time, referenced to Kernel::Clock. + @return address of the allocated memory block or nullptr in case of no memory available. + + @note You cannot call this function from ISR context. + @note the underlying RTOS may have a limit to the maximum wait time + due to internal 32-bit computations, but this is guaranteed to work if the + wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded, + the wait will time out earlier than specified. + */ + T *calloc_until(Kernel::Clock::time_point abs_time) + { + T *item = alloc_until(abs_time); if (item != nullptr) { memset(item, 0, sizeof(T)); } diff --git a/rtos/Queue.h b/rtos/Queue.h index 1c176d1045..14081ecd0b 100644 --- a/rtos/Queue.h +++ b/rtos/Queue.h @@ -26,6 +26,7 @@ #include "rtos/mbed_rtos_types.h" #include "rtos/mbed_rtos1_types.h" #include "rtos/mbed_rtos_storage.h" +#include "rtos/Kernel.h" #include "platform/mbed_error.h" #include "platform/NonCopyable.h" @@ -121,6 +122,47 @@ public: return osMessageQueueGetCount(_id); } + /** Inserts the given element to the end of the queue. + * + * This function puts the message pointed to by `data` into the queue. The + * parameter `prio` is used to sort the message according to their priority + * (higher numbers indicate higher priority) on insertion. + * + * The timeout indicated by the parameter `rel_time` specifies how long the + * function blocks waiting for the message to be inserted into the + * queue. + * + * The parameter `rel_time` can have the following values: + * - When the duration is 0 (the default), the function returns instantly. + * - When the duration is Kernel::wait_for_u32_forever, the function waits for an + * infinite time. + * - For all other values, the function waits for the given duration. + * + * @param data Pointer to the element to insert into the queue. + * @param rel_time Timeout for the operation to be executed, or 0 in case + * of no timeout. (default: 0) + * @param prio Priority of the operation or 0 in case of default. + * (default: 0) + * + * @return Status code that indicates the execution status of the function: + * @a osOK The message has been successfully inserted + * into the queue. + * @a osErrorTimeout The message could not be inserted into the + * queue in the given time. + * @a osErrorResource The message could not be inserted because + * the queue is full. + * @a osErrorParameter Internal error or nonzero timeout specified + * in an ISR. + * + * @note You may call this function from ISR context if the rel_time + * parameter is set to 0. + * + */ + osStatus put(T *data, Kernel::Clock::duration_u32 rel_time = Kernel::Clock::duration_u32::zero(), uint8_t prio = 0) + { + return osMessageQueuePut(_id, &data, prio, rel_time.count()); + } + /** Inserts the given element to the end of the queue. * * This function puts the message pointed to by `data` into the queue. The @@ -156,11 +198,74 @@ public: * * @note You may call this function from ISR context if the millisec * parameter is set to 0. - * + * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") osStatus put(T *data, uint32_t millisec = 0, uint8_t prio = 0) { - return osMessageQueuePut(_id, &data, prio, millisec); + return put(data, std::chrono::duration(millisec), prio); + } + + /** Get a message or wait for a message from the queue. + * + * This function retrieves a message from the queue. The message is stored + * in the value field of the returned `osEvent` object. + * + * The timeout specified by the parameter `rel_time` specifies how long the + * function waits to retrieve the message from the queue. + * + * The timeout parameter can have the following values: + * - When the timeout is 0, the function returns instantly. + * - When the timeout is Kernel::wait_for_u32_forever (default), the function waits + * infinite time until the message is retrieved. + * - When the timeout is any other value, the function waits for the + * specified time before returning a timeout error. + * + * Messages are retrieved in descending priority order. If two messages + * share the same priority level, they are retrieved in first-in, first-out + * (FIFO) order. + * + * @param rel_time Timeout value. + * (default: Kernel::wait_for_u32_forever). + * + * @return Event information that includes the message in event. Message + * value and the status code in event.status: + * @a osEventMessage Message successfully received. + * @a osOK No message is available in the queue, and no + * timeout was specified. + * @a osEventTimeout No message was received before a timeout + * event occurred. + * @a osErrorParameter A parameter is invalid or outside of a + * permitted range. + * + * @note You may call this function from ISR context if the rel_time + * parameter is set to 0. + */ + osEvent get(Kernel::Clock::duration_u32 rel_time = Kernel::wait_for_u32_forever) + { + osEvent event; + T *data = nullptr; + osStatus_t res = osMessageQueueGet(_id, &data, nullptr, rel_time.count()); + + switch (res) { + case osOK: + event.status = (osStatus)osEventMessage; + event.value.p = data; + break; + case osErrorResource: + event.status = osOK; + break; + case osErrorTimeout: + event.status = (osStatus)osEventTimeout; + break; + case osErrorParameter: + default: + event.status = osErrorParameter; + break; + } + event.def.message_id = _id; + + return event; } /** Get a message or wait for a message from the queue. @@ -197,34 +302,13 @@ public: * * @note You may call this function from ISR context if the millisec * parameter is set to 0. + * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") osEvent get(uint32_t millisec = osWaitForever) { - osEvent event; - T *data = nullptr; - osStatus_t res = osMessageQueueGet(_id, &data, nullptr, millisec); - - switch (res) { - case osOK: - event.status = (osStatus)osEventMessage; - event.value.p = data; - break; - case osErrorResource: - event.status = osOK; - break; - case osErrorTimeout: - event.status = (osStatus)osEventTimeout; - break; - case osErrorParameter: - default: - event.status = osErrorParameter; - break; - } - event.def.message_id = _id; - - return event; + return get(std::chrono::duration(millisec)); } - private: osMessageQueueId_t _id; char _queue_mem[queue_sz * (sizeof(T *) + sizeof(mbed_rtos_storage_message_t))];