diff --git a/os/hal/osal/os-less/ARMCMx/osal.h b/os/hal/osal/os-less/ARMCMx/osal.h index 362a30c66..0450ace61 100644 --- a/os/hal/osal/os-less/ARMCMx/osal.h +++ b/os/hal/osal/os-less/ARMCMx/osal.h @@ -186,6 +186,13 @@ typedef uint32_t systime_t; */ typedef uint32_t sysinterval_t; +/** + * @brief Type of time conversion variable. + * @note This type must have double width than other time types, it is + * only used internally for conversions. + */ +typedef uint64_t time_conv_t; + /** * @brief Type of realtime counter. */ @@ -361,9 +368,12 @@ typedef struct { * @{ */ /** - * @brief Seconds to system ticks. + * @brief Seconds to time interval. * @details Converts from seconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] secs number of seconds * @return The number of ticks. @@ -371,12 +381,15 @@ typedef struct { * @api */ #define OSAL_S2I(secs) \ - ((sysinterval_t)((uint32_t)(secs) * (uint32_t)OSAL_ST_FREQUENCY)) + ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)OSAL_ST_FREQUENCY)) /** - * @brief Milliseconds to system ticks. + * @brief Milliseconds to time interval. * @details Converts from milliseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] msecs number of milliseconds * @return The number of ticks. @@ -384,13 +397,17 @@ typedef struct { * @api */ #define OSAL_MS2I(msecs) \ - ((sysinterval_t)((((((uint32_t)(msecs)) * \ - ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000UL) + 1UL)) + ((sysinterval_t)((((time_conv_t)(msecs) * \ + (time_conv_t)OSAL_ST_FREQUENCY) + \ + (time_conv_t)999) / (time_conv_t)1000)) /** - * @brief Microseconds to system ticks. + * @brief Microseconds to time interval. * @details Converts from microseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] usecs number of microseconds * @return The number of ticks. @@ -398,8 +415,63 @@ typedef struct { * @api */ #define OSAL_US2I(usecs) \ - ((sysinterval_t)((((((uint32_t)(usecs)) * \ - ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000000UL) + 1UL)) + ((sysinterval_t)((((time_conv_t)(usecs) * \ + (time_conv_t)OSAL_ST_FREQUENCY) + \ + (time_conv_t)999999) / (time_conv_t)1000000)) + +/** + * @brief Time interval to seconds. + * @details Converts from system ticks number to seconds. + * @note The result is rounded up to the next second boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of seconds. + * + * @api + */ +#define OSAL_I2S(interval) \ + (time_secs_t)(((time_conv_t)(interval) + \ + (time_conv_t)OSAL_ST_FREQUENCY - \ + (time_conv_t)1) / (time_conv_t)OSAL_ST_FREQUENCY) + +/** + * @brief Time interval to milliseconds. + * @details Converts from system ticks number to milliseconds. + * @note The result is rounded up to the next millisecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of milliseconds. + * + * @api + */ +#define OSAL_I2MS(interval) \ + (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \ + (time_conv_t)OSAL_ST_FREQUENCY - (time_conv_t)1) / \ + (time_conv_t)OSAL_ST_FREQUENCY) + +/** + * @brief Time interval to microseconds. + * @details Converts from system ticks number to microseconds. + * @note The result is rounded up to the next microsecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of microseconds. + * + * @api + */ +#define OSAL_I2US(interval) \ + (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \ + (time_conv_t)OSAL_ST_FREQUENCY - (time_conv_t)1) / \ + (time_conv_t)OSAL_ST_FREQUENCY) /** @} */ /** diff --git a/os/hal/osal/rt-nil/osal.h b/os/hal/osal/rt-nil/osal.h index 73e8e3fa9..27b086fe7 100644 --- a/os/hal/osal/rt-nil/osal.h +++ b/os/hal/osal/rt-nil/osal.h @@ -155,6 +155,15 @@ typedef uint32_t systime_t; typedef uint32_t sysinterval_t; #endif +#if 0 +/** + * @brief Type of time conversion variable. + * @note This type must have double width than other time types, it is + * only used internally for conversions. + */ +typedef uint64_t time_conv_t; +#endif + #if 0 /** * @brief Type of realtime counter. @@ -318,9 +327,12 @@ typedef struct { * @{ */ /** - * @brief Seconds to system ticks. + * @brief Seconds to time interval. * @details Converts from seconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] secs number of seconds * @return The number of ticks. @@ -330,9 +342,12 @@ typedef struct { #define OSAL_S2I(secs) TIME_S2I(secs) /** - * @brief Milliseconds to system ticks. + * @brief Milliseconds to time interval. * @details Converts from milliseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] msecs number of milliseconds * @return The number of ticks. @@ -342,9 +357,12 @@ typedef struct { #define OSAL_MS2I(msecs) TIME_MS2I(msecs) /** - * @brief Microseconds to system ticks. + * @brief Microseconds to time interval. * @details Converts from microseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] usecs number of microseconds * @return The number of ticks. @@ -352,6 +370,51 @@ typedef struct { * @api */ #define OSAL_US2I(usecs) TIME_US2I(usecs) + +/** + * @brief Time interval to seconds. + * @details Converts from system ticks number to seconds. + * @note The result is rounded up to the next second boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of seconds. + * + * @api + */ +#define OSAL_I2S(interval) TIME_I2S(interval) + +/** + * @brief Time interval to milliseconds. + * @details Converts from system ticks number to milliseconds. + * @note The result is rounded up to the next millisecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of milliseconds. + * + * @api + */ +#define OSAL_I2MS(interval) TIME_I2MS(interval) + +/** + * @brief Time interval to microseconds. + * @details Converts from system ticks number to microseconds. + * @note The result is rounded up to the next microsecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of microseconds. + * + * @api + */ +#define OSAL_I2US(interval) TIME_I2US(interval) /** @} */ /** diff --git a/os/hal/templates/osal/osal.h b/os/hal/templates/osal/osal.h index 5c38c21c4..273ccb7e8 100644 --- a/os/hal/templates/osal/osal.h +++ b/os/hal/templates/osal/osal.h @@ -168,6 +168,13 @@ typedef uint32_t systime_t; */ typedef uint32_t sysinterval_t; +/** + * @brief Type of time conversion variable. + * @note This type must have double width than other time types, it is + * only used internally for conversions. + */ +typedef uint64_t time_conv_t; + /** * @brief Type of realtime counter. */ @@ -333,9 +340,12 @@ typedef struct { * @{ */ /** - * @brief Seconds to system ticks. + * @brief Seconds to time interval. * @details Converts from seconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] secs number of seconds * @return The number of ticks. @@ -343,12 +353,15 @@ typedef struct { * @api */ #define OSAL_S2I(secs) \ - ((sysinterval_t)((uint32_t)(secs) * (uint32_t)OSAL_ST_FREQUENCY)) + ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)OSAL_ST_FREQUENCY)) /** - * @brief Milliseconds to system ticks. + * @brief Milliseconds to time interval. * @details Converts from milliseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] msecs number of milliseconds * @return The number of ticks. @@ -356,13 +369,17 @@ typedef struct { * @api */ #define OSAL_MS2I(msecs) \ - ((sysinterval_t)((((((uint32_t)(msecs)) * \ - ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000UL) + 1UL)) + ((sysinterval_t)((((time_conv_t)(msecs) * \ + (time_conv_t)OSAL_ST_FREQUENCY) + \ + (time_conv_t)999) / (time_conv_t)1000)) /** - * @brief Microseconds to system ticks. + * @brief Microseconds to time interval. * @details Converts from microseconds to system ticks number. * @note The result is rounded upward to the next tick boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. * * @param[in] usecs number of microseconds * @return The number of ticks. @@ -370,8 +387,63 @@ typedef struct { * @api */ #define OSAL_US2I(usecs) \ - ((sysinterval_t)((((((uint32_t)(usecs)) * \ - ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000000UL) + 1UL)) + ((sysinterval_t)((((time_conv_t)(usecs) * \ + (time_conv_t)OSAL_ST_FREQUENCY) + \ + (time_conv_t)999999) / (time_conv_t)1000000)) + +/** + * @brief Time interval to seconds. + * @details Converts from system ticks number to seconds. + * @note The result is rounded up to the next second boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of seconds. + * + * @api + */ +#define OSAL_I2S(interval) \ + (time_secs_t)(((time_conv_t)(interval) + \ + (time_conv_t)OSAL_ST_FREQUENCY - \ + (time_conv_t)1) / (time_conv_t)OSAL_ST_FREQUENCY) + +/** + * @brief Time interval to milliseconds. + * @details Converts from system ticks number to milliseconds. + * @note The result is rounded up to the next millisecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of milliseconds. + * + * @api + */ +#define OSAL_I2MS(interval) \ + (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \ + (time_conv_t)OSAL_ST_FREQUENCY - (time_conv_t)1) / \ + (time_conv_t)OSAL_ST_FREQUENCY) + +/** + * @brief Time interval to microseconds. + * @details Converts from system ticks number to microseconds. + * @note The result is rounded up to the next microsecond boundary. + * @note Use of this macro for large values is not secure because + * integer overflows, make sure your value can be correctly + * converted. + * + * @param[in] interval interval in ticks + * @return The number of microseconds. + * + * @api + */ +#define OSAL_I2US(interval) \ + (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \ + (time_conv_t)OSAL_ST_FREQUENCY - (time_conv_t)1) / \ + (time_conv_t)OSAL_ST_FREQUENCY) /** @} */ /** diff --git a/os/rt/include/chtime.h b/os/rt/include/chtime.h index 79fab6a85..c6c1de8cc 100644 --- a/os/rt/include/chtime.h +++ b/os/rt/include/chtime.h @@ -266,9 +266,9 @@ typedef uint32_t time_conv_t; * @api */ #define TIME_I2US(interval) \ - (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \ - (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \ - (time_conv_t)CH_CFG_ST_FREQUENCY) + (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \ + (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \ + (time_conv_t)CH_CFG_ST_FREQUENCY) /** @} */ /*===========================================================================*/ diff --git a/readme.txt b/readme.txt index 8b3533adf..7383dec44 100644 --- a/readme.txt +++ b/readme.txt @@ -74,6 +74,7 @@ ***************************************************************************** *** Next *** +- NEW: More time conversion macros added to HAL OSAL. - NEW: Updated debug tools to be independent from the toolchain position: they now rely on the environment variable CHIBISTUDIO. - NEW: Mail Queues test implementation in CMSIS RTOS wrapper.