511 lines
15 KiB
C
Executable File
511 lines
15 KiB
C
Executable File
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
|
|
#ifndef IOT_UTILS_API_H
|
|
#define IOT_UTILS_API_H
|
|
|
|
/* os shim includes */
|
|
#include "os_types_api.h"
|
|
#include "os_mem_api.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \defgroup MISC_APIs MISC APIs
|
|
* @brief MISC APIs
|
|
*
|
|
*
|
|
*/
|
|
|
|
/** @addtogroup MISC_APIs
|
|
* @{
|
|
*
|
|
*/
|
|
|
|
#if !defined(max)
|
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
#if !defined(min)
|
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
#define IOT_ABS(x) ((x) > 0 ? (x) : -(x))
|
|
|
|
#define IOT_ARRAY_CNT(a) (sizeof(a) / sizeof(a[0]))
|
|
|
|
/* used for ceil if the numerator and denumerator is int */
|
|
#define iot_ceil(numerator, denumerator) \
|
|
(((numerator) + ((denumerator) - 1)) / (denumerator))
|
|
|
|
/**
|
|
* @brief BUILD_BUG_ON() - raise build error if the condition is not true.
|
|
* this macro is useful for checks in compilation time.
|
|
* @param condition: verify condition
|
|
*/
|
|
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - (2 * (!(condition)))]))
|
|
|
|
/**
|
|
* @brief container_of() - cast a member of a structure to the containing
|
|
* structure.
|
|
* @param ptr: the pointer to the member
|
|
* @param type: the type of the container struct this is embedded in
|
|
* @param member: the name of the member within the struct
|
|
*/
|
|
#define container_of(ptr, type, member) ( \
|
|
(type *)((uint8_t *)ptr - ((size_t) &((type *)0)->member)))
|
|
|
|
/* mac address length */
|
|
#define IOT_MAC_ADDR_LEN 6
|
|
|
|
/* ip4 address length */
|
|
#define IOT_IP4_ADDR_LEN 4
|
|
|
|
|
|
/* meter address length */
|
|
#define IOT_METER_ADDR_LEN 12
|
|
|
|
/* maximum value of BCD codes */
|
|
#define IOT_MAC_BCD_MAX 0x99
|
|
|
|
/* broadcast mac address for downlink proxy broadcast */
|
|
extern const uint8_t bcast_mac[];
|
|
|
|
/**
|
|
* @brief iot_mac_addr_uint8_array_to_long_int() - transform mac address
|
|
* uint8_t[6] to a long long int.
|
|
* @param mac_addr: the uint8_t[6] mac address
|
|
*/
|
|
#define iot_mac_addr_uint8_array_to_long_int(mac_addr) \
|
|
((uint64_t)mac_addr[0] << (40) | \
|
|
(uint64_t)mac_addr[1] << (32) | \
|
|
(uint64_t)mac_addr[2] << (24) | \
|
|
(uint64_t)mac_addr[3] << (16) | \
|
|
(uint64_t)mac_addr[4] << (8) | \
|
|
(uint64_t)mac_addr[5] << (0))
|
|
|
|
/**
|
|
* @brief iot_uint64_to_mac_addr() - transform a long long int to mac address
|
|
* uint8_t[6].
|
|
* @param int64val: the long int mac address
|
|
* @param mac_addr: the uint8_t[6] mac address
|
|
*/
|
|
#define iot_uint64_to_mac_addr(int64val, mac_addr) \
|
|
{ \
|
|
mac_addr[0] = (((uint64_t)int64val) >> 40) & 0xFF; \
|
|
mac_addr[1] = (((uint64_t)int64val) >> 32) & 0xFF; \
|
|
mac_addr[2] = (((uint64_t)int64val) >> 24) & 0xFF; \
|
|
mac_addr[3] = (((uint64_t)int64val) >> 16) & 0xFF; \
|
|
mac_addr[4] = (((uint64_t)int64val) >> 8) & 0xFF; \
|
|
mac_addr[5] = (((uint64_t)int64val) >> 0) & 0xFF; \
|
|
}
|
|
|
|
/* get lower 32bit value of an unsigned long long */
|
|
#define iot_uint64_lower32(int64val) ((uint32_t)((int64val) & 0xFFFFFFFF))
|
|
|
|
/* get higer 32bit value of an unsigned long long */
|
|
#define iot_uint64_higher32(int64val) ((uint32_t)((int64val) >> 32))
|
|
|
|
/**
|
|
* calculate memory size for an aligned buffer - returns the next highest
|
|
* multiple of alignment. alignment must be a multiple of 2.
|
|
* (e.g. IOT_MEM_ALIGN_SIZE(3, 4) and IOT_MEM_ALIGN_SIZE(4, 4) will both
|
|
* yield 4 for align == 4).
|
|
*/
|
|
#define IOT_MEM_ALIGN_SIZE(size, align) (((size) + align - 1U) & ~(align - 1U))
|
|
|
|
/** Calculate safe memory size for an aligned buffer when using an unaligned
|
|
* type as storage. This includes a safety-margin on (align - 1) at the
|
|
* start (e.g. if buffer is uint8_t[] and actual data will be uint32_t*)
|
|
* alignment must be a multiple of 2.
|
|
*/
|
|
#define IOT_MEM_ALIGN_BUFFER(size, align) (((size) + align - 1U))
|
|
|
|
/**
|
|
* align a memory pointer to the alignment defined by align so that
|
|
* (ADDR % ALIGN == 0). alignment must be a multiple of 2.
|
|
*/
|
|
#define IOT_MEM_ALIGN(addr, align) ((void *)(((uint32_t)(addr) + align - 1) \
|
|
& ~(uint32_t)(align - 1)))
|
|
|
|
#define iot_counter_inc(__cnt) \
|
|
do { \
|
|
(__cnt)++; \
|
|
if ((__cnt) == 0) \
|
|
(__cnt)--; \
|
|
} while (0)
|
|
|
|
/**
|
|
* @brief iot_mac_addr_cpy() - copy mac address
|
|
* @param dst: pointer to destination mac address
|
|
* @param src: pointer to source mac address
|
|
*/
|
|
static inline void iot_mac_addr_cpy(uint8_t* dst, uint8_t* src)
|
|
{
|
|
os_mem_cpy(dst, src, IOT_MAC_ADDR_LEN);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_meter_addr_cpy() - copy meter address
|
|
* @param dst: pointer to destination meter address
|
|
* @param src: pointer to source meter address
|
|
*/
|
|
static inline void iot_meter_addr_cpy(uint8_t* dst, uint8_t* src)
|
|
{
|
|
os_mem_cpy(dst, src, IOT_METER_ADDR_LEN);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_mac_addr_cmp() - mac address compare
|
|
* @param dst: pointer to first mac address to compare
|
|
* @param src: pointer to second mac address to compare
|
|
*
|
|
* @return 1 -- if mac address is the same
|
|
* @return 0 -- otherwise
|
|
*/
|
|
static inline uint8_t iot_mac_addr_cmp(const uint8_t* dst, const uint8_t* src)
|
|
{
|
|
return os_mem_cmp(dst, src, IOT_MAC_ADDR_LEN) == 0 ? 1 : 0;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_ip4_addr_cmp() - ip4 address compare
|
|
* @param dst: pointer to first ip4 address to compare
|
|
* @param src: pointer to second ip4 address to compare
|
|
*
|
|
* @return 1 -- if ip4 address is the same
|
|
* @return 0 -- otherwise
|
|
*/
|
|
static inline uint8_t iot_ip4_addr_cmp(const uint8_t* dst, const uint8_t* src)
|
|
{
|
|
return os_mem_cmp(dst, src, IOT_IP4_ADDR_LEN) == 0 ? 1 : 0;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_meter_addr_cmp() - meter address compare
|
|
* @param dst: pointer to first meter address to compare
|
|
* @param src: pointer to second meter address to compare
|
|
*
|
|
* @return 1 -- if meter address is the same
|
|
* @return 0 -- otherwise
|
|
*/
|
|
static inline uint8_t iot_meter_addr_cmp(const uint8_t* dst,
|
|
const uint8_t* src)
|
|
{
|
|
return os_mem_cmp(dst, src, IOT_METER_ADDR_LEN) == 0 ? 1 : 0;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_mac_is_bcast() - check if a mac is broadcast mac
|
|
* @param dst: the mac address to be checked
|
|
*
|
|
* @return 1 -- is broadcast mac
|
|
* @return 0 -- NOT a broadcast mac
|
|
*/
|
|
static inline uint8_t iot_mac_is_bcast(const uint8_t* dst)
|
|
{
|
|
return iot_mac_addr_cmp(dst, bcast_mac);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_set_bcast_mac() - set the dest mac as bcast addr
|
|
* @param mac: the dest mac to be filled with bcast addr
|
|
*/
|
|
static inline void iot_set_bcast_mac(uint8_t *mac)
|
|
{
|
|
iot_mac_addr_cpy(mac, (uint8_t*)bcast_mac);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_mac_addr_reverse() - reverse the mac address sequence
|
|
* @param addr: pointer to mac address to be reversed
|
|
*/
|
|
void iot_mac_addr_reverse(uint8_t* addr);
|
|
|
|
/**
|
|
* @brief iot_mac_addr_valid() - check if mac address is valid
|
|
* @param addr: pointer to mac address to be checked
|
|
*
|
|
* @return 1 -- if mac address is valid
|
|
* @return 0 -- otherwise
|
|
*/
|
|
uint8_t iot_mac_addr_valid(uint8_t* addr);
|
|
|
|
/**
|
|
* @brief iot_mac_addr_range_check() - check the addr in start address - end
|
|
address.
|
|
* @param addr: the address that need to check.
|
|
* @param start_addr: start address
|
|
* @param end_addr: end address
|
|
*
|
|
* @return 1 -- start_addr <= addr <= end_addr.
|
|
* @return 0 -- otherwise
|
|
*/
|
|
uint8_t iot_mac_addr_range_check(uint8_t *addr, uint8_t *start_addr,
|
|
uint8_t *end_addr);
|
|
|
|
/**
|
|
* @brief iot_meter_addr_valid() - check if meter address is valid
|
|
* @param addr: pointer to meter address to be checked
|
|
*
|
|
* @return 1 -- if meter address is valid
|
|
* @return 0 -- otherwise
|
|
*/
|
|
static inline uint8_t iot_meter_addr_valid(uint8_t* addr)
|
|
{
|
|
if (!addr) {
|
|
return 0;
|
|
}
|
|
|
|
return !!(addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5] ||
|
|
addr[6] || addr[7] || addr[8] || addr[9] || addr[10] || addr[11]);
|
|
}
|
|
|
|
/* iot_bytes_to_uint32() - parse byte stream to get a uint32_t value
|
|
* @data: data stream
|
|
* @flag_big_endian: flag of big endian. 1 mean data is big endian.
|
|
* return:
|
|
* the value from byte stream
|
|
*/
|
|
uint32_t iot_bytes_to_uint32(uint8_t* data, uint8_t flag_big_endian);
|
|
|
|
/* iot_bytes_to_uint16() - parse byte stream to get a uint32_t value
|
|
* @data: data stream
|
|
* @flag_big_endian: flag of big endian. 1 mean data is big endian.
|
|
* return:
|
|
* the value from byte stream
|
|
*/
|
|
static inline uint16_t iot_bytes_to_uint16(uint8_t* data,
|
|
uint8_t flag_big_endian)
|
|
{
|
|
uint16_t result = 0;
|
|
|
|
if (flag_big_endian) {
|
|
result = data[1] + (data[0] << 8);
|
|
} else {
|
|
result = data[0] + (data[1] << 8);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* iot_uint32_to_bytes - convert uint32_t value to byte stream
|
|
* @value: the uint32_t value to be converted to byte stream
|
|
* @data: pointer to the buffer containing the output byte stream
|
|
* @flag_big_endian: flag of big endian. 1 mean data is big endian.
|
|
*/
|
|
void iot_uint32_to_bytes(uint32_t value, uint8_t *data,
|
|
uint8_t flag_big_endian);
|
|
|
|
/* iot_uint16_to_bytes - convert uint32_t value to byte stream
|
|
* @value: the uint16_t value to be converted to byte stream
|
|
* @data: pointer to the buffer containing the output byte stream
|
|
* @flag_big_endian: flag of big endian. 1 mean data is big endian.
|
|
*/
|
|
void iot_uint16_to_bytes(uint16_t value, uint8_t *data,
|
|
uint8_t flag_big_endian);
|
|
|
|
/* iot_bcd_to_byte - convert BCD code to byte
|
|
* @value: the BCD value to be converted to byte
|
|
* @return: the byte value
|
|
*/
|
|
static inline uint8_t iot_bcd_to_byte(uint8_t value)
|
|
{
|
|
return (value >> 4) * 10 + (value & 0x0F);
|
|
}
|
|
|
|
/* iot_byte_to_bcd - convert byte to BCD code
|
|
* @value: the byte to be converted to BCD code
|
|
* @return: the BCD code
|
|
*/
|
|
static inline uint8_t iot_byte_to_bcd(uint8_t value)
|
|
{
|
|
return ((value / 10) << 4) + (value % 10);
|
|
}
|
|
|
|
/*
|
|
* @brief iot_float_ceil() - float ceil.
|
|
* @param f: - float value.
|
|
* @return uint32_t: - float ceil uint32_t
|
|
*/
|
|
static inline uint32_t iot_float_ceil(float f)
|
|
{
|
|
if (f - (uint32_t)(f) > 0) {
|
|
return (uint32_t)f + 1;
|
|
} else {
|
|
return (uint32_t)f;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief iot_float_round_int32() - float round to int32_t.
|
|
* @param f: float value.
|
|
* @return int32_t: float round to int32_t
|
|
*/
|
|
static inline int32_t iot_float_round_int32(float f)
|
|
{
|
|
if (f < 0)
|
|
return (int32_t)(f - 0.5);
|
|
else
|
|
return (int32_t)(f + 0.5);
|
|
}
|
|
|
|
/**
|
|
* @brief: iot_uint32_to_bcd - convert a uint32 number to bcd buffer
|
|
* @param value: the value to be converted
|
|
* @param bcd_len: bcd buffer len
|
|
* @param bcd: bcd buffer to receive the result
|
|
* @return: the actual valid len in bcd buffer
|
|
*/
|
|
uint8_t iot_uint32_to_bcd(uint32_t value, uint8_t bcd_len,
|
|
uint8_t *bcd);
|
|
|
|
/**
|
|
* @brief: iot_bcd_to_uint32 - convert bcd buffer to a uint32 number
|
|
* @param bcd: bcd buffer to be converted
|
|
* @param bcd_len: bcd buffer len, max length is 4 byte.
|
|
* @param flag_big:flag of bcd buffer edition. 1 mean big edition.
|
|
* @param value: the value to receive the result
|
|
* @return: the actual valid len in bcd buffer
|
|
*/
|
|
uint8_t iot_bcd_to_uint32(uint8_t *bcd, uint8_t bcd_len,
|
|
uint8_t flag_big, uint32_t *value);
|
|
|
|
/**
|
|
* @brief: iot_byte_reverse - convert a byte between MSB to LSB
|
|
* @param value: the byte to be converted
|
|
* @return: the byte after converted
|
|
*/
|
|
uint8_t iot_byte_reverse(uint8_t value);
|
|
|
|
/**
|
|
* @brief iot_bcd_data_check() - check if bcd data is valid
|
|
* @param data: pointer to bcd data to be checked
|
|
* @param len: length of bcd data
|
|
* @return 1 -- if bcd data is valid
|
|
* @return 0 -- otherwise
|
|
*/
|
|
uint8_t iot_bcd_data_check(uint8_t *data, uint8_t len);
|
|
|
|
/**
|
|
* @brief iot_bcd_check() - whether bytes are BCD code
|
|
* @param v: value to be checked
|
|
* @return 1 -- bytes is BCD code
|
|
* @return 0 -- otherwise
|
|
*/
|
|
uint8_t iot_bcd_check(uint8_t v);
|
|
|
|
/**
|
|
* @brief: iot_data_reverse - convert data sequence
|
|
* @param data: the data to be converted
|
|
* @param data: the data length. unit is 1 byte
|
|
*/
|
|
void iot_data_reverse(uint8_t *data, uint32_t len);
|
|
|
|
/**
|
|
* @brief iot_atoi() - alphanumeric to integer.
|
|
* @s: The string to be convert.
|
|
* @return: convert integer value.
|
|
*/
|
|
int iot_atoi(const char *s);
|
|
|
|
/**
|
|
* @brief iot_atoi_to_uint8() - alphanumeric to uint8 data.
|
|
* @param s: The string to be convert.
|
|
* @param value: convert uint8 value.
|
|
* @retval ERR_OK: handle success.
|
|
* @retval ERR_FAIL: handle false.
|
|
*/
|
|
uint8_t iot_atoi_to_uint8(const char *s, uint8_t *value);
|
|
|
|
/**
|
|
* @brief iot_atoi_to_uint16() - alphanumeric to uint16 data.
|
|
* @param s: The string to be convert.
|
|
* @param value: convert uint16 value.
|
|
* @retval ERR_OK: handle success.
|
|
* @retval ERR_FAIL: handle false.
|
|
*/
|
|
uint8_t iot_atoi_to_uint16(const char *s, uint16_t *value);
|
|
|
|
/**
|
|
* @brief iot_atoi_to_uint32() - alphanumeric to uint32 data.
|
|
* @param s: The string to be convert.
|
|
* @param value: convert uint32 value.
|
|
* @retval ERR_OK: handle success.
|
|
* @retval ERR_FAIL: handle false.
|
|
*/
|
|
uint8_t iot_atoi_to_uint32(const char *s, uint32_t *value);
|
|
|
|
/**
|
|
* @brief iot_calc_week() - calculate weekday
|
|
* @param year: year of the date, like 2008, 2019 ...
|
|
* @param mon : month of the date
|
|
* @param mday: day of the date
|
|
* @return : weekday from 0 to 6. 0 - sunday, 6 - saturday.
|
|
*/
|
|
uint8_t iot_calc_week(uint16_t year, uint8_t mon, uint8_t mday);
|
|
|
|
/*
|
|
* @brief iot_bubble_sort_int32() - bubble sort of the array.
|
|
* @param data: continuous data array
|
|
* @param cnt: array size
|
|
* @param increase: 1 means sort from small to large, 0 means sort from large
|
|
* small.
|
|
*/
|
|
void iot_bubble_sort_int32(int32_t *data, uint32_t cnt, uint8_t increase);
|
|
|
|
/*
|
|
* @brief iot_bubble_sort_int8() - bubble sort of the array.
|
|
* @param data: continuous data array
|
|
* @param cnt: array size
|
|
* @param increase: 1 means sort from small to large, 0 means sort from large
|
|
* small.
|
|
*/
|
|
void iot_bubble_sort_int8(int8_t *data, uint32_t cnt, uint8_t increase);
|
|
|
|
/*
|
|
* @brief iot_math_sqrt() - square root.
|
|
* @param data: value to be calculated
|
|
* @return: result of square root
|
|
*/
|
|
int32_t iot_math_sqrt(int64_t x);
|
|
|
|
/*
|
|
* @brief iot_ascii_to_byte() - ascii to byte.
|
|
* @param value: ascii code value
|
|
* @return: byte value
|
|
*/
|
|
uint8_t iot_ascii_to_byte(const char value);
|
|
|
|
/*
|
|
* @brief iot_byte_to_ascii() - byte to ascii.
|
|
* @param value: byte value
|
|
* @param flag_uppercase: 1 means byte to uppercase ascii code value,
|
|
* 0 means byte to lowercase ascii code value.
|
|
* @return: ascii code value
|
|
*/
|
|
uint8_t iot_byte_to_ascii(const uint8_t value, uint8_t flag_uppercase);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* IOT_UTILS_API_H */
|