This commit is contained in:
许晟昊 2025-04-29 16:29:06 +08:00
commit b05d224423
36 changed files with 8170 additions and 0 deletions

161
inc/aes.h Normal file
View File

@ -0,0 +1,161 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state.
*/
#ifndef AES_H
#define AES_H
#if 1
#define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
#endif
#if 1
#define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
#endif
#if 0
#define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
#endif
#if 0
#define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
#endif
#if 0
#define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
#endif
#if 0
#define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
#endif
#define N_ROW 4
#define N_COL 4
#define N_BLOCK (N_ROW * N_COL)
#define N_MAX_ROUNDS 14
typedef uint8_t return_type;
/* Warning: The key length for 256 bit keys overflows a byte
(see comment below)
*/
typedef uint8_t length_type;
typedef struct
{
uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
uint8_t rnd;
} aes_context;
/* The following calls are for a precomputed key schedule
NOTE: If the length_type used for the key length is an
unsigned 8-bit character, a key length of 256 bits must
be entered as a length in bytes (valid inputs are hence
128, 192, 16, 24 and 32).
*/
#if defined(AES_ENC_PREKEYED) || defined(AES_DEC_PREKEYED)
return_type aes_set_key(const uint8_t key[],
length_type keylen,
aes_context ctx[1]);
#endif
#if defined(AES_ENC_PREKEYED)
return_type aes_encrypt(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1]);
return_type aes_cbc_encrypt(const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1]);
#endif
#if defined(AES_DEC_PREKEYED)
return_type aes_decrypt(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1]);
return_type aes_cbc_decrypt(const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1]);
#endif
/* The following calls are for 'on the fly' keying. In this case the
encryption and decryption keys are different.
The encryption subroutines take a key in an array of bytes in
key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
192, and 256 bits respectively. They then encrypts the input
data, in[] with this key and put the reult in the output array
out[]. In addition, the second key array, o_key[L], is used
to output the key that is needed by the decryption subroutine
to reverse the encryption operation. The two key arrays can
be the same array but in this case the original key will be
overwritten.
In the same way, the decryption subroutines output keys that
can be used to reverse their effect when used for encryption.
Only 128 and 256 bit keys are supported in these 'on the fly'
modes.
*/
#if defined(AES_ENC_128_OTFK)
void aes_encrypt_128(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK]);
#endif
#if defined(AES_DEC_128_OTFK)
void aes_decrypt_128(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK]);
#endif
#if defined(AES_ENC_256_OTFK)
void aes_encrypt_256(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK]);
#endif
#if defined(AES_DEC_256_OTFK)
void aes_decrypt_256(const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK]);
#endif
#endif

49
inc/clist.h Normal file
View File

@ -0,0 +1,49 @@
/**
* @file clist.h
* @author xxx
* @date 2023-08-08 23:18:15
* @brief 使 lib\examples\simple_clist.c
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __CLIST_H
#define __CLIST_H
#include "lib.h"
typedef void *cnode;
/// 链表中一个节点的结构体
typedef struct CLIST_NODE
{
cnode data; /// 值
struct CLIST_NODE *next; /// 指向下一个结点
} clist_node_t;
void clist_init(clist_node_t **ppFirst); ///< 初始化 ,构造一条空的链表
void clist_print(clist_node_t *First); ///< 打印链表
uint32_t clist_node_count(clist_node_t *First); ///< 获取链表节点数
void clist_push_back(clist_node_t **ppFirst, cnode data); ///< 尾部插入
void clist_push_front(clist_node_t **ppFirst, cnode data); ///< 头部插入
void clist_pop_back(clist_node_t **ppFirst); ///< 尾部删除
void clist_pop_front(clist_node_t **ppFirst); ///< 头部删除
void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data); ///< 给定结点插入,插入到结点前
int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data); ///< 按位置插入
void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos); ///< 给定结点删除
void clist_remove(clist_node_t **ppFirst, cnode data); ///< 按值删除,只删遇到的第一个
void clist_remove_all(clist_node_t **ppFirst, cnode data); ///< 按值删除,删除所有的
void clist_destroy(clist_node_t **ppFirst); ///< 销毁 ,需要销毁每一个节点
clist_node_t *clist_find(clist_node_t *pFirst, cnode data); ///< 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL
#endif //__CLIST_H

63
inc/cmac.h Normal file
View File

@ -0,0 +1,63 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
#ifndef _CMAC_H_
#define _CMAC_H_
#include "aes.h"
#define AES_CMAC_KEY_LENGTH 16
#define AES_CMAC_DIGEST_LENGTH 16
typedef struct _AES_CMAC_CTX
{
aes_context rijndael;
uint8_t X[16];
uint8_t M_last[16];
uint32_t M_n;
} AES_CMAC_CTX;
// #include <sys/cdefs.h>
//__BEGIN_DECLS
void AES_CMAC_Init(AES_CMAC_CTX *ctx);
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]);
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len);
// __attribute__((__bounded__(__string__,2,3)));
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx);
// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
//__END_DECLS
#endif /* _CMAC_H_ */

49
inc/cmd.h Normal file
View File

@ -0,0 +1,49 @@
/**
* @file cmd.h
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef _CMD_H_
#define _CMD_H_
#define CMD_HASH 0xb433e5c6
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
#define SECTION(x) __attribute__((section(x)))
#define CMD_USED __attribute__((used))
#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */
#define SECTION(x) @x
#define CMD_USED __root
#else
#error "not supported tool chain..."
#endif
typedef void (*cmd_handler)(void);
typedef struct cmd
{
const char *cmd;
const char *cmd_mess;
unsigned int hash;
cmd_handler handler;
} cmd_t;
/// 注册命令
#define REGISTER_CMD(cmd, handler, desc) \
const char _register_##cmd##_cmd[] = #cmd; \
const char _register_##cmd##_desc[] = #desc; \
CMD_USED cmd_t _register_##cmd SECTION("CMDS") = \
{ \
_register_##cmd##_cmd, \
_register_##cmd##_desc, \
(unsigned int)CMD_HASH, \
(cmd_handler)&handler};
void cmd_init(void); ///< 初始化命令
void cmd_parsing(char *str); ///< 命令解析
#endif

79
inc/data_analysis.h Normal file
View File

@ -0,0 +1,79 @@
/**
* @file data_analysis.h
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_
#define COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_
#include "data_type_def.h"
typedef enum
{
DATA_1,
DATA_2,
DATA_MAX,
} data_analysis_id_e; // 处理数据模块的个数,请根据实际情况修改
#define DATA_NUM (DATA_MAX)
#define DATA_BUF_RECV_SQQ_LEN 1200u
#define DATA_BUF_SEND_SQQ_LEN 0u
#define DATA_SD_LEN_MAX 2
#define DATA_LD_LEN_MAX 2
#define DATA_ED_LEN_MAX 1
typedef struct _data_reg_t_
{
struct
{
uint8_t len;
uint8_t pos;
uint8_t data[DATA_SD_LEN_MAX];
BOOL valid; // 是否有效
} sd; // start delimiter
struct
{
uint8_t len;
uint8_t pos; // 偏移量在wait_end_state中根据帧长去掉固定长度来判断是否是结束符
uint8_t little_endian;
BOOL valid; // 是否有效
} ld; // length describe
struct
{
uint16_t len_max;
uint16_t len_min;
} argu;
struct
{
uint8_t len;
uint8_t data[DATA_ED_LEN_MAX];
BOOL valid;
} ed;
BOOL echo_en;
void (*func_ptr)(void);
} data_reg_t;
typedef void (*data_interupt_cb_t)(uint8_t id, uint8_t ch); ///< 中断回调函数,数据从这里写入
extern uint8_t data_read(uint8_t id, void *buffer, uint16_t len); ///< 读取数据
extern void data_write(uint8_t id, uint8_t *const string, uint16_t len); ///< TODO 写入数据
extern void lock_data(uint8_t data_id); ///< 锁定数据,防止中断写入数据
extern void unlock_data(uint8_t data_id); ///< 解锁数据
extern data_interupt_cb_t data_fsm_init(uint8_t data_id); ///< 初始化数据状态机
extern BOOL data_reg(uint8_t id, data_reg_t reg); ///< 注册数据
extern void data_unreg(uint8_t id); ///< 注销数据
#endif /* COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_ */

332
inc/data_type_def.h Normal file
View File

@ -0,0 +1,332 @@
/***
* @Author:
* @Date: 2023-03-29 13:16:28
* @LastEditors: xxx
* @LastEditTime: 2023-03-30 00:34:11
* @Description:
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __DATA_TYPE_DEF_H_
#define __DATA_TYPE_DEF_H_
#include <stdint.h>
#ifndef PI
#define PI (3.14159265358979323846f)
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef OK
typedef enum
{
FAIL = 0,
OK = !FAIL,
} state_e;
#endif
#ifndef __IO
#define __IO volatile
#endif
typedef unsigned char BOOL; /* boolean data */
typedef unsigned char bool_t; /* boolean data */
#if !defined(__stdint_h) && !defined(_GCC_WRAP_STDINT_H)
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed long int int32_t;
typedef long long int64_t;
#endif
typedef float float32;
typedef double float64;
#ifndef float32_t
typedef float float32_t;
#endif
#ifndef float64_t
typedef double float64_t;
#endif
#pragma pack(1)
typedef struct
{
uint8_t bs[3];
} uint24_t;
typedef struct
{
uint8_t bs[5];
} uint40_t;
typedef union
{
float32 f;
int32_t c;
} float32_u;
#pragma pack()
typedef enum
{
DATA_TYPE_INT8 = 0, // 8-bit signed integer
DATA_TYPE_UINT8, // 8-bit unsigned integer
DATA_TYPE_INT16, // 16-bit signed integer
DATA_TYPE_UINT16, // 16-bit unsigned integer
DATA_TYPE_INT32, // 32-bit signed integer
DATA_TYPE_UINT32, // 32-bit unsigned integer
DATA_TYPE_INT64, // 64-bit signed integer
DATA_TYPE_UINT64, // 64-bit unsigned integer
DATA_TYPE_FLOAT, // 32-bit floating point number
DATA_TYPE_DOUBLE, // 64-bit floating point number
DATA_TYPE_STRING, // string
DATA_TYPE_ARRAY, // array
DATA_TYPE_STRUCT, // structure
DATA_TYPE_UNION, // union
DATA_TYPE_ENUM, // enumeration
DATA_TYPE_POINTER, // pointer
DATA_TYPE_FUNCTION, // function
DATA_TYPE_VOID, // void
DATA_TYPE_MAX,
} data_type_e;
typedef uint16_t nwk_id_t;
/**
* STANDARD BITS
*/
#ifndef BIT0
#define BIT0 (0x01u)
#define BIT1 (0x02u)
#define BIT2 (0x04u)
#define BIT3 (0x08u)
#define BIT4 (0x10u)
#define BIT5 (0x20u)
#define BIT6 (0x40u)
#define BIT7 (0x80u)
#define BIT8 (0x0100u)
#define BIT9 (0x0200u)
#define BIT10 (0x0400u)
#define BIT11 (0x0800u)
#define BIT12 (0x1000u)
#define BIT13 (0x2000u)
#define BIT14 (0x4000u)
#define BIT15 (0x8000u)
#define BIT16 (0x00010000u)
#define BIT17 (0x00020000u)
#define BIT18 (0x00040000u)
#define BIT19 (0x00080000u)
#define BIT20 (0x00100000u)
#define BIT21 (0x00200000u)
#define BIT22 (0x00400000u)
#define BIT23 (0x00800000u)
#define BIT24 (0x01000000u)
#define BIT25 (0x02000000u)
#define BIT26 (0x04000000u)
#define BIT27 (0x08000000u)
#define BIT28 (0x10000000u)
#define BIT29 (0x20000000u)
#define BIT30 (0x40000000u)
#define BIT31 (0x80000000u)
#define PACKED2_LEN 2U
#define PACKED3_LEN 3U
#define PACKED4_LEN 4U
#define PACKED6_LEN 6U
#define PACKED8_LEN 8U
#define PACKED10_LEN 10U
#define PACKED12_LEN 12U
#define PACKED16_LEN 16U
#define PACKED20_LEN 20U
#define PACKED21_LEN 21U
#define PACKED24_LEN 24U
#define PACKED25_LEN 25U
#define PACKED26_LEN 26U
#define PACKED30_LEN 30U
#define PACKED32_LEN 32U
#define PACKED40_LEN 40U
#define PACKED64_LEN 64U
#define PACKED128_LEN 128U
#define BIT_SET(x, b) x |= b // 置位
#define BIT_CLR(x, b) x &= ~b // 清零
#define BIT_GET(x, y) ((x) >> (y) & 1) // 获取某一位
#define BIT_REVERSE(x, y) (x) ^= (1 << y) // 某位取反
#define BIT_IS_SET(x, b) ((x) & (b)) // 判断某一位是否为1
#define BIT_IS_CLR(x, b) (!((x) & (b))) // 判断某一位是否为0
#endif
#ifndef BF
/**
* @brief
* @return {*}
* @note
*> uint8_t num = 0x12; 00010010 <p>
*> uint8_t bit = 2; 20 <p>
*> uint8_t width = 1; 1 <p>
*> uint8_t result = BF(num, bit, width); 1 <p>
*/
#define BF(x, b, s) (((x) & (b)) >> (s))
#endif
#ifndef MIN
/**
* @brief
* @return {*}
* @note
*> int num1 = 10; <p>
*> int num2 = 20; <p>
*> int result = MIN(num1, num2); // 结果为10 <p>
*/
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
#ifndef MAX
/**
* @brief
* @return {*}
* @note
*> int num1 = 10; <p>
*> int num2 = 20; <p>
*> int result = MAX(num1, num2); // 结果为20 <p>
*/
#define MAX(n, m) (((n) < (m)) ? (m) : (n))
#endif
#ifndef ABS
/**
* @brief
* @return {*}
* @note
*> int num = -10;
*> int result = ABS(num); // 结果为10
*/
#define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
#ifndef RANGE
#define RANGE(x, a, b) (MIN(MAX(x, a), b))
#endif
/**
* @brief Macro to check if a value is between a minimum and maximum value (inclusive).
* @param x The value to check.
* @param min The minimum value.
* @param max The maximum value.
* @return Returns 1 if the value is between the minimum and maximum values (inclusive), 0 otherwise.
*/
#define IS_BETWEEN(x, min, max) ((x) >= min && (x) <= max)
#define ARRAY_LEN(arr) (sizeof(arr)) / (sizeof(arr[0]))
#define HI_UINT16(a) (((uint16_t)(a) >> 8) & 0xFF)
#define LO_UINT16(a) ((uint16_t)(a) & 0xFF)
#define HI_1_UINT32(a) (((uint32_t)(a) >> 24) & 0xFF)
#define HI_2_UINT32(a) (((uint32_t)(a) >> 16) & 0xFF)
#define HI_3_UINT32(a) (((uint32_t)(a) >> 8) & 0xFF)
#define HI_4_UINT32(a) ((uint32_t)(a) & 0xFF)
#define LO_1_UINT8(a) (uint8_t)((a) & 0xFF)
#define LO_2_UINT8(a) (uint8_t)(((a) & 0xFF00) >> 8)
#define LO_3_UINT8(a) (uint8_t)(((a) & 0xFF0000) >> 16)
#define LO_4_UINT8(a) (uint8_t)(((a) & 0xFF000000) >> 24)
// uint32小端转大端
#define S2B_UINT32(a) \
(((uint32_t)(a) & 0xFF000000) >> 24) + (((uint32_t)(a) & 0x00FF0000) >> 8) + (((uint32_t)(a) & 0x0000FF00) << 8) + (((uint32_t)(a) & 0x000000FF) << 24)
// uint32大端转小端
#define B2S_UINT32(a) S2B_UINT32(a)
// uint16小端转大端
#define S2B_UINT16(a) ((((uint16_t)(a) & 0xFF00) >> 8) + (((uint16_t)(a) & 0x00FF) << 8))
// uint16大端转小端
#define B2S_UINT16(a) S2B_UINT16(a)
#define BUILD_UINT16(loByte, hiByte) \
((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
// float32小端转大端
static inline float32 S2B_FLOAT32(float fv)
{
float32_u _f;
_f.f = fv;
_f.c = S2B_UINT32(_f.c);
return _f.f;
}
// float32大端转小端
#define B2S_FLOAT32(a) S2B_FLOAT32(a)
// 反序数组
#define REVERSE_ARRAY(arr, len) \
do \
{ \
uint8_t _tmp; \
uint16_t _i; \
for (_i = 0; _i < len / 2; _i++) \
{ \
_tmp = arr[_i]; \
arr[_i] = arr[len - _i - 1]; \
arr[len - _i - 1] = _tmp; \
} \
} while (0);
// 比较2个数组是否相等
#define IsEqual(arr1, arr2, n) ({ \
int _equal = 1; \
for (int _i = 0; _i < n; _i++) \
{ \
if (arr1[_i] != arr2[_i]) \
{ \
_equal = 0; \
break; \
} \
} \
_equal; \
})
// 数组中的ASSCII 小写字母改成大写
#define ASCII_TO_UPPER(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 32 : (c))
// ASSIC码转换为数字
#define ASCII_TO_NUM(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : (c) - 'A' + 10)
// 数字转换为ASSIC码
#define NUM_TO_ASCII(x) ((x) < 10 ? (x) + '0' : (x) - 10 + 'A')
#define FLOAT_TO_UINT16(x) (x * 8192 / 100 + 2048) ///> 浮点压缩uint16_t
#define UINT16_TO_FLOAT(x) (100 * (x - 2048) / 8192) ///> uint16转浮点
// 实现了类似标准库中 floorf 函数的向下取整功能,适用于浮点数向下取整。
static inline float32_t custom_floorf(float32_t x)
{
int32_t i = (int32_t)x;
float32_t result = (float32_t)i;
// 对于负数且 x 不等于截断后的整数时,需要再减 1
result -= (x < 0.0f) && (result != x);
return result;
}
// 实现了类似标准库中 ceilf 函数的向上取整功能,适用于浮点数向上取整。
static inline float32_t custom_ceilf(float32_t x)
{
int32_t i = (int32_t)x;
float32_t result = (float32_t)i;
// 对于正数且 x 不等于截断后的整数时,需要再加 1
result += (x > 0.0f) && (result != x);
return result;
}
#endif /* __DATA_TYPE_DEF_H_ */

21
inc/debug.h Normal file
View File

@ -0,0 +1,21 @@
/***
* @Author:
* @Date: 2023-04-04 08:13:11
* @LastEditors: xxx
* @LastEditTime: 2023-04-04 13:21:46
* @Description:
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#include "lib.h"
/*形参*/
#define _DBG_LINE_ , uint16_t line
/*实参*/
#define __DBG_LINE , __LINE__
extern BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_);
#endif //__DEBUG_H

53
inc/filter.h Normal file
View File

@ -0,0 +1,53 @@
/**
* @file filter.h
* @author xxx
* @date 2023-08-08 22:59:46
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __FILTER_H__
#define __FILTER_H__
#include "lib.h"
typedef struct
{
float32 x; // 卡尔曼滤波器的估计值
float32 a; // 状态转移矩阵1表示没有动态变化
float32 h; // 观测矩阵1表示直接观测
float32 q; // 过程噪声协方差
float32 r; // 观测噪声协方差
float32 p; // 估计误差协方差
float32 gain; // 卡尔曼增益
float32 change_max; // 允许的最大变化量,用于判断观测值是否异常
} kalman_t; // 卡尔曼滤波器结构
typedef struct
{
BOOL fisrt_flag; // 第一次标志位
float32 alpha; // 滤波系数 0~1
float32 last_value; // 上次滤波结果
} lpf_t; // 一阶低通滤波器
typedef struct
{
uint16_t size; // 滑动窗口大小
float32 *window; // 滑动窗口
volatile float32 sum; // 滑动窗口和
volatile float32 out; // 滤波结果
uint16_t index; // 滑动窗口索引
} lpf_window_t; // 滑动窗口滤波器
void kalman_init(kalman_t *cfg, float32 change_max);
float32 kalman_update(kalman_t *cfg, float32 input);
void lpf_init(lpf_t *cfg);
float32 lpf_update(lpf_t *cfg, float32 input);
void lpf_reset(lpf_t *cfg);
void lpf_window_init(lpf_window_t *cfg, uint16_t size);
void lpf_window_dinit(lpf_window_t *cfg);
float32 lpf_window_update(lpf_window_t *cfg, float32 input);
void lpf_window_reset(lpf_window_t *cfg);
#endif // __FILTER_H__

307
inc/fsm.h Normal file
View File

@ -0,0 +1,307 @@
#ifndef __FSM_H__
#define __FSM_H__
#include <stdint.h>
/* ----------------------- Defines ------------------------------------------*/
// 用于快速识别出 STATE与STEP
#define FSM_STATE(name) state_##name
#define FSM_FUNCT(name) funct_##name
// 数据类型定义区
typedef signed char state;
typedef long long step_ret;
typedef void *AS_STEP_RETVAL;
/*!
* @brief
*
*
* @param[in] void*
*
* @return
*/
typedef void *(*Procedure)(void *);
typedef struct
{
state ds; // 默认状态
state cs; // 当前状态
state ns; // 下个状态
} SM_STATE;
// 状态机 属性 定义
typedef struct
{
// 状态管理
SM_STATE st;
// 状态机跳转表
Procedure *procedures;
// 状态机数据区域
void *data;
// 错误处理(用于存放 状态 执行 的结果)
step_ret ret_ptr; // 状态 执行结果
void *err_ptr;
state err_flag;
} FSM;
/* ----------------------- Start function declaration -----------------------------*/
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] err_var
*
* @return /
*/
static inline void set_err_var(FSM *fsm, void *err_var)
{
if (!fsm)
return;
fsm->err_ptr = err_var;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return /
*/
static inline void *get_err_var(FSM *fsm)
{
return fsm->err_ptr;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return /
*/
static inline state is_fsm_error(FSM *fsm)
{
return fsm->err_flag;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return /
*/
static inline state set_fsm_error_flag(FSM *fsm)
{
if (!fsm)
return -1;
fsm->err_flag = 1;
return 0;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return /
*/
static inline state clr_fsm_error_flag(FSM *fsm)
{
if (!fsm)
return -1;
fsm->err_flag = 0;
return 0;
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] procedures
*
*/
static inline void set_procedures(FSM *fsm, Procedure *procedures)
{
if (fsm)
{
fsm->procedures = procedures;
fsm->st.cs = -1; // 执行run之前当前状态是未定的
}
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] data
*
*/
static inline void set_data_entry(FSM *fsm, void *data)
{
if (fsm)
fsm->data = data;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return
*
*/
static inline void *get_data_entry(FSM *fsm)
{
return fsm->data;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return
* -1 :
*/
static inline state run_state_machine_once(FSM *fsm)
{
if (!fsm)
return -1;
// 切换到新状态
fsm->st.cs = fsm->st.ns;
// 跳转到下一个状态(状态 执行 结果 保存在 ret_ptr 中
fsm->ret_ptr = (step_ret)fsm->procedures[fsm->st.cs](fsm);
return fsm->st.cs;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return /
*/
static inline step_ret *get_step_retval(FSM *fsm)
{
return &fsm->ret_ptr;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return
*/
static inline state get_curr_state(FSM *fsm)
{
return fsm->st.cs;
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] st
*
*/
static inline void set_default_state(FSM *fsm, state st)
{
if (!fsm)
return;
fsm->st.ds = st;
fsm->st.ns = st;
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] st
*
*/
static inline void set_next_state(FSM *fsm, state st)
{
if (fsm)
fsm->st.ns = st;
}
/*!
* @brief
*
* @param[in] fsm
*
* @return
*/
static inline state get_next_state(FSM *fsm)
{
return fsm->st.ns;
}
/*!
* @brief
*
* @param[in] fsm
*
*/
static inline void init_state_machine(FSM *p)
{
set_next_state(p, p->st.ds);
p->st.cs = -1; // 执行run之前当前状态是未定的
}
/*!
* @brief
*
* @param[in] fsm
*
*/
static inline void reset_state_machine(FSM *p)
{
if (!p)
return;
clr_fsm_error_flag(p);
init_state_machine(p);
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] st
*
* @return /
*/
static inline state is_curr_state(FSM *fsm, state st)
{
return fsm->st.cs == st;
}
/*!
* @brief
*
* @param[in] fsm
*
* @param[in] st
*
* @return /
*/
static inline state is_next_state(FSM *fsm, state st)
{
return fsm->st.ns == st;
}
#endif // __FSM_H__

136
inc/lib.h Normal file
View File

@ -0,0 +1,136 @@
/***
* @Author:
* @Date: 2023-04-04 08:13:11
* @LastEditors: xxx
* @LastEditTime: 2023-04-04 10:13:21
* @Description:
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __LIB_H
#define __LIB_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "data_type_def.h"
#include "malloc.h"
#include "data_analysis.h"
#include "osel_arch.h"
#include "debug.h"
#include "sqqueue.h"
#include "clist.h"
#define INTERNAL_EXTERN extern
#ifndef STM32
#include "log.h"
#else
#define LOG_PRINT(fmt, ...) \
do \
{ \
} while (0);
#define LOG_ERR(fmt, ...) \
do \
{ \
} while (0);
#define LOG_HEX(data, len) \
do \
{ \
} while (0);
#endif
#define EXIT(x) \
do \
{ \
DBG_ASSERT(FALSE, __DBG_LINE); \
} while (0);
////< 时间结构
typedef union
{
uint8_t data[6];
struct
{
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} date;
} date_time_t;
typedef struct
{
uint16_t year;
uint8_t month;
uint8_t day;
} rtc_date_t;
typedef struct
{
uint8_t hour;
uint8_t minute;
uint8_t second;
} rtc_time_t;
typedef struct
{
float32 x;
float32 y;
} point_t;
typedef struct
{
float32 a;
float32 b;
} linear_func_param_t;
#define S_CURVE_POINTS 70
typedef struct
{
float32 start;
float32 end;
float32 current;
float32 t[S_CURVE_POINTS];
uint16_t index;
} s_curve_generator_t;
extern void assic_to_str(uint8_t *assic, uint8_t len, uint8_t *str); // ASCII码转字符串
extern void get_cpu_id(uint8_t *id); // 获取CPU ID
extern void get_cpu_id_32(uint32_t *id); // 获取CPU ID
extern uint32_t cpu_encrypt(void); // CPU加密
extern BOOL cpu_judge_encrypt(uint32_t cupid_encrypt); // CPU判断加密
extern void version_split(uint8_t *version, uint8_t *hi, uint8_t *lo); // 版本号1.0拆解成1和0
extern void reverse(uint8_t *buf, uint16_t len); // 反序数组
extern BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val); // 判断val是否在数组arr中
extern BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value); // 判断数组中的值是否都相等
extern uint16_t crc16_compute(const uint8_t *const data, uint16_t length); // CRC16校验
extern uint32_t crc32_compute(const uint8_t *const data, uint16_t length); // CRC32校验
extern uint64_t crc64_compute(const uint8_t *const data, const uint16_t length); // CRC64校验
extern uint8_t xor_compute(const uint8_t *const data, uint16_t length); // 异或校验
extern uint8_t get_bit_num(uint8_t bit); // 获取bit位的值
extern BOOL is_bit_set(int x, int k); // 判断x的第k位是否为1
extern uint8_t is_leap_year(uint16_t year); // 检查是否是闰年
extern BOOL is_valid_date(uint8_t year, uint8_t month, uint8_t day); // 检查日期是否有效
extern BOOL is_valid_time(uint8_t hour, uint8_t minute, uint8_t second); // 检查时间是否有效
extern BOOL is_valid_datetime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 检查日期和时间是否有效
extern uint32_t days_since_1970(uint16_t year, uint8_t month, uint8_t day); // 计算从1970年1月1日到给定年月日的天数
extern uint32_t date_to_seconds(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 将日期转换为秒数
extern void seconds_to_date(uint32_t total_seconds, rtc_date_t *date, rtc_time_t *time); // 将秒数转换为日期
extern uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几天
extern uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几周
extern uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day); // 获取今天星期几
extern uint8_t hex_format_dec(uint8_t hex); // 十六进制转十进制
extern uint8_t dec_format_hex(uint8_t dec); // 十进制转十六进制
extern void quicksort(uint16_t arr[], int low, int high); // 快速排序
extern void insertion_sort(uint16_t arr[], uint16_t n); // 插入排序
extern uint32_t time2stamp(const rtc_date_t *const date, const rtc_time_t *const time); // 日期时间转时间戳
extern void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time); // 时间戳转北京时间
extern void convert_seconds(uint32_t total_seconds, char *date); // 秒数转换成时分秒
extern void add_commas(uint32_t num, char *result); // 数字添加逗号
#endif //__LIB_H

45
inc/log.h Normal file
View File

@ -0,0 +1,45 @@
/***
* @Author:
* @Date: 2023-03-20 19:27:47
* @LastEditors: xxx
* @LastEditTime: 2023-03-30 00:34:41
* @Description:PC端调试使用
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __LOG_H_
#define __LOG_H_
#include <string.h>
#include <stdio.h>
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__)
/*调试日志宏定义*/
#define LOG_PRINT(fmt, ...) \
do \
{ \
printf("[DEBUG:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0);
/*错误日志打印(在日志打印模块还未启动时使用)*/
#define LOG_ERR(fmt, ...) \
do \
{ \
printf("[ERROR:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0);
// 打印十六进制字符串
#define LOG_HEX(data, len) \
do \
{ \
printf("[DEBUG:%s][%s:%d] ", __FILENAME__, __FUNCTION__, __LINE__); \
for (int i = 0; i < len; i++) \
{ \
printf("%02x ", data[i]); \
} \
printf("\n"); \
} while (0);
#endif //__LOG_H_

160
inc/lwrb.h Normal file
View File

@ -0,0 +1,160 @@
/**
* @file lwrb.h
* \brief LwRB - Lightweight ring buffer
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v3.2.0
*/
#ifndef LWRB_HDR_H
#define LWRB_HDR_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "lib.h"
// #define LWRB_DISABLE_ATOMIC
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* \defgroup LWRB Lightweight ring buffer manager
* \brief Lightweight ring buffer manager
* \{
*/
#if defined(LWRB_DISABLE_ATOMIC) || __DOXYGEN__
#include <stdatomic.h>
/**
* \brief Atomic type for size variable.
* Default value is set to be `unsigned 32-bits` type
*/
typedef atomic_ulong lwrb_sz_atomic_t;
/**
* \brief Size variable for all library operations.
* Default value is set to be `unsigned 32-bits` type
*/
typedef unsigned long lwrb_sz_t;
#else
typedef unsigned long lwrb_sz_atomic_t;
typedef unsigned long lwrb_sz_t;
#endif
/**
* \brief Event type for buffer operations
*/
typedef enum
{
LWRB_EVT_READ, /*!< Read event */
LWRB_EVT_WRITE, /*!< Write event */
LWRB_EVT_RESET, /*!< Reset event */
} lwrb_evt_type_t;
/**
* \brief Buffer structure forward declaration
*/
struct lwrb;
/**
* \brief Event callback function type
* \param[in] buff: Buffer handle for event
* \param[in] evt: Event type
* \param[in] bp: Number of bytes written or read (when used), depends on event type
*/
typedef void (*lwrb_evt_fn)(struct lwrb *buff, lwrb_evt_type_t evt, lwrb_sz_t bp);
/* List of flags */
#define LWRB_FLAG_READ_ALL ((uint16_t)0x0001)
#define LWRB_FLAG_WRITE_ALL ((uint16_t)0x0001)
/**
* \brief Buffer structure
*/
typedef struct lwrb
{
uint8_t *buff; /*!< Pointer to buffer data. Buffer is considered initialized when `buff != NULL` and `size > 0` */
lwrb_sz_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */
lwrb_sz_atomic_t r_ptr; /*!< Next read pointer.
Buffer is considered empty when `r == w` and full when `w == r - 1` */
lwrb_sz_atomic_t w_ptr; /*!< Next write pointer.
Buffer is considered empty when `r == w` and full when `w == r - 1` */
lwrb_evt_fn evt_fn; /*!< Pointer to event callback function */
void *arg; /*!< Event custom user argument */
} lwrb_t;
uint8_t lwrb_init(lwrb_t *buff, void *buffdata, lwrb_sz_t size);
uint8_t lwrb_is_ready(lwrb_t *buff);
void lwrb_free(lwrb_t *buff);
void lwrb_reset(lwrb_t *buff);
void lwrb_set_evt_fn(lwrb_t *buff, lwrb_evt_fn fn);
void lwrb_set_arg(lwrb_t *buff, void *arg);
void *lwrb_get_arg(lwrb_t *buff);
/* Read/Write functions */
lwrb_sz_t lwrb_write(lwrb_t *buff, const void *data, lwrb_sz_t btw);
lwrb_sz_t lwrb_read(lwrb_t *buff, void *data, lwrb_sz_t btr);
lwrb_sz_t lwrb_peek(const lwrb_t *buff, lwrb_sz_t skip_count, void *data, lwrb_sz_t btp);
/* Extended read/write functions */
uint8_t lwrb_write_ex(lwrb_t *buff, const void *data, lwrb_sz_t btw, lwrb_sz_t *bwritten, uint16_t flags);
uint8_t lwrb_read_ex(lwrb_t *buff, void *data, lwrb_sz_t btr, lwrb_sz_t *bread, uint16_t flags);
/* Buffer size information */
lwrb_sz_t lwrb_get_free(const lwrb_t *buff);
lwrb_sz_t lwrb_get_full(const lwrb_t *buff);
/* Read data block management */
void *lwrb_get_linear_block_read_address(const lwrb_t *buff);
lwrb_sz_t lwrb_get_linear_block_read_length(const lwrb_t *buff);
lwrb_sz_t lwrb_skip(lwrb_t *buff, lwrb_sz_t len);
/* Write data block management */
void *lwrb_get_linear_block_write_address(const lwrb_t *buff);
lwrb_sz_t lwrb_get_linear_block_write_length(const lwrb_t *buff);
lwrb_sz_t lwrb_advance(lwrb_t *buff, lwrb_sz_t len);
/* Search in buffer */
uint8_t lwrb_find(const lwrb_t *buff, const void *bts, lwrb_sz_t len, lwrb_sz_t start_offset, lwrb_sz_t *found_idx);
lwrb_sz_t lwrb_overwrite(lwrb_t *buff, const void *data, lwrb_sz_t btw);
lwrb_sz_t lwrb_move(lwrb_t *dest, lwrb_t *src);
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWRB_HDR_H */

45
inc/malloc.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef _MOLLOC_H
#define _MOLLOC_H
#include "../inc/data_type_def.h"
#ifndef NULL
#define NULL 0
#endif
// 定义两个内存池
#define SRAMIN 0 // 内部内存池
#define SRAMEX 1 // 外部内存池(精英STM32开发板不支持外部内存)
// 我们又多少个SRAM可管理
#define SRAMBANK 2 // 定义支持的SRAM块数. 精英版实际上只支持1个内存区域,即内部内存.
// mem1内存参数设定.mem1完全处于内部SRAM里面.(设置内部SARM的内存池和内存表的参数)
#define MEM1_BLOCK_SIZE 8 // 一个内存块大小为32字节
#define MEM1_MAX_SIZE 25 * 1024 // 最大管理内存 1K (我们这个内存管理系统的内部SRAM可控制的内存大小)
#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE / MEM1_BLOCK_SIZE // 内存表大小(有多少块内存块)
// mem2内存参数设定.mem2的内存池处于外部SRAM里面
#define MEM2_BLOCK_SIZE 8 // 一个内存块大小为32字节
#define MEM2_MAX_SIZE 20 * 1024 // 因为精英版没有外扩内存,故这里设置一个最小值
#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE / MEM2_BLOCK_SIZE // 内存表大小
// 内存管理控制器结构体
// 注意:内存管理由内存池和内存列表组成
// SRAMBANKSARM块数一般有内部SRAM和外部SRAM、CCM
struct _m_mallco_dev
{
void (*init)(uint8_t); // 初始化
uint8_t (*perused)(uint8_t); // 内存使用率
uint8_t *membase[SRAMBANK]; // 内存池 管理SRAMBANK个区域的内存
uint16_t *memmap[SRAMBANK]; // 内存管理状态表
uint8_t memrdy[SRAMBANK]; // 内存管理是否就绪
};
void my_mem_init(uint8_t memx);
uint8_t my_mem_perused(uint8_t memx);
void *mymalloc(uint8_t memx, uint32_t size);
void myfree(uint8_t memx, void *ptr);
void *myrealloc(uint8_t memx, void *ptr, uint32_t size);
#endif

268
inc/mlist.h Normal file
View File

@ -0,0 +1,268 @@
/***
* @Author:
* @Date: 2023-04-04 08:39:32
* @LastEditors: xxx
* @LastEditTime: 2023-04-04 08:46:20
* @Description: Linux内核 (include/linux/list.h)
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __LIST_H
#define __LIST_H
#include <stdbool.h>
#include "data_type_def.h"
typedef struct list_head
{
struct list_head *next;
struct list_head *prev;
} list_head_t;
/**
* ,
*
* @param ptr:
* @param type:
* @param member:
*
* @return
*/
#define list_entry_addr_find(ptr, type, member) \
((type *)((char *)(ptr) - (char *)(&((type *)NULL)->member)))
/**
*
*
* @param head:
* @param type:
* @param member:
*
* @return
*/
#define list_entry_decap(head, type, member) \
( \
(list_empty(head)) ? (type *)NULL \
: (list_entry_addr_find(list_next_elem_get(head), type, member)))
#define list_entry_get_head(head, type, member) \
((list_empty(head)) ? (type *)NULL : (list_entry_addr_find((head)->next, type, member)))
/**
*
*
* @param head:
* @param type:
* @param member:
*
* @return
*/
#define list_entry_curtail(head, type, member) \
((list_empty(head)) ? (type *)NULL \
: (list_entry_addr_find(list_curtail(head), type, member)))
/**
* -- list_for_each
*
* @param pos:
* @param head:
*/
#define list_for_each_forwards(pos, head) \
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
/**
*
*
* @param pos:
* @param head:
*/
#define list_for_each_backwards(pos, head) \
for ((pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev)
/**
*
*
* @param pos:
* @param n:
* @param head:
*/
#define list_for_each_safe(pos, n, head) \
for ((pos) = (head)->next, n = (pos)->next; (pos) != (head); \
(pos) = n, n = (pos)->next)
/**
*
*
* @param pos:
* @param head:
* @param type:
* @param member:
*/
#define list_entry_for_each(pos, head, type, member) \
for ((pos) = list_entry_addr_find((head)->next, type, member); \
&(pos)->member != (head); \
(pos) = list_entry_addr_find((pos)->member.next, type, member))
/**
* ,
*
* @param pos:
* @param n:
* @param head:
* @param type:
* @param member:
*/
#define list_entry_for_each_safe(pos, n, head, type, member) \
for ((pos) = list_entry_addr_find((head)->next, type, member), \
n = list_entry_addr_find((pos)->member.next, type, member); \
&(pos)->member != (head); \
(pos) = n, n = list_entry_addr_find(n->member.next, type, member))
/**
*
*/
#define list_count(head, count) \
do \
{ \
count = 0; \
for (list_head_t *pos = (head)->next; pos != (head); pos = pos->next) \
{ \
count++; \
} \
} while (0)
/**
* funcCompare来决定 -- list_sorted_add
*
* @param new_entry:
* @param head:
* @param type:
* @param member:
* @param func_compare: ,bool func_compare(Node* A, Node* B)
* A < B, true, false
* @param pos:
*/
#define list_entry_sorted_add(new_entry, head, type, member, func_compare, pos) \
do \
{ \
type *entry_a = NULL; \
type *entry_b = NULL; \
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next) \
{ \
entry_a = list_entry_addr_find((new_entry), type, member); \
entry_b = list_entry_addr_find((pos), type, member); \
if (func_compare(entry_a, entry_b)) \
{ \
break; \
} \
} \
if ((pos) != (head)) \
{ \
list_insert_forwards((new_entry), (pos)); \
} \
else \
{ \
list_add_to_tail((new_entry), (head)); \
} \
} while (__LINE__ == -1)
/**
*
*
* @param ptr:
*/
void list_init(list_head_t *const ptr);
/**
*
*
* @param new_entry:
* @param pos:
*/
void list_insert_forwards(list_head_t *const new_entry, list_head_t *const pos);
/**
*
*
* @param new_entry:
* @param pos:
*/
void list_insert_backwards(list_head_t *const new_entry, list_head_t *const pos);
/**
* -- list_append
*
* @param new_entry:
* @param list:
*/
void list_add_to_tail(list_head_t *const new_entry, list_head_t *const list);
/**
*
*
* @param new_entry:
* @param list:
*/
void list_add_to_head(list_head_t *const new_entry, list_head_t *const list);
/**
*
*
* @param elem:
*/
void list_del(list_head_t *const elem);
/**
*
*
* @param head:
*
* @return
*/
list_head_t *list_curtail(const list_head_t *const head);
/**
*
*
* @param head:
*
* @return TRUEFALSE
*/
bool list_empty(const list_head_t *const head);
/**
* -- list_get_head
*
* @param head:
*
* @return
*/
list_head_t *list_first_elem_look(const list_head_t *const head);
/**
*
*
* @param pos:
*
* @return
*/
list_head_t *list_next_elem_get(const list_head_t *const pos);
/**
*
*
* @param elem:
* @param head:
*/
void list_move_to_another_head(list_head_t *const elem, list_head_t *const head);
/**
*
*
* @param elem:
* @param head:
*/
void list_move_to_another_tail(list_head_t *const elem, list_head_t *const head);
#endif
/**
* @}
*/

181
inc/osel_arch.h Normal file
View File

@ -0,0 +1,181 @@
/***
* @Author:
* @Date: 2023-04-04 08:13:11
* @LastEditors: xxx
* @LastEditTime: 2023-04-04 08:16:58
* @Description:
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __OSEL_ARCH_H__
#define __OSEL_ARCH_H__
#include "lib.h"
#define hal_int_state_t char
#ifdef STM32
#include "main.h"
#define HAL_ENTER_CRITICAL(__HANDLE__) \
do \
{ \
if ((__HANDLE__)->Lock == HAL_LOCKED) \
{ \
return HAL_BUSY; \
} \
else \
{ \
(__HANDLE__)->Lock = HAL_LOCKED; \
} \
} while (0U)
#define HAL_EXIT_CRITICAL(__HANDLE__) \
do \
{ \
(__HANDLE__)->Lock = HAL_UNLOCKED; \
} while (0U)
#else
#define HAL_ENTER_CRITICAL(__HANDLE__)
#define HAL_EXIT_CRITICAL(__HANDLE__)
#endif
#define osel_memset _memset
#define osel_memcmp _memcmp
#define osel_memcpy _memcpyL
#define osel_memcpyr _memcpyR
#define osel_reverse _reverse
#define osel_mem_alloc _malloc
#define osel_mem_free _free
#define osel_mem_alloc2 _malloc2
#define osel_mem_free2 _free2
#define osel_mstrlen _mstrlen
static inline void *_malloc(uint32_t size)
{
return mymalloc(SRAMIN, size);
}
static inline void _free(void *ptr)
{
myfree(SRAMIN, ptr);
}
static inline void *_malloc2(uint32_t size)
{
return mymalloc(SRAMEX, size);
}
static inline void _free2(void *ptr)
{
myfree(SRAMEX, ptr);
}
/**
* @brief Fills a block of memory with a given value.
*
* @param dst The destination block of memory.
* @param value The value to fill the memory with.
* @param size The size of the memory block, in bytes.
*/
static inline void _memset(uint8_t *dst, uint8_t value, uint16_t size)
{
while (size--)
{
*dst++ = value;
}
}
/**
* @brief Compares two blocks of memory for equality.
*
* @param[in] dst The first block of memory to compare.
* @param[in] src The second block of memory to compare.
* @param[in] size The number of bytes to compare.
*
* @return 0 if the blocks of memory are equal, -1 otherwise.
*/
static inline int8_t _memcmp(const uint8_t *dst, const uint8_t *src, uint16_t size)
{
while (size--)
{
if (*dst++ != *src++)
{
return -1;
}
}
return 0;
}
/**
* @brief Copies data from a source buffer to a destination buffer in a forward direction.
*
* @param dst The destination buffer.
* @param src The source buffer.
* @param size The number of bytes to copy.
*/
static inline void _memcpyL(uint8_t *dst, const uint8_t *src, uint16_t size)
{
while (size--)
{
*dst++ = *src++;
}
}
/**
* @brief Copies data from a source buffer to a destination buffer in reverse order.
*
* @param dst The destination buffer.
* @param src The source buffer.
* @param size The number of bytes to copy.
*/
static inline void _memcpyR(uint8_t *dst, const uint8_t *src, uint16_t size)
{
// dst is a pointer to the last byte of the destination buffer
// src is a pointer to the first byte of the source buffer
// size is the number of bytes to copy
// decrement the destination pointer by the size, since we want to write to the last byte of the buffer
dst = dst + (size - 1);
// loop through each byte in the buffer, copying from the source to the destination in reverse order
while (size--)
{
// write the next byte from the source to the destination
*dst-- = *src++;
}
}
/**
* @brief Reverses the order of bytes in a buffer
*
* @param buf The buffer to reverse
* @param len The length of the buffer, in bytes
*/
static inline void _reverse(uint8_t *buf, uint16_t len)
{
uint8_t temp = 0;
uint16_t i;
for (i = 0; i < len / 2; i++)
{
temp = buf[i];
buf[i] = buf[len - i - 1];
buf[len - i - 1] = temp;
}
}
/**
* @brief Returns the length of a null-terminated string
*
* @param s The string to measure
* @return The length of the string, not including the null terminator
*/
static inline unsigned int _mstrlen(const unsigned char *s)
{
const unsigned char *ss = s;
while (*ss)
ss++;
return ss - s;
}
#endif // __OSEL_ARCH_H__

169
inc/pbuf.h Normal file
View File

@ -0,0 +1,169 @@
/***
* @Author:
* @Date: 2023-04-04 10:06:40
* @LastEditors: xxx
* @LastEditTime: 2023-04-04 13:21:27
* @Description:
* @email:
* @Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef COMPONENTS_COMMON_INCLUDE_PBUF_H_
#define COMPONENTS_COMMON_INCLUDE_PBUF_H_
#include "../inc/data_type_def.h"
#include "../inc/mlist.h"
#include "../inc/malloc.h"
#define PBUF_DBG_EN (1u)
#define PBUF_TYPE_MAX_NUM (3u)
#define PBUF_NUM_MAX (10u)
// 如果size>254,并使用data_analysis接收数据需要修改data_analysis.c中的DATA_BUF_RECV_SQQ_LEN
#define SMALL_PBUF_BUFFER_SIZE (32)
#define MEDIUM_PBUF_BUFFER_SIZE (32 * 2)
#define LARGE_PBUF_BUFFER_SIZE (32 * 4)
#define SMALL_PBUF_NUM (4u) // 各种PBUF最大个数
#define MEDIUM_PBUF_NUM (4u)
#define LARGE_PBUF_NUM (4u)
#if PBUF_DBG_EN > 0
/*形参*/
#define _PLINE1_ , uint16_t line
#define _PLINE2_ , uint16_t line
/*实参*/
#define __PLINE1 , __LINE__
#define __PLINE2 , __LINE__
#else
#define _PLINE1_
#define _PLINE2_
#define __PLINE1
#define __PLINE2
#endif
enum _PBUF_TYPE
{
SMALL_PBUF,
MEDIUM_PBUF,
LARGE_PBUF,
PBUF_TYPE_INVALID
};
typedef struct __send_times_t
{
uint8_t app_send_times;
uint8_t mac_send_times;
} send_times_t;
typedef struct
{
int8_t rssi_dbm;
uint8_t seq;
nwk_id_t src_id; // 接收到数据帧时,为同步模块提供同步对象信息;
nwk_id_t dst_id; // 填写帧的目的节点网络地址
uint8_t send_mode : 2,
is_ack : 1,
need_ack : 1,
crc_ok : 1,
is_pending : 1,
debug_info : 1,
reserved : 1;
send_times_t already_send_times;
} pkt_attri_t;
typedef struct
{
struct list_head list;
uint8_t *data_p; // 指向数据区
uint8_t *head; // 指向数据区的第一个字节
uint8_t *end; // 指向数据区的最后一个字节
uint16_t data_len; // 该pbuf的实际数据长度
pkt_attri_t attri;
bool used;
#if PBUF_DBG_EN > 0
uint16_t alloc_line;
uint16_t free_line;
#endif
} pbuf_t;
/**
* pbuf_initz: pbuf申请一块内存区域pbuf的大小和数量等
*/
void pbuf_initz(void);
/**
* pbuf
*
* @param size:
* @param _PLINE1_: pbuf_allocz()__PLINE1
*
* @return: pbuf的指针
*/
extern pbuf_t *pbuf_allocz(uint16_t size _PLINE1_);
/**
* 使pbuf
*
* @param pbuf: pbuf的指针的指针
* @param _PLINE2_: pbuf_freez()__PLINE2
*
* @return:
*/
void pbuf_freez(pbuf_t **const pbuf _PLINE2_);
/**
* pbuf->end方向移动pbuf->data_p指针len
*
* @param pbuf: pbuf的指针
* @param len: data_p需要移动的距离
*
* @return: data_p指针NULL
*/
extern uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf,
uint8_t len);
/**
* pbuf->head方向移动pbuf->data_p指针len
*
* @param pbuf: pbuf的指针
* @param len: data_p需要移动的距离
*
* @return: data_p指针NULL
*/
extern uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf,
uint8_t len);
/**
* pbuf的数据区拷贝数据data_p指针data_len
*
* @param pbuf: pbuf的指针(pbuf->data_p开始拷贝)
* @param src:
* @param len:
*
* @return: TRUE, FALSE
*/
extern bool pbuf_copy_data_in(pbuf_t *const pbuf,
const uint8_t *const src,
uint8_t len);
/**
* pbuf的数据区拷贝数据data_p指针data_len
*
* @param dst:
* @param pbuf: pbuf的指针(pbuf->data_p开始拷贝)
* @param len:
*
* @return: TRUE,
*/
extern bool pbuf_copy_data_out(uint8_t *const dst,
pbuf_t *const pbuf,
uint8_t len);
#endif /* COMPONENTS_COMMON_INCLUDE_PBUF_H_ */

52
inc/sqqueue.h Normal file
View File

@ -0,0 +1,52 @@
/**
* @file sqqueue.h
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#ifndef __SQQUEUE_H
#define __SQQUEUE_H
#include "data_type_def.h"
typedef struct _sqqueue_t
{
uint8_t *base; // 队列存储元素的首地址
uint8_t entry_size; // 队列元素的宽度
uint16_t sqq_len; // 队列总长
uint16_t front; // 队列头下标
uint16_t rear; // 队列尾下标
} sqqueue_t;
/**
*
*
* ()
*/
typedef struct _sqqueue_ctrl_t
{
sqqueue_t sqq;
BOOL(*enter)
(struct _sqqueue_ctrl_t *const p_this, const void *const e); // 单元素入队列
BOOL(*string_enter)
(struct _sqqueue_ctrl_t *const p_this, const void *const string, uint16_t len); // 多元素入队列
void *(*del)(struct _sqqueue_ctrl_t *const p_this); // 出队列
void *(*revoke)(struct _sqqueue_ctrl_t *const p_this); // 撤销入队列
uint16_t (*get_len)(const struct _sqqueue_ctrl_t *const p_this); // 取队列长度
BOOL(*full)
(const struct _sqqueue_ctrl_t *const p_this); // 判满
void (*clear_sqq)(struct _sqqueue_ctrl_t *const p_this); // 清空队列
void (*traverse)(struct _sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)); // 遍历
void (*remove)(struct _sqqueue_ctrl_t *const p_this, uint16_t location); // 删除指定位置
} sqqueue_ctrl_t;
BOOL sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this,
uint8_t entry_size,
uint16_t sqq_len); ///< 初始化
void sqqueue_ctrl_dinit(sqqueue_ctrl_t *const p_this); ///< 销毁
#endif
/**
* @}
*/

52
inc/storage.h Normal file
View File

@ -0,0 +1,52 @@
/**
* @file storage.h
* @author xushenghao
* @date 2024-11-15 15:57:02
* @brief
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __STORAGE_H__
#define __STORAGE_H__
#include "lib.h"
typedef struct
{
uint16_t index;
uint16_t size;
uint32_t address;
} storage_node_t;
typedef struct
{
clist_node_t *head;
struct
{
uint32_t base_addr; ///< 存储器基地址
uint16_t page_size; ///< 存储器页大小
uint16_t variable_count; ///< 存储器变量数量
uint16_t variable_size; ///< 存储器变量占用大小,如果变量大小不够一页剩余部分则写入下一页,上一页剩余字节计入变量占用大小
uint16_t page_count; ///< 变量占用存储器页数
} params;
struct
{
BOOL(*read)
(uint32_t addr, uint8_t *buf, uint16_t size);
BOOL(*write)
(uint32_t addr, uint8_t * buf, uint16_t size);
BOOL(*erase_page)
(uint32_t page);
} ops;
} storage_t;
storage_t *storage_init(uint32_t base_addr, uint16_t page_size); ///< 初始化存储器
void storage_destroy(storage_t *storage); ///< 销毁存储器
void storage_add_node(storage_t *storage, uint16_t index, uint16_t size); ///< 添加存储节点
BOOL storage_write(storage_t *storage, uint16_t index, const uint8_t *buf); ///< 存储数据
BOOL storage_read(storage_t *storage, uint16_t index, uint8_t *buf); ///< 读取数据
BOOL storage_write_all(storage_t *storage, const uint8_t *buf); ///< 存储所有数据
BOOL storage_read_all(storage_t *storage, uint8_t *buf); ///< 读取所有数据
BOOL storage_check(storage_t *storage, uint16_t index, uint8_t *buf); ///< 检查存储数据
BOOL storage_check_all(storage_t *storage, uint8_t *buf); ///< 检查所有存储数据
#endif // __STORAGE_H__

108
inc/wl_flash.h Normal file
View File

@ -0,0 +1,108 @@
/**
* @file wl_flash.h
* @author xushenghao
* @date 2024-07-22 13:57:02
* @brief
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
/**
* @brief
*
* 1. block_page大小和当前写入地址
* 2.
* a.
* b.
* i. 使block_pageblock_page继续写入
* ii. block_pageblock_page是否已满
* - block_page
* - block_page是否有有效数据需要迁移
* 3. block_page前Wear Leveling算法选择最佳的block_page进行擦除
* 4.
*/
/**
* 使
*
#define LL_FLASH_PAGE_SIZE (2 * 1024)
#define PVD_RESET_STORAGE_START_ADDRESS (256 * LL_FLASH_PAGE_SIZE)
static void test_wl_flash(void)
{
uint32_t address = 0;
wl_flash_t wf = {
.wl_flag = TRUE,
.addr = PVD_RESET_STORAGE_START_ADDRESS,
.len = 2 * LL_FLASH_PAGE_SIZE,
.page_size = LL_FLASH_PAGE_SIZE,
.data_size = sizeof(device_reset_t),
.write_gran = 8,
.ops.srand = board_srand,
.ops.read = flash_read,
.ops.write = flash_write,
.ops.erase_page = flash_erase_page,
};
wl_flash_init(&wf);
wl_flash_erase(&wf);
address = wl_flash_get_current_address(&wf);
device_reset_t power_on;
power_on.flag = PVD_RESET_FLAG;
// 一页2048/16 = 128个数据,2页 = 256个数据i=255时数据从头开始
for (uint16_t i = 0; i < 1000; i++)
{
wl_flash_write(&wf, (uint8_t *)&power_on, sizeof(device_reset_t));
wl_flash_set_next_address(&wf);
address = wl_flash_get_current_address(&wf);
if (address == wf.addr)
{
__NOP();
}
}
}
*/
#ifndef __WL_FLASH_H__
#define __WL_FLASH_H__
#include "lib.h"
typedef struct
{
BOOL wl_flag; // 开启平衡擦写标志
uint32_t addr; // Flash 起始地址
uint32_t len; // Flash 长度
uint16_t page_size; // Flash 页大小 2^N
uint16_t data_size; // 数据大小
/* write minimum granularity, unit: byte.
1(stm32f2/f4)/ 4(stm32f1)/ 8(stm32l4)
0 will not take effect. */
uint8_t write_gran;
struct
{
void (*srand)(void); // 随机数种子
BOOL(*read)
(uint32_t addr, uint8_t *buf, uint16_t size);
BOOL(*write)
(uint32_t addr, const uint8_t *buf, uint16_t size);
BOOL(*erase_page)
(uint32_t page);
} ops;
struct
{
uint32_t current_address; // 当前准备写入的地址
uint16_t residue_size; // 剩余可写大小
uint16_t start_page; // 起始页
uint16_t page_total; // 总页数
uint16_t block_page; // 擦除块大小
} private;
} wl_flash_t;
extern void wl_flash_init(wl_flash_t *cfg); ///< 初始化 Flash 磨损平衡算法
extern uint32_t wl_flash_get_current_address(wl_flash_t *cfg); ///< 获取当前写入地址
extern void wl_flash_set_next_address(wl_flash_t *cfg); ///< 设置下一个写入地址,下一个写入区域会被擦除
extern void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address); ///< 设置当前写入地址
extern void wl_flash_erase(wl_flash_t *cfg); ///< 擦除 Flash, 如果开启了平衡擦写标志, 则会随机分配写入地址
extern BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size); ///< 写入 Flash
extern BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size); ///< 读取 Flash
#endif // __WL_FLASH_H__

169
readme.md Normal file
View File

@ -0,0 +1,169 @@
[TOC]
### clist 简单链表
#### 说明
- clist是list的简化版下面给出常用的接口说明
- 接口说明:
```code
void clist_init(clist_node_t **ppFirst); ///< 初始化 ,构造一条空的链表
void clist_print(clist_node_t *First); ///< 打印链表
uint32_t clist_node_count(clist_node_t *First); ///< 获取链表节点数
void clist_push_back(clist_node_t **ppFirst, cnode data); ///< 尾部插入
void clist_push_front(clist_node_t **ppFirst, cnode data); ///< 头部插入
void clist_pop_back(clist_node_t **ppFirst); ///< 尾部删除
void clist_pop_front(clist_node_t **ppFirst); ///< 头部删除
void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data); ///< 给定结点插入插入到结点前
int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data); ///< 按位置插入
void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos); ///< 给定结点删除
void clist_remove(clist_node_t **ppFirst, cnode data); ///< 按值删除只删遇到的第一个
void clist_remove_all(clist_node_t **ppFirst, cnode data); ///< 按值删除删除所有的
void clist_destroy(clist_node_t **ppFirst); ///< 销毁 需要销毁每一个节点
clist_node_t *clist_find(clist_node_t *pFirst, cnode data); ///< 按值查找返回第一个找到的结点指针如果没找到返回 NULL
```
#### DEMO
- 详细使用请见<a href="examples/simple_clist.c" target="_blank">simple_clist.c</a>
- examples目录内执行```make clist && make run```
### cmd 命令解析器
#### 说明
- cmd是一个非常简单好用的命令解析器。
> 简单来说我希望我的开发板可以通过命令执行一些处理比如说我用串口发一个命令A开发板就执行A的一些处理或者在调试某些AT模组的时候当我收到模组返回的一些指令后自动执行一些处理。
- 接口说明:
```code
REGISTER_CMD(cmd, handler, desc) ///< 注册命令
void cmd_init(void); ///< 初始化命令
void cmd_parsing(char *str); ///< 命令解析
```
#### DEMO
- 详细使用请见<a href="examples/simple_cmd.c" target="_blank">simple_cmd.c</a>
- 该模块不提供GCC编译只提供KEIL编译和IAR编译
### data_analysis 数据分析器
#### 说明
- data_analysis 是用来处理串口或者其他方式获得的数据,具有识别数据帧起始和结束的功能,只需要定义好识别符以及长度,该模块会将完整的数据帧处理好
- 接口说明:
```code
typedef void (*data_interupt_cb_t)(uint8_t id, uint8_t ch); ///< 中断回调函数数据从这里写入
extern uint8_t data_read(uint8_t id, void *buffer, uint16_t len); ///< 读取数据
extern void data_write(uint8_t id, uint8_t *const string, uint16_t len); ///< TODO 写入数据
extern void lock_data(uint8_t data_id); ///< 锁定数据防止中断写入数据
extern void unlock_data(uint8_t data_id); ///< 解锁数据
extern data_interupt_cb_t data_fsm_init(uint8_t data_id); ///< 初始化数据状态机
extern bool data_reg(uint8_t id, data_reg_t reg); ///< 注册数据
extern void data_unreg(uint8_t id); ///< 注销数据
```
#### DEMO
- 详细使用请见<a href="examples/simple_data_analysis.c" target="_blank">simple_data_analysis.c</a>
- examples目录内执行```make data_analysis && make run```
### sqqueue(队列)
#### 说明
- sqqueue 是一个成员变量固定长度的队列
- 使用的时候先创建一个"sqqueue_ctrl_t"类型的队列对象,调用初始化函数后就可以使用对象中的功能了
#### DEMO
- 详细使用请见<a href="examples/simple_sqqueue.c" target="_blank">simple_sqqueue.c</a>
- examples目录内执行```make sqqueue && make run```
### aes(加密)
<a href="http://baike.baidu.com/link?url=WnbPeKCwba_BGRIBls-MNxyghGRrAI3Ubu4bntdlnjqHKzOjEl5a3-w-E-XF0Mi-A8dEaFpC31ofGw-GOaC_ea" target="_blank">百度百科</a>
#### 说明
- 对不同长度的密钥AES采用不同的加密轮次
| 128位 | 192位 | 256位 |
| ------------- | -----------: | :--------: |
| 10 | 12 | 14 |
- 密钥扩展:简单说就是将原来的密钥扩展到足够用的长度:
- 128位密钥 扩展到 11x4x4
- 192位密钥 扩展到 13x4x4
- 256位密钥 扩展到 15x4x4
- AES加密过程是在一个4×4的字节矩阵上运作,所以一次加解密传入的最小块单位为16字节
#### 代码流程
```flow
st=>start: 加密开始
e=>end: 加密结束
op1=>operation: 加密的数据[简称密文]、密钥16个字节、输入数据块和输出数据块
op2=>operation: 调用接口"aes_set_key",完成密钥的扩展
op3=>operation: 调用接口"aes_encrypt",完成数据的加密
st->op1->op2->op3->e
```
```flow
st=>start: 解密开始
e=>end: 解密结束
op1=>operation: 解密的数据[简称密文]、密钥16个字节、输入数据块和输出数据块
op2=>operation: 调用接口"aes_set_key",完成密钥的扩展
op3=>operation: 调用接口"aes_encrypt",完成数据的解密
st->op1->op2->op3->e
```
#### DEMO
- demo中会使用aes中的接口完成简单的加密和解密数据
- **将aes.h中的AES_ENC_PREKEYED和AES_DEC_PREKEYED置1**
- 详细使用请见<a href="../../apps/simple_aes.c" target="_blank">simple_aes.c</a>
- examples目录内执行```make aes && make run```
### cmac(类CRC)
#### 说明
- cmac是一种数据传输检错功能以保证数据传输的正确性和完整性
- cmac基本原理是通过对需要校验的数据奇偶校验、位移、AES加密获取一段16个字节大小的数组
- **lorawan使用cmac模块给MAC数据和加密数据做校验的优点效率很高、安全性很高在校验数据之前调用"AES_CMAC_Update"二次,增加了异变因子)**
- **困惑为什么不使用CRC32**
- demo中只对需要校验的数据使用"AES_CMAC_Update"一次无法确定lorawan增加一次"AES_CMAC_Update"的效果如何
#### 代码流程
```flow
st=>start: 校验开始
e=>end: 校验结束
op1=>operation: 需要校验的数据、密钥、密钥扩展表
op2=>operation: 调用接口"AES_CMAC_Init",完成密钥扩展表的初始化
op3=>operation: 调用接口"AES_CMAC_SetKey",完成密钥扩展表数据
op4=>operation: 调用接口"AES_CMAC_Update",完成数据的奇偶校验
op5=>operation: 调用接口"AES_CMAC_Final",生成16个字节的校验表
op6=>operation: 取表4个字节作为校验码
st->op1->op2->op3->op4->op5->op6->e
```
#### DEMO
- 详细使用请见<a href="../../apps/simple_cmac.c" target="_blank">simple_cmac.c</a>
- examples目录内执行```make cmac && make run```

0
src/.gitkeep Normal file
View File

981
src/aes.c Normal file
View File

@ -0,0 +1,981 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state (there are options to use 32-bit types if available).
The combination of mix columns and byte substitution used here is based on
that developed by Karl Malbrain. His contribution is acknowledged.
*/
/* define if you have a fast memcpy function on your system */
#if 0
#define HAVE_MEMCPY
#include <string.h>
#if defined(_MSC_VER)
#include <intrin.h>
#pragma intrinsic(memcpy)
#endif
#endif
#include <stdlib.h>
#include <stdint.h>
/* define if you have fast 32-bit types on your system */
#if (__CORTEX_M != 0) // if Cortex is different from M0/M0+
#define HAVE_UINT_32T
#endif
/* define if you don't want any tables */
#if 1
#define USE_TABLES
#endif
/* On Intel Core 2 duo VERSION_1 is faster */
/* alternative versions (test for performance on your system) */
#if 1
#define VERSION_1
#endif
#include "aes.h"
// #if defined( HAVE_UINT_32T )
// typedef unsigned long uint32_t;
// #endif
/* functions for finite field multiplication in the AES Galois field */
#define WPOLY 0x011b
#define BPOLY 0x1b
#define DPOLY 0x008d
#define f1(x) (x)
#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) ^ (((x >> 5) & 4) * WPOLY))
#define d2(x) (((x) >> 1) ^ ((x)&1 ? DPOLY : 0))
#define f3(x) (f2(x) ^ x)
#define f9(x) (f8(x) ^ x)
#define fb(x) (f8(x) ^ f2(x) ^ x)
#define fd(x) (f8(x) ^ f4(x) ^ x)
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
#if defined(USE_TABLES)
#define sb_data(w) \
{ /* S Box data values */ \
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5), \
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76), \
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0), \
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0), \
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), \
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), \
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75), \
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0), \
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84), \
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b), \
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), \
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), \
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5), \
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2), \
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17), \
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73), \
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), \
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), \
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79), \
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9), \
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08), \
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6), \
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), \
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), \
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94), \
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf), \
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68), \
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) \
}
#define isb_data(w) \
{ /* inverse S Box data values */ \
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38), \
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb), \
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87), \
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb), \
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d), \
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e), \
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2), \
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25), \
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16), \
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92), \
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda), \
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84), \
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a), \
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06), \
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02), \
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b), \
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea), \
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73), \
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85), \
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e), \
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89), \
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b), \
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20), \
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4), \
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31), \
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f), \
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d), \
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef), \
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0), \
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61), \
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26), \
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) \
}
#define mm_data(w) \
{ /* basic data for forming finite field tables */ \
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07), \
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f), \
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17), \
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f), \
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27), \
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f), \
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37), \
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f), \
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47), \
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f), \
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57), \
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f), \
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67), \
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f), \
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77), \
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f), \
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87), \
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f), \
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97), \
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f), \
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7), \
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf), \
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7), \
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf), \
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7), \
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf), \
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7), \
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf), \
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7), \
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef), \
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7), \
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) \
}
static const uint8_t sbox[256] = sb_data(f1);
#if defined(AES_DEC_PREKEYED)
static const uint8_t isbox[256] = isb_data(f1);
#endif
static const uint8_t gfm2_sbox[256] = sb_data(f2);
static const uint8_t gfm3_sbox[256] = sb_data(f3);
#if defined(AES_DEC_PREKEYED)
static const uint8_t gfmul_9[256] = mm_data(f9);
static const uint8_t gfmul_b[256] = mm_data(fb);
static const uint8_t gfmul_d[256] = mm_data(fd);
static const uint8_t gfmul_e[256] = mm_data(fe);
#endif
#define s_box(x) sbox[(x)]
#if defined(AES_DEC_PREKEYED)
#define is_box(x) isbox[(x)]
#endif
#define gfm2_sb(x) gfm2_sbox[(x)]
#define gfm3_sb(x) gfm3_sbox[(x)]
#if defined(AES_DEC_PREKEYED)
#define gfm_9(x) gfmul_9[(x)]
#define gfm_b(x) gfmul_b[(x)]
#define gfm_d(x) gfmul_d[(x)]
#define gfm_e(x) gfmul_e[(x)]
#endif
#else
/* this is the high bit of x right shifted by 1 */
/* position. Since the starting polynomial has */
/* 9 bits (0x11b), this right shift keeps the */
/* values of all top bits within a byte */
static uint8_t hibit(const uint8_t x)
{
uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static uint8_t gf_inv(const uint8_t x)
{
uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if (x < 2)
return x;
for (;;)
{
if (n1)
while (n2 >= n1) /* divide polynomial p2 by p1 */
{
n2 /= n1; /* shift smaller polynomial left */
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
v2 ^= (v1 * n2); /* shift accumulated value and */
n2 = hibit(p2); /* add into result */
}
else
return v1;
if (n2) /* repeat with values swapped */
while (n1 >= n2)
{
n1 /= n2;
p1 ^= p2 * n1;
v1 ^= v2 * n1;
n1 = hibit(p1);
}
else
return v2;
}
}
/* The forward and inverse affine transformations used in the S-box */
uint8_t fwd_affine(const uint8_t x)
{
#if defined(HAVE_UINT_32T)
uint32_t w = x;
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4) ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
#endif
}
uint8_t inv_affine(const uint8_t x)
{
#if defined(HAVE_UINT_32T)
uint32_t w = x;
w = (w << 1) ^ (w << 3) ^ (w << 6);
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6) ^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
#endif
}
#define s_box(x) fwd_affine(gf_inv(x))
#define is_box(x) gf_inv(inv_affine(x))
#define gfm2_sb(x) f2(s_box(x))
#define gfm3_sb(x) f3(s_box(x))
#define gfm_9(x) f9(x)
#define gfm_b(x) fb(x)
#define gfm_d(x) fd(x)
#define gfm_e(x) fe(x)
#endif
#if defined(HAVE_MEMCPY)
#define block_copy_nn(d, s, l) memcpy(d, s, l)
#define block_copy(d, s) memcpy(d, s, N_BLOCK)
#else
#define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
#define block_copy(d, s) copy_block(d, s)
#endif
static void copy_block(void *d, const void *s)
{
#if defined(HAVE_UINT_32T)
((uint32_t *)d)[0] = ((uint32_t *)s)[0];
((uint32_t *)d)[1] = ((uint32_t *)s)[1];
((uint32_t *)d)[2] = ((uint32_t *)s)[2];
((uint32_t *)d)[3] = ((uint32_t *)s)[3];
#else
((uint8_t *)d)[0] = ((uint8_t *)s)[0];
((uint8_t *)d)[1] = ((uint8_t *)s)[1];
((uint8_t *)d)[2] = ((uint8_t *)s)[2];
((uint8_t *)d)[3] = ((uint8_t *)s)[3];
((uint8_t *)d)[4] = ((uint8_t *)s)[4];
((uint8_t *)d)[5] = ((uint8_t *)s)[5];
((uint8_t *)d)[6] = ((uint8_t *)s)[6];
((uint8_t *)d)[7] = ((uint8_t *)s)[7];
((uint8_t *)d)[8] = ((uint8_t *)s)[8];
((uint8_t *)d)[9] = ((uint8_t *)s)[9];
((uint8_t *)d)[10] = ((uint8_t *)s)[10];
((uint8_t *)d)[11] = ((uint8_t *)s)[11];
((uint8_t *)d)[12] = ((uint8_t *)s)[12];
((uint8_t *)d)[13] = ((uint8_t *)s)[13];
((uint8_t *)d)[14] = ((uint8_t *)s)[14];
((uint8_t *)d)[15] = ((uint8_t *)s)[15];
#endif
}
static void copy_block_nn(uint8_t *d, const uint8_t *s, uint8_t nn)
{
while (nn--)
//*((uint8_t*)d)++ = *((uint8_t*)s)++;
*d++ = *s++;
}
static void xor_block(void *d, const void *s)
{
#if defined(HAVE_UINT_32T)
((uint32_t *)d)[0] ^= ((uint32_t *)s)[0];
((uint32_t *)d)[1] ^= ((uint32_t *)s)[1];
((uint32_t *)d)[2] ^= ((uint32_t *)s)[2];
((uint32_t *)d)[3] ^= ((uint32_t *)s)[3];
#else
((uint8_t *)d)[0] ^= ((uint8_t *)s)[0];
((uint8_t *)d)[1] ^= ((uint8_t *)s)[1];
((uint8_t *)d)[2] ^= ((uint8_t *)s)[2];
((uint8_t *)d)[3] ^= ((uint8_t *)s)[3];
((uint8_t *)d)[4] ^= ((uint8_t *)s)[4];
((uint8_t *)d)[5] ^= ((uint8_t *)s)[5];
((uint8_t *)d)[6] ^= ((uint8_t *)s)[6];
((uint8_t *)d)[7] ^= ((uint8_t *)s)[7];
((uint8_t *)d)[8] ^= ((uint8_t *)s)[8];
((uint8_t *)d)[9] ^= ((uint8_t *)s)[9];
((uint8_t *)d)[10] ^= ((uint8_t *)s)[10];
((uint8_t *)d)[11] ^= ((uint8_t *)s)[11];
((uint8_t *)d)[12] ^= ((uint8_t *)s)[12];
((uint8_t *)d)[13] ^= ((uint8_t *)s)[13];
((uint8_t *)d)[14] ^= ((uint8_t *)s)[14];
((uint8_t *)d)[15] ^= ((uint8_t *)s)[15];
#endif
}
static void copy_and_key(void *d, const void *s, const void *k)
{
#if defined(HAVE_UINT_32T)
((uint32_t *)d)[0] = ((uint32_t *)s)[0] ^ ((uint32_t *)k)[0];
((uint32_t *)d)[1] = ((uint32_t *)s)[1] ^ ((uint32_t *)k)[1];
((uint32_t *)d)[2] = ((uint32_t *)s)[2] ^ ((uint32_t *)k)[2];
((uint32_t *)d)[3] = ((uint32_t *)s)[3] ^ ((uint32_t *)k)[3];
#elif 1
((uint8_t *)d)[0] = ((uint8_t *)s)[0] ^ ((uint8_t *)k)[0];
((uint8_t *)d)[1] = ((uint8_t *)s)[1] ^ ((uint8_t *)k)[1];
((uint8_t *)d)[2] = ((uint8_t *)s)[2] ^ ((uint8_t *)k)[2];
((uint8_t *)d)[3] = ((uint8_t *)s)[3] ^ ((uint8_t *)k)[3];
((uint8_t *)d)[4] = ((uint8_t *)s)[4] ^ ((uint8_t *)k)[4];
((uint8_t *)d)[5] = ((uint8_t *)s)[5] ^ ((uint8_t *)k)[5];
((uint8_t *)d)[6] = ((uint8_t *)s)[6] ^ ((uint8_t *)k)[6];
((uint8_t *)d)[7] = ((uint8_t *)s)[7] ^ ((uint8_t *)k)[7];
((uint8_t *)d)[8] = ((uint8_t *)s)[8] ^ ((uint8_t *)k)[8];
((uint8_t *)d)[9] = ((uint8_t *)s)[9] ^ ((uint8_t *)k)[9];
((uint8_t *)d)[10] = ((uint8_t *)s)[10] ^ ((uint8_t *)k)[10];
((uint8_t *)d)[11] = ((uint8_t *)s)[11] ^ ((uint8_t *)k)[11];
((uint8_t *)d)[12] = ((uint8_t *)s)[12] ^ ((uint8_t *)k)[12];
((uint8_t *)d)[13] = ((uint8_t *)s)[13] ^ ((uint8_t *)k)[13];
((uint8_t *)d)[14] = ((uint8_t *)s)[14] ^ ((uint8_t *)k)[14];
((uint8_t *)d)[15] = ((uint8_t *)s)[15] ^ ((uint8_t *)k)[15];
#else
block_copy(d, s);
xor_block(d, k);
#endif
}
static void add_round_key(uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK])
{
xor_block(d, k);
}
static void shift_sub_rows(uint8_t st[N_BLOCK])
{
uint8_t tt;
st[0] = s_box(st[0]);
st[4] = s_box(st[4]);
st[8] = s_box(st[8]);
st[12] = s_box(st[12]);
tt = st[1];
st[1] = s_box(st[5]);
st[5] = s_box(st[9]);
st[9] = s_box(st[13]);
st[13] = s_box(tt);
tt = st[2];
st[2] = s_box(st[10]);
st[10] = s_box(tt);
tt = st[6];
st[6] = s_box(st[14]);
st[14] = s_box(tt);
tt = st[15];
st[15] = s_box(st[11]);
st[11] = s_box(st[7]);
st[7] = s_box(st[3]);
st[3] = s_box(tt);
}
#if defined(AES_DEC_PREKEYED)
static void inv_shift_sub_rows(uint8_t st[N_BLOCK])
{
uint8_t tt;
st[0] = is_box(st[0]);
st[4] = is_box(st[4]);
st[8] = is_box(st[8]);
st[12] = is_box(st[12]);
tt = st[13];
st[13] = is_box(st[9]);
st[9] = is_box(st[5]);
st[5] = is_box(st[1]);
st[1] = is_box(tt);
tt = st[2];
st[2] = is_box(st[10]);
st[10] = is_box(tt);
tt = st[6];
st[6] = is_box(st[14]);
st[14] = is_box(tt);
tt = st[3];
st[3] = is_box(st[7]);
st[7] = is_box(st[11]);
st[11] = is_box(st[15]);
st[15] = is_box(tt);
}
#endif
#if defined(VERSION_1)
static void mix_sub_columns(uint8_t dt[N_BLOCK])
{
uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void mix_sub_columns(uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK])
{
#endif
dt[0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
dt[1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
dt[2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
dt[3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
dt[4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
dt[5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
dt[6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
dt[7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
dt[8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
dt[9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
}
#if defined(AES_DEC_PREKEYED)
#if defined(VERSION_1)
static void inv_mix_sub_columns(uint8_t dt[N_BLOCK])
{
uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void inv_mix_sub_columns(uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK])
{
#endif
dt[0] = is_box(gfm_e(st[0]) ^ gfm_b(st[1]) ^ gfm_d(st[2]) ^ gfm_9(st[3]));
dt[5] = is_box(gfm_9(st[0]) ^ gfm_e(st[1]) ^ gfm_b(st[2]) ^ gfm_d(st[3]));
dt[10] = is_box(gfm_d(st[0]) ^ gfm_9(st[1]) ^ gfm_e(st[2]) ^ gfm_b(st[3]));
dt[15] = is_box(gfm_b(st[0]) ^ gfm_d(st[1]) ^ gfm_9(st[2]) ^ gfm_e(st[3]));
dt[4] = is_box(gfm_e(st[4]) ^ gfm_b(st[5]) ^ gfm_d(st[6]) ^ gfm_9(st[7]));
dt[9] = is_box(gfm_9(st[4]) ^ gfm_e(st[5]) ^ gfm_b(st[6]) ^ gfm_d(st[7]));
dt[14] = is_box(gfm_d(st[4]) ^ gfm_9(st[5]) ^ gfm_e(st[6]) ^ gfm_b(st[7]));
dt[3] = is_box(gfm_b(st[4]) ^ gfm_d(st[5]) ^ gfm_9(st[6]) ^ gfm_e(st[7]));
dt[8] = is_box(gfm_e(st[8]) ^ gfm_b(st[9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
dt[13] = is_box(gfm_9(st[8]) ^ gfm_e(st[9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
dt[2] = is_box(gfm_d(st[8]) ^ gfm_9(st[9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
dt[7] = is_box(gfm_b(st[8]) ^ gfm_d(st[9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
dt[1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
dt[6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
}
#endif
#if defined(AES_ENC_PREKEYED) || defined(AES_DEC_PREKEYED)
/* Set the cipher key for the pre-keyed version */
return_type aes_set_key(const uint8_t key[], length_type keylen, aes_context ctx[1])
{
uint8_t cc, rc, hi;
switch (keylen)
{
case 16:
case 24:
case 32:
break;
default:
ctx->rnd = 0;
return (uint8_t)-1;
}
block_copy_nn(ctx->ksch, key, keylen);
hi = (keylen + 28) << 2;
ctx->rnd = (hi >> 4) - 1;
for (cc = keylen, rc = 1; cc < hi; cc += 4)
{
uint8_t tt, t0, t1, t2, t3;
t0 = ctx->ksch[cc - 4];
t1 = ctx->ksch[cc - 3];
t2 = ctx->ksch[cc - 2];
t3 = ctx->ksch[cc - 1];
if (cc % keylen == 0)
{
tt = t0;
t0 = s_box(t1) ^ rc;
t1 = s_box(t2);
t2 = s_box(t3);
t3 = s_box(tt);
rc = f2(rc);
}
else if (keylen > 24 && cc % keylen == 16)
{
t0 = s_box(t0);
t1 = s_box(t1);
t2 = s_box(t2);
t3 = s_box(t3);
}
tt = cc - keylen;
ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
}
return 0;
}
#endif
#if defined(AES_ENC_PREKEYED)
/* Encrypt a single block of 16 bytes */
return_type aes_encrypt(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1])
{
if (ctx->rnd)
{
uint8_t s1[N_BLOCK], r;
copy_and_key(s1, in, ctx->ksch);
for (r = 1; r < ctx->rnd; ++r)
#if defined(VERSION_1)
{
mix_sub_columns(s1);
add_round_key(s1, ctx->ksch + r * N_BLOCK);
}
#else
{
uint8_t s2[N_BLOCK];
mix_sub_columns(s2, s1);
copy_and_key(s1, s2, ctx->ksch + r * N_BLOCK);
}
#endif
shift_sub_rows(s1);
copy_and_key(out, s1, ctx->ksch + r * N_BLOCK);
}
else
return (uint8_t)-1;
return 0;
}
/* CBC encrypt a number of blocks (input and return an IV) */
return_type aes_cbc_encrypt(const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1])
{
while (n_block--)
{
xor_block(iv, in);
if (aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
// memcpy(out, iv, N_BLOCK);
block_copy(out, iv);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined(AES_DEC_PREKEYED)
/* Decrypt a single block of 16 bytes */
return_type aes_decrypt(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1])
{
if (ctx->rnd)
{
uint8_t s1[N_BLOCK], r;
copy_and_key(s1, in, ctx->ksch + ctx->rnd * N_BLOCK);
inv_shift_sub_rows(s1);
for (r = ctx->rnd; --r;)
#if defined(VERSION_1)
{
add_round_key(s1, ctx->ksch + r * N_BLOCK);
inv_mix_sub_columns(s1);
}
#else
{
uint8_t s2[N_BLOCK];
copy_and_key(s2, s1, ctx->ksch + r * N_BLOCK);
inv_mix_sub_columns(s1, s2);
}
#endif
copy_and_key(out, s1, ctx->ksch);
return 0;
}
else
return 1;
}
/* CBC decrypt a number of blocks (input and return an IV) */
return_type aes_cbc_decrypt(const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1])
{
while (n_block--)
{
uint8_t tmp[N_BLOCK];
// memcpy(tmp, in, N_BLOCK);
block_copy(tmp, in);
if (aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
xor_block(out, iv);
// memcpy(iv, tmp, N_BLOCK);
block_copy(iv, tmp);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined(AES_ENC_128_OTFK)
/* The 'on the fly' encryption key update for for 128 bit keys */
static void update_encrypt_key_128(uint8_t k[N_BLOCK], uint8_t *rc)
{
uint8_t cc;
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
*rc = f2(*rc);
for (cc = 4; cc < 16; cc += 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_encrypt_128(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK])
{
uint8_t s1[N_BLOCK], r, rc = 1;
if (o_key != key)
block_copy(o_key, key);
copy_and_key(s1, in, o_key);
for (r = 1; r < 10; ++r)
#if defined(VERSION_1)
{
mix_sub_columns(s1);
update_encrypt_key_128(o_key, &rc);
add_round_key(s1, o_key);
}
#else
{
uint8_t s2[N_BLOCK];
mix_sub_columns(s2, s1);
update_encrypt_key_128(o_key, &rc);
copy_and_key(s1, s2, o_key);
}
#endif
shift_sub_rows(s1);
update_encrypt_key_128(o_key, &rc);
copy_and_key(out, s1, o_key);
}
#endif
#if defined(AES_DEC_128_OTFK)
/* The 'on the fly' decryption key update for for 128 bit keys */
static void update_decrypt_key_128(uint8_t k[N_BLOCK], uint8_t *rc)
{
uint8_t cc;
for (cc = 12; cc > 0; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
}
/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_decrypt_128(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK])
{
uint8_t s1[N_BLOCK], r, rc = 0x6c;
if (o_key != key)
block_copy(o_key, key);
copy_and_key(s1, in, o_key);
inv_shift_sub_rows(s1);
for (r = 10; --r;)
#if defined(VERSION_1)
{
update_decrypt_key_128(o_key, &rc);
add_round_key(s1, o_key);
inv_mix_sub_columns(s1);
}
#else
{
uint8_t s2[N_BLOCK];
update_decrypt_key_128(o_key, &rc);
copy_and_key(s2, s1, o_key);
inv_mix_sub_columns(s1, s2);
}
#endif
update_decrypt_key_128(o_key, &rc);
copy_and_key(out, s1, o_key);
}
#endif
#if defined(AES_ENC_256_OTFK)
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_encrypt_key_256(uint8_t k[2 * N_BLOCK], uint8_t *rc)
{
uint8_t cc;
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
*rc = f2(*rc);
for (cc = 4; cc < 16; cc += 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for (cc = 20; cc < 32; cc += 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
void aes_encrypt_256(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK])
{
uint8_t s1[N_BLOCK], r, rc = 1;
if (o_key != key)
{
block_copy(o_key, key);
block_copy(o_key + 16, key + 16);
}
copy_and_key(s1, in, o_key);
for (r = 1; r < 14; ++r)
#if defined(VERSION_1)
{
mix_sub_columns(s1);
if (r & 1)
add_round_key(s1, o_key + 16);
else
{
update_encrypt_key_256(o_key, &rc);
add_round_key(s1, o_key);
}
}
#else
{
uint8_t s2[N_BLOCK];
mix_sub_columns(s2, s1);
if (r & 1)
copy_and_key(s1, s2, o_key + 16);
else
{
update_encrypt_key_256(o_key, &rc);
copy_and_key(s1, s2, o_key);
}
}
#endif
shift_sub_rows(s1);
update_encrypt_key_256(o_key, &rc);
copy_and_key(out, s1, o_key);
}
#endif
#if defined(AES_DEC_256_OTFK)
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_decrypt_key_256(uint8_t k[2 * N_BLOCK], uint8_t *rc)
{
uint8_t cc;
for (cc = 28; cc > 16; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for (cc = 12; cc > 0; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
}
/* Decrypt a single block of 16 bytes with 'on the fly'
256 bit keying
*/
void aes_decrypt_256(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK])
{
uint8_t s1[N_BLOCK], r, rc = 0x80;
if (o_key != key)
{
block_copy(o_key, key);
block_copy(o_key + 16, key + 16);
}
copy_and_key(s1, in, o_key);
inv_shift_sub_rows(s1);
for (r = 14; --r;)
#if defined(VERSION_1)
{
if ((r & 1))
{
update_decrypt_key_256(o_key, &rc);
add_round_key(s1, o_key + 16);
}
else
add_round_key(s1, o_key);
inv_mix_sub_columns(s1);
}
#else
{
uint8_t s2[N_BLOCK];
if ((r & 1))
{
update_decrypt_key_256(o_key, &rc);
copy_and_key(s2, s1, o_key + 16);
}
else
copy_and_key(s2, s1, o_key);
inv_mix_sub_columns(s1, s2);
}
#endif
copy_and_key(out, s1, o_key);
}
#endif

338
src/clist.c Normal file
View File

@ -0,0 +1,338 @@
/**
* @file clist.c
* @author xxx
* @date 2023-08-08 23:18:09
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "clist.h"
/**
* @brief
* @param {clist_node_t} **ppFirst
* @return void
* @note
*/
void clist_init(clist_node_t **ppFirst)
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
*ppFirst = NULL;
}
/**
* @brief
* @param {clist_node_t} First
* @return void
* @note
*/
void clist_print(clist_node_t *First)
{
LOG_PRINT("list: ");
for (clist_node_t *p = First; p != NULL; p = p->next)
LOG_PRINT("%d-->", p->data);
LOG_PRINT("\n");
}
/**
* @brief
* @param {clist_node_t} First
* @return {uint32_t}
* @note
*/
uint32_t clist_node_count(clist_node_t *First)
{
int32_t count = 0;
for (clist_node_t *p = First; p != NULL; p = p->next)
count++;
return count;
}
/**
* @brief
* @param {cnode} data
* @return {clist_node_t *}
* @note
*/
static clist_node_t *CreateNode(cnode data)
{
clist_node_t *node = (clist_node_t *)osel_mem_alloc(sizeof(clist_node_t));
node->data = data;
node->next = NULL;
return node;
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @param {cnode} data
* @return void
* @note data
*/
void clist_push_back(clist_node_t **ppFirst, cnode data)
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
clist_node_t *node = CreateNode(data);
if (*ppFirst == NULL) // 判断链表不为空
{
*ppFirst = node;
return;
}
// 找链表中的最后一个节点
clist_node_t *p = *ppFirst;
while (p->next != NULL)
p = p->next;
p->next = node; // 插入新申请的节点
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @param {cnode} data
* @return void
* @note data
*/
void clist_push_front(clist_node_t **ppFirst, cnode data)
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
clist_node_t *node = CreateNode(data);
node->next = *ppFirst;
*ppFirst = node;
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @return void
* @note
*/
void clist_pop_back(clist_node_t **ppFirst) // 尾部删除
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
DBG_ASSERT(*ppFirst != NULL __DBG_LINE);
if ((*ppFirst)->next == NULL)
{
osel_mem_free(*ppFirst);
*ppFirst = NULL;
return;
}
clist_node_t *p = *ppFirst;
while (p->next->next != NULL)
p = p->next;
osel_mem_free(p->next);
p->next = NULL;
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @return void
* @note
*/
void clist_pop_front(clist_node_t **ppFirst)
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
DBG_ASSERT(*ppFirst != NULL __DBG_LINE); // 链表不是空链表
clist_node_t *first = *ppFirst;
*ppFirst = (*ppFirst)->next;
osel_mem_free(first);
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @param {clist_node_t} *pPos
* @param {cnode} data
* @return void
* @note data
*/
void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data)
{
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
if (*ppFirst == pPos)
{
clist_push_front(ppFirst, data);
return;
}
clist_node_t *newNode = CreateNode(data);
clist_node_t *p;
for (p = *ppFirst; p->next != pPos; p = p->next)
{
} // 找到pos前的一个节点
p->next = newNode; // 改变的是字段内的值,而不是指针的值
newNode->next = pPos;
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @param {int32_t} Pos
* @param {cnode} data
* @return {int32_t} 10
* @note data
*/
int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data) // 按位置插入
{
clist_node_t *p = *ppFirst;
for (int32_t i = 0; i < Pos; i++)
{
if (p == NULL)
return 0;
p = p->next;
}
clist_insert_for_node(ppFirst, p, data);
return 1;
}
/**
* @brief
* @param {clist_node_t} **ppFirst
* @param {int32_t} Pos
* @return {int32_t} 10
* @note
*/
int32_t cListErase(clist_node_t **ppFirst, int32_t Pos)
{
clist_node_t *p = *ppFirst;
for (int32_t i = 0; i < Pos; i++)
{
if (p == NULL)
return 0;
p = p->next;
}
clist_erase_for_node(ppFirst, p);
return 1;
}
/**
* @brief
* @param {clist_node_t **} ppFirst
* @param {clist_node_t *} pPos
* @return void
* @note
*/
void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos)
{
if (*ppFirst == pPos)
{
clist_pop_front(ppFirst);
return;
}
clist_node_t *p = *ppFirst;
while (p->next != pPos)
p = p->next;
p->next = pPos->next;
osel_mem_free(pPos);
}
/**
* @brief
* @param {clist_node_t **} ppFirst
* @param {cnode} data
* @return void
* @note
*/
void clist_remove(clist_node_t **ppFirst, cnode data)
{
clist_node_t *p = *ppFirst;
clist_node_t *prev = NULL;
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
if (*ppFirst == NULL)
return;
while (p)
{
if (p->data == data)
{
if (*ppFirst == p) // 删除的是第一个节点
{
*ppFirst = p->next;
osel_mem_free(p);
p = NULL;
}
else // 删除中间节点
{
prev->next = p->next;
osel_mem_free(p);
p = NULL;
}
break;
}
prev = p;
p = p->next;
}
}
/**
* @brief
* @param {clist_node_t **} ppFirst
* @param {cnode} data
* @return void
* @note
*/
void clist_remove_all(clist_node_t **ppFirst, cnode data)
{
clist_node_t *p = NULL;
clist_node_t *prev = NULL;
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
if (*ppFirst == NULL)
return;
p = *ppFirst;
while (p)
{
if (p->data == data)
{
if (*ppFirst == p) // 删除的是第一个节点
{
*ppFirst = p->next;
osel_mem_free(p);
p = *ppFirst;
}
else // 删除中间节点
{
prev->next = p->next;
osel_mem_free(p);
p = prev;
}
}
prev = p;
p = p->next;
}
}
/**
* @brief
* @param {clist_node_t **} ppFirst
* @return void
* @note
*/
void clist_destroy(clist_node_t **ppFirst)
{
clist_node_t *p = NULL;
clist_node_t *del = NULL;
DBG_ASSERT(ppFirst != NULL __DBG_LINE);
p = *ppFirst;
while (p)
{
del = p;
p = p->next;
osel_mem_free(del);
del = NULL;
}
*ppFirst = NULL;
}
/**
* @brief NULL
* @param {clist_node_t *} pFirst
* @param {cnode} data
* @return {clist_node_t *} NULL
* @note
*/
clist_node_t *clist_find(clist_node_t *pFirst, cnode data)
{
for (clist_node_t *p = pFirst; p != NULL; p = p->next)
{
if (p->data == data)
return p;
}
return NULL;
}

159
src/cmac.c Normal file
View File

@ -0,0 +1,159 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
// #include <sys/param.h>
// #include <sys/systm.h>
#include <stdint.h>
#include "aes.h"
#include "cmac.h"
#include "osel_arch.h"
#define LSHIFT(v, r) \
do \
{ \
int32_t i; \
for (i = 0; i < 15; i++) \
(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \
(r)[15] = (v)[15] << 1; \
} while (0)
#define XOR(v, r) \
do \
{ \
int32_t i; \
for (i = 0; i < 16; i++) \
{ \
(r)[i] = (r)[i] ^ (v)[i]; \
} \
} while (0)
void AES_CMAC_Init(AES_CMAC_CTX *ctx)
{
osel_memset(ctx->X, 0, sizeof ctx->X);
ctx->M_n = 0;
osel_memset(ctx->rijndael.ksch, '\0', 240);
}
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
{
// rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
aes_set_key(key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
}
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
{
uint32_t mlen;
uint8_t in[16];
if (ctx->M_n > 0)
{
mlen = MIN(16 - ctx->M_n, len);
osel_memcpy(ctx->M_last + ctx->M_n, data, mlen);
ctx->M_n += mlen;
if (ctx->M_n < 16 || len == mlen)
return;
XOR(ctx->M_last, ctx->X);
// rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
aes_encrypt(ctx->X, ctx->X, &ctx->rijndael);
data += mlen;
len -= mlen;
}
while (len > 16) /* not last block */
{
XOR(data, ctx->X);
// rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
osel_memcpy(in, &ctx->X[0], 16); // Bestela ez du ondo iten
aes_encrypt(in, in, &ctx->rijndael);
osel_memcpy(&ctx->X[0], in, 16);
data += 16;
len -= 16;
}
/* potential last block, save it */
osel_memcpy(ctx->M_last, data, len);
ctx->M_n = len;
}
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
{
uint8_t K[16];
uint8_t in[16];
/* generate subkey K1 */
osel_memset(K, '\0', 16);
// rijndael_encrypt(&ctx->rijndael, K, K);
aes_encrypt(K, K, &ctx->rijndael);
if (K[0] & 0x80)
{
LSHIFT(K, K);
K[15] ^= 0x87;
}
else
LSHIFT(K, K);
if (ctx->M_n == 16)
{
/* last block was a complete block */
XOR(K, ctx->M_last);
}
else
{
/* generate subkey K2 */
if (K[0] & 0x80)
{
LSHIFT(K, K);
K[15] ^= 0x87;
}
else
LSHIFT(K, K);
/* padding(M_last) */
ctx->M_last[ctx->M_n] = 0x80;
while (++ctx->M_n < 16)
ctx->M_last[ctx->M_n] = 0;
XOR(K, ctx->M_last);
}
XOR(ctx->M_last, ctx->X);
// rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
osel_memcpy(in, &ctx->X[0], 16); // Bestela ez du ondo iten
aes_encrypt(in, digest, &ctx->rijndael);
osel_memset(K, 0, sizeof K);
}

111
src/cmd.c Normal file
View File

@ -0,0 +1,111 @@
/**
* @file cmd.c
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "cmd.h"
#include <stdio.h>
static cmd_t *_cmd_begin, *_cmd_end;
static int _cmd_to_lower(int c)
{
if ((c >= 'A') && (c <= 'Z'))
return c + ('a' - 'A');
return c;
}
static unsigned int _cmd_hash(const char *str)
{
int tmp, c = *str;
unsigned int seed = CMD_HASH; /* 'jiejie' string hash */
unsigned int hash = 0;
while (*str)
{
tmp = _cmd_to_lower(c);
hash = (hash ^ seed) + tmp;
str++;
c = *str;
}
return hash;
}
static void _cmd_init(const void *begin, const void *end)
{
_cmd_begin = (cmd_t *)begin;
_cmd_end = (cmd_t *)end;
}
static cmd_t *_get_next_cmd(cmd_t *cmd)
{
unsigned int *ptr;
ptr = (unsigned int *)(cmd + 1);
while ((*ptr == 0) && ((unsigned int *)ptr < (unsigned int *)_cmd_end))
ptr++;
return (cmd_t *)ptr;
}
static int _cmd_match(const char *str, const char *cmd)
{
int c1, c2;
do
{
c1 = _cmd_to_lower(*str++);
c2 = _cmd_to_lower(*cmd++);
} while ((c1 == c2) && c1);
return c1 - c2;
}
static void _list(void)
{
cmd_t *index;
for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index))
{
// printf("%s -->%s\n", index->cmd, index->cmd_mess);
}
}
REGISTER_CMD(_list, _list, list all command);
void cmd_init(void)
{
cmd_t *index;
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */
extern const int CMDS$$Base;
extern const int CMDS$$Limit;
_cmd_init(&CMDS$$Base, &CMDS$$Limit);
#elif defined(__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
_cmd_init(__section_begin("CMDS"), __section_end("CMDS"));
#endif
for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index))
{
index->hash = _cmd_hash(index->cmd);
}
}
void cmd_parsing(char *str)
{
cmd_t *index;
unsigned int hash = _cmd_hash(str);
for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index))
{
if (hash == index->hash)
{
if (_cmd_match(str, index->cmd) == 0)
{
index->handler();
break;
}
}
}
}

473
src/data_analysis.c Normal file
View File

@ -0,0 +1,473 @@
/**
* @file data_analysis.c
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include <string.h>
#include "../inc/data_analysis.h"
#include "../inc/sqqueue.h"
#include "../inc/debug.h"
typedef uint8_t data_entry_t;
typedef void (*state_t)(uint8_t data_id, uint8_t sig, uint8_t ch);
typedef enum _event /* enumeration */
{
SD_SIG,
LD_SIG,
CHAR_SIG,
ED_SIG,
} sig_event;
typedef struct _fsm_t_
{
state_t current_state;
} fsm_t;
typedef struct _DATA_frm_t_
{
uint8_t sd_index;
struct
{
uint8_t data[DATA_LD_LEN_MAX];
uint8_t index;
uint16_t frm_len;
} ld; // length describe
uint16_t payload_len; // actually len of recvived data
uint8_t ed_index;
uint16_t last_enter_q_num; // record the num of frames has entered the queue
uint8_t locked;
uint8_t sig;
} data_frm_t;
#define TRAN(state) (fsm[data_id].current_state = (state_t)(state))
#define FSM_DISPATCH(data_id, sig, ch) (fsm[data_id].current_state((data_id), (sig), (ch)))
static fsm_t fsm[DATA_NUM] = {0};
static data_frm_t data_frm_array[DATA_NUM];
static data_reg_t data_reg_array[DATA_NUM];
static sqqueue_ctrl_t data_recv_sqq[DATA_NUM];
static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch);
/**
* @brief
* @param {uint8_t} data_id
* @note
*/
void lock_data(uint8_t data_id)
{
data_frm_array[data_id].locked = TRUE; // 设置数据帧结构体的锁定标志为TRUE
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++) // 遍历数据接收缓冲区,删除所有已入队项
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); // 删除项
}
data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量
data_frm_array[data_id].sd_index = 0; // 重置SD索引
data_frm_array[data_id].ed_index = 0; // 重置ED索引
data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度
data_frm_array[data_id].payload_len = 0; // 重置负载长度
TRAN(wait_sd_state); // 切换到等待SD状态
}
/**
* @brief
* @param {uint8_t} data_id
* @note
*/
void unlock_data(uint8_t data_id)
{
TRAN(wait_sd_state); // 切换到等待SD状态
data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量
data_frm_array[data_id].sd_index = 0; // 重置SD索引
data_frm_array[data_id].ed_index = 0; // 重置ED索引
data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度
data_frm_array[data_id].payload_len = 0; // 重置负载长度
data_frm_array[data_id].locked = FALSE; // 设置数据帧结构体的锁定标志为FALSE
}
/**
* @brief
* @param {uint8_t} data_id
* @param {uint8_t} sig
* @param {uint8_t} ch
* @note
*/
static void end_state_handle(uint8_t data_id, uint8_t sig, uint8_t ch)
{
TRAN(wait_sd_state); // 切换到等待SD状态
data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度
data_frm_array[data_id].payload_len = 0; // 重置负载长度
data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量
if (data_reg_array[data_id].func_ptr != NULL) // 如果数据项注册了处理函数
{
(*(data_reg_array[data_id].func_ptr))(); // 调用处理函数
}
}
/**
* @brief
* @param {uint8_t} data_id - ID
* @param {uint8_t} sig -
* @param {uint8_t} ch -
* @return {*}
* @note
*/
static void wait_end_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
// 如果数据寄存器数组无效
if (!data_reg_array[data_id].ed.valid)
{
// 如果数据帧数组的帧长度为0
if (data_frm_array[data_id].ld.frm_len == 0)
{
// 转换到等待SD状态
TRAN(wait_sd_state);
// 处理结束状态
end_state_handle(data_id, sig, ch);
// 对于数据帧数组的最后一个进入队列的数量,撤销数据接收队列
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
// 将数据帧数组的最后一个进入队列的数量设置为0
data_frm_array[data_id].last_enter_q_num = 0;
}
else
{
// 如果数据接收队列进入成功
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
// 增加数据帧数组的最后一个进入队列的数量
data_frm_array[data_id].last_enter_q_num++;
// 如果增加的数据帧数组的有效载荷长度等于数据帧数组的帧长度
if (++data_frm_array[data_id].payload_len ==
(data_frm_array[data_id].ld.frm_len - data_reg_array[data_id].ld.pos))
{
// 处理结束状态
end_state_handle(data_id, sig, ch);
}
}
else
{
// 锁定数据
lock_data(data_id);
}
}
}
else
{
// 如果数据帧数组的帧长度为0
if (data_frm_array[data_id].ld.frm_len == 0)
{
// 如果数据接收队列进入成功
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
// 增加数据帧数组的最后一个进入队列的数量
data_frm_array[data_id].last_enter_q_num++;
// 如果数据寄存器数组的数据等于通道
if (data_reg_array[data_id].ed.data[0] == ch)
{
// 处理结束状态
end_state_handle(data_id, sig, ch);
}
}
else
{
// 锁定数据
lock_data(data_id);
}
}
else
{
// 如果数据接收队列进入成功
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
// 增加数据帧数组的最后一个进入队列的数量
data_frm_array[data_id].last_enter_q_num++;
// 如果增加的数据帧数组的有效载荷长度大于等于数据帧数组的帧长度减去数据寄存器数组的位置
if (++data_frm_array[data_id].payload_len >=
data_frm_array[data_id].ld.frm_len - data_reg_array[data_id].ld.pos)
{
// 如果数据寄存器数组的数据等于通道
if (data_reg_array[data_id].ed.data[0] == ch)
{
// 处理结束状态
end_state_handle(data_id, sig, ch);
}
}
}
else
{
// 锁定数据
lock_data(data_id);
}
}
}
}
/**
* @brief LD状态
* @param {uint8_t} data_id
* @param {uint8_t} sig
* @param {uint8_t} ch
* @return {*}
* @note
*/
static void wait_ld_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
if (!data_reg_array[data_id].ld.valid) // 如果数据项未注册LD状态
{
TRAN(wait_end_state); // 切换到等待结束状态
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch); // 调用FSM处理函数
return;
}
data_frm_array[data_id].ld.data[data_frm_array[data_id].ld.index++] = ch; // 将字符添加到数据帧中
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) // 尝试进入队列
{
data_frm_array[data_id].last_enter_q_num++; // 增加最后进入队列的项数量
if (data_frm_array[data_id].ld.index == data_reg_array[data_id].ld.len) // 如果索引等于数据项长度
{
if (data_reg_array[data_id].ld.little_endian == TRUE) // 如果小端存储
{
data_frm_array[data_id].ld.frm_len =
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1] * 256 +
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2];
}
else
{
data_frm_array[data_id].ld.frm_len =
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2] * 256 +
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1];
}
if (data_reg_array[data_id].ld.len == 1) // 如果是只有1个字节长度的数据
{
data_frm_array[data_id].ld.frm_len = data_frm_array[data_id].ld.data[0];
}
if ((data_frm_array[data_id].ld.frm_len > data_reg_array[data_id].argu.len_max) || (data_frm_array[data_id].ld.frm_len < data_reg_array[data_id].argu.len_min))
{
data_frm_array[data_id].ld.index = 0;
TRAN(wait_sd_state); // 切换到等待SD状态
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); // 删除项
}
data_frm_array[data_id].ld.frm_len = 0;
data_frm_array[data_id].last_enter_q_num = 0;
}
else
{
data_frm_array[data_id].ld.index = 0;
TRAN(wait_end_state); // 切换到等待结束状态
}
}
}
else
{
lock_data(data_id); // 锁定数据
}
}
/**
* @brief SD状态处理函数
* @param {uint8_t} data_id ID
* @param {uint8_t} sig
* @param {uint8_t} ch
* @return {*}
* @note
*/
static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
// 如果数据寄存器中的SD数据无效
if (!data_reg_array[data_id].sd.valid)
{
// transition to wait_ld_state状态
TRAN(wait_ld_state);
// 调用数据帧数组中对应的数据帧处理函数
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch);
return;
}
// 如果数据寄存器中的SD数据中的当前字节等于输入的字节
if (data_reg_array[data_id].sd.data[data_frm_array[data_id].sd_index++] == ch)
{
// 如果输入字符串成功进入队列
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
// 更新数据帧数组中对应的数据帧的最后一个进入队列的队列号
data_frm_array[data_id].last_enter_q_num++;
// 如果数据帧中的SD数据索引等于数据寄存器中的SD数据长度
if (data_frm_array[data_id].sd_index == data_reg_array[data_id].sd.len)
{
// 更新数据帧中的SD数据索引为0
data_frm_array[data_id].sd_index = 0;
// transition to wait_ld_state状态
TRAN(wait_ld_state);
}
}
// 如果输入字符串无法进入队列
else
{
// 锁定数据
lock_data(data_id);
}
}
// 如果数据寄存器中的SD数据中的当前字节不等于输入的字节
else
{
// 遍历并删除队列中的输入字符串
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
// 更新数据帧中的SD数据索引为0
data_frm_array[data_id].sd_index = 0;
// 更新数据帧中的最后一个进入队列的队列号为0
data_frm_array[data_id].last_enter_q_num = 0;
}
}
/**
* @brief
* @param {uint8_t} data_id
* @param {uint8_t} ch
* @return {*}
* @note
*/
static void data_char_handle(uint8_t data_id, uint8_t ch)
{
// 如果数据ID对应的数据寄存器的回显使能标志为真
if (data_reg_array[data_id].echo_en)
{
// 将输入字符写入数据寄存器
data_write(data_id, &ch, 1);
}
// 调用数据帧数组中对应的数据帧处理函数
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch);
}
/**
* @brief
* @param {uint8_t} data_id
* @return {*}
* @note
*/
data_interupt_cb_t data_fsm_init(uint8_t data_id)
{
TRAN(wait_sd_state); // 切换到等待SD状态
data_reg_array[data_id].func_ptr = NULL; // 设置数据ID寄存器的回调函数为空
memset(&data_frm_array[data_id], 0, sizeof(data_frm_t)); // 初始化数据帧结构体
data_frm_array[data_id].sig = CHAR_SIG; // 设置数据帧签名
if (sqqueue_ctrl_init(&data_recv_sqq[data_id],
sizeof(data_entry_t),
DATA_BUF_RECV_SQQ_LEN) == FALSE) // 初始化数据接收缓冲区
{
DBG_ASSERT(FALSE __DBG_LINE); // 如果初始化失败,输出调试信息
}
return data_char_handle; // 返回数据处理回调函数指针
}
/**
* @brief
* @param {uint8_t} id
* @param {void} *buffer
* @param {uint16_t} len
* @return {*}
* @note
*/
uint8_t data_read(uint8_t id, void *buffer, uint16_t len)
{
uint8_t i = 0;
data_entry_t e;
uint8_t *buf = (uint8_t *)buffer;
// 如果接收队列中存在长度大于等于输入长度的数据项
if (data_recv_sqq[id].get_len(&data_recv_sqq[id]) >= len)
{
// 遍历接收队列并读取数据项到缓冲区
for (i = 0; i < len; i++)
{
e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id]));
buf[i] = e;
}
}
// 如果接收队列中不存在长度大于等于输入长度的数据项
else
{
// 遍历接收队列并读取数据项到缓冲区
while ((data_recv_sqq[id].get_len(&data_recv_sqq[id]) != 0) && (i < len))
{
e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id]));
buf[i++] = e;
}
}
// 如果数据帧数组中对应的数据帧被锁定
if (data_frm_array[id].locked)
{
// 解锁数据
unlock_data(id);
}
return i;
}
/**
* @brief
* @param {uint8_t} id
* @param {uint8_t} *string
* @param {uint16_t} len
* @return {*}
* @note
*/
void data_write(uint8_t id, uint8_t *const string, uint16_t len)
{
}
/**
* @brief
* @param {uint8_t} id
* @param {data_reg_t} reg
* @return {*}
* @note
*/
BOOL data_reg(uint8_t id, data_reg_t reg)
{
if (reg.argu.len_max > DATA_BUF_RECV_SQQ_LEN)
{
return FALSE; // 如果数据寄存器的最大长度大于接收队列的长度返回FALSE
}
if (data_reg_array[id].func_ptr == NULL)
{
memcpy((void *)&data_reg_array[id], (void *)&reg, sizeof(reg));
return TRUE;
}
else
{
return FALSE;
}
}
void data_unreg(uint8_t id)
{
memset((void *)&data_reg_array[id], 0, sizeof(data_reg_t));
data_reg_array[id].func_ptr = NULL;
}

46
src/debug.c Normal file
View File

@ -0,0 +1,46 @@
/*
* @File: debug.c
* @Descripttion:
* @Version: 1.0
* @Author:
* @Date: 2022-12-10 20:15:01
* @LastEditors: xxx
* @LastEditTime: 2023-08-08 14:39:18
*/
#include "../inc/debug.h"
#ifndef STM32
BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_)
{
do
{
if ((cond) == FALSE)
{
LOG_ERR("DBG_ASSERT:%d", line);
return FALSE;
}
} while (__LINE__ == -1);
return TRUE;
}
#else
#include "board.h"
#include "sys.h"
#include "leds.h"
BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_)
{
do
{
if ((cond) == FALSE)
{
dbg_assert_cb(line);
leds_on(LEDS_ORANGE);
while (1)
{
LOG_ERR("DBG_ASSERT:%d", line);
}
}
} while (__LINE__ == -1);
return TRUE;
}
#endif

156
src/filter.c Normal file
View File

@ -0,0 +1,156 @@
#include "filter.h"
#include <math.h>
#include "osel_arch.h"
/**
* @brief
*
*
*
* @param cfg
* @param change_max
*/
void kalman_init(kalman_t *cfg, float32 change_max)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 初始化卡尔曼滤波器配置
cfg->x = 0; // 初始状态估计值
cfg->p = 5; // 初始估计误差协方差
cfg->a = 1; // 状态转移矩阵
cfg->h = 1; // 观测矩阵
cfg->q = 0.25; // 过程噪声协方差
cfg->r = 1; // 观测噪声协方差
cfg->change_max = change_max; // 最大变化值
}
/**
* @brief
*
*
*
* @param cfg
* @param input
*
* @return
*/
float32 kalman_update(kalman_t *cfg, float32 input)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 计算变化值
float32 delta = input - cfg->x;
// 如果变化值超过0.5,直接返回输入值
if (ABS(delta) > cfg->change_max)
{
cfg->x = input;
return cfg->x;
}
cfg->x = cfg->a * cfg->x;
cfg->p = cfg->a * cfg->a * cfg->p + cfg->q;
cfg->gain = cfg->p * cfg->h / (cfg->p * cfg->h * cfg->h + cfg->r);
cfg->x = cfg->x + cfg->gain * (input - cfg->h * cfg->x);
cfg->p = (1 - cfg->gain * cfg->h) * cfg->p;
return cfg->x;
}
// 一阶滞后滤波法
void lpf_init(lpf_t *cfg)
{
cfg->fisrt_flag = TRUE;
cfg->last_value = 0;
if (cfg->alpha <= 0 || cfg->alpha > 1)
{
cfg->alpha = 0.3f;
}
}
float32 lpf_update(lpf_t *cfg, float32 input)
{
float32 out;
/***************** 如果第一次进入,则给 out_last 赋值 ******************/
if (TRUE == cfg->fisrt_flag)
{
cfg->fisrt_flag = FALSE;
cfg->last_value = input;
}
/*************************** 一阶滤波 *********************************/
out = cfg->alpha * input + (1 - cfg->alpha) * cfg->last_value;
cfg->last_value = out;
return out;
}
void lpf_reset(lpf_t *cfg)
{
cfg->fisrt_flag = TRUE;
}
/**
*
*/
void lpf_window_init(lpf_window_t *cfg, uint16_t size)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
if (cfg->window != NULL)
{
osel_mem_free(cfg->window);
}
osel_memset((uint8_t *)cfg, 0, sizeof(lpf_window_t));
cfg->size = size;
cfg->window = (float32 *)osel_mem_alloc(sizeof(float32) * size);
DBG_ASSERT(cfg->window != NULL __DBG_LINE);
cfg->index = 0;
cfg->sum = 0;
}
void lpf_window_dinit(lpf_window_t *cfg)
{
if (cfg != NULL)
{
if (cfg->window != NULL)
{
osel_mem_free(cfg->window);
}
osel_mem_free(cfg);
}
}
// 滑动平均窗口重置
void lpf_window_reset(lpf_window_t *cfg)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
cfg->index = 0;
cfg->sum = 0;
osel_memset((uint8_t *)cfg->window, 0, sizeof(float32) * cfg->size);
}
float32 lpf_window_update(lpf_window_t *cfg, float32 input)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
cfg->sum = 0;
// 如果窗口未满,直接添加新值到当前索引位置
if (cfg->index < cfg->size)
{
cfg->window[cfg->index++] = input;
}
else
{
// 如果窗口已满,替换最旧的值
for (uint16_t i = 0; i < cfg->size - 1; i++)
{
cfg->window[i] = cfg->window[i + 1];
}
cfg->window[cfg->size - 1] = input;
}
// 计算窗口中所有值的和
for (uint16_t i = 0; i < cfg->index; i++)
{
cfg->sum += cfg->window[i];
}
// 计算平均值
cfg->out = cfg->sum / cfg->index;
return cfg->out;
}

743
src/lib.c Normal file
View File

@ -0,0 +1,743 @@
/*
* @Author:
* @day: 2023-04-11 08:21:19
* @LastEditors: xxx
* @LastEditTime: 2023-08-15 10:14:58
* @Description:
* email:
* Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "../inc/lib.h"
#include <stdio.h>
#include <string.h>
#include "math.h"
#include "cmac.h"
const uint8_t _days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const uint16_t _month_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
static uint32_t crc32_table[256]; // CRC32表
// ASSIC码数组转字符串
void assic_to_str(uint8_t *assic, uint8_t len, uint8_t *str)
{
for (uint8_t i = 0; i < len; i++)
{
if (assic[i] == 0)
{
str[i] = 48;
}
else
{
str[i] = (char)assic[i];
}
}
}
// 每隔三位数加逗号将数字转为每隔3位整数由逗号“,”分隔的字符串
void add_commas(uint32_t num, char *result)
{
char temp[64];
sprintf(temp, "%d", num);
int32_t len = strlen(temp);
int32_t commas = (len - 1) / 3;
int32_t index = 0;
int32_t resultIndex = 0;
for (int32_t i = len - 1; i >= 0; i--)
{
result[resultIndex++] = temp[i];
index++;
if (index % 3 == 0 && commas > 0)
{
result[resultIndex++] = ',';
commas--;
}
}
result[resultIndex] = '\0';
// Reverse the result string
int32_t start = 0;
int32_t end = resultIndex - 1;
while (start < end)
{
char temp = result[start];
result[start] = result[end];
result[end] = temp;
start++;
end--;
}
}
void get_cpu_id(uint8_t *id)
{
#ifdef STM32
uint32_t uid[3];
// 获取CPU唯一的ID
uid[0] = *(uint32_t *)(UID_BASE);
uid[1] = *(uint32_t *)(UID_BASE + 4);
uid[2] = *(uint32_t *)(UID_BASE + 8);
id[0] = (uid[0] >> 0) & 0xFF;
id[1] = (uid[0] >> 8) & 0xFF;
id[2] = (uid[0] >> 16) & 0xFF;
id[3] = (uid[0] >> 24) & 0xFF;
id[4] = (uid[1] >> 0) & 0xFF;
id[5] = (uid[1] >> 8) & 0xFF;
id[6] = (uid[1] >> 16) & 0xFF;
id[7] = (uid[1] >> 24) & 0xFF;
id[8] = (uid[2] >> 0) & 0xFF;
id[9] = (uid[2] >> 8) & 0xFF;
id[10] = (uid[2] >> 16) & 0xFF;
id[11] = (uid[2] >> 24) & 0xFF;
id[12] = 0;
id[13] = 0;
id[14] = 0;
id[15] = 0;
#endif
}
void get_cpu_id_32(uint32_t *id)
{
#ifdef STM32
id[0] = *(uint32_t *)(UID_BASE);
id[1] = *(uint32_t *)(UID_BASE + 4);
id[2] = *(uint32_t *)(UID_BASE + 8);
#endif
}
uint32_t cpu_encrypt(void)
{
uint32_t cpuid[3];
#ifdef STM32
// 获取CPU唯一的ID
cpuid[0] = *(uint32_t *)(UID_BASE);
cpuid[1] = *(uint32_t *)(UID_BASE + 4);
cpuid[2] = *(uint32_t *)(UID_BASE + 8);
#endif
// 加密算法,很简单的加密算法
uint32_t encrypt_code = (cpuid[0] >> 3) + (cpuid[1] >> 1) + (cpuid[2] >> 2);
return encrypt_code;
}
// 判断加密
BOOL cpu_judge_encrypt(uint32_t cupid_encrypt)
{
uint32_t cpuid[4];
#ifdef STM32
// 获取CPU唯一的ID
cpuid[0] = *(uint32_t *)(UID_BASE);
cpuid[1] = *(uint32_t *)(UID_BASE + 4);
cpuid[2] = *(uint32_t *)(UID_BASE + 8);
#endif
// 加密算法,很简单的加密算法
cpuid[3] = (cpuid[0] >> 3) + (cpuid[1] >> 1) + (cpuid[2] >> 2);
// 检查Flash中的UID是否合法
return (cupid_encrypt == cpuid[3]);
}
void convert_seconds(uint32_t total_seconds, char *date)
{
uint32_t days = total_seconds / 86400;
uint32_t hours = (total_seconds % 86400) / 3600;
uint32_t minutes = (total_seconds % 3600) / 60;
uint32_t seconds = total_seconds % 60;
if (days > 0)
{
if (days > 1000)
{
sprintf(date, "%02d d %02d h", days, hours);
}
else
{
sprintf(date, "%02d d %02d h %02d m", days, hours, minutes);
}
}
else if (hours > 0)
{
sprintf(date, "%02d h %02d m %02d s", hours, minutes, seconds);
}
else if (minutes > 0)
{
sprintf(date, "%02d m %02d s", minutes, seconds);
}
else
{
sprintf(date, "%02d s", seconds);
}
}
/**
* @brief Generate the CRC32 lookup table.
*
* This function generates the CRC32 lookup table used for fast computation of the
* CRC32 checksum. The table is generated using the polynomial 0xEDB88320, which is a
* common polynomial used in CRC32 calculations.
*/
static void generate_crc32_table()
{
static BOOL is_init = FALSE;
if (is_init)
{
return;
}
uint32_t polynomial = 0xEDB88320;
for (uint32_t i = 0; i < 256; i++)
{
uint32_t crc = i;
for (uint32_t j = 0; j < 8; j++)
{
crc = (crc & 1) ? (crc >> 1) ^ polynomial : crc >> 1;
}
crc32_table[i] = crc;
}
is_init = TRUE;
}
/**
* @brief 1.010
* @param {uint8_t} *version_str
* @param {uint8_t} *hi
* @param {uint8_t} *lo
* @return {*}
*/
void version_split(uint8_t *version_str, uint8_t *hi, uint8_t *lo)
{
uint8_t flag = 1;
for (uint8_t i = 0; version_str[i] != '\0'; i++)
{
if (version_str[i] == '.')
{
flag = 0;
continue;
}
if (flag)
{
*hi = *hi * 10 + (version_str[i] - '0');
}
else
{
*lo = *lo * 10 + (version_str[i] - '0');
}
}
}
// 反序数组
void reverse(uint8_t *buf, uint16_t len)
{
uint8_t tmp;
uint16_t i;
for (i = 0; i < len / 2; i++)
{
tmp = buf[i];
buf[i] = buf[len - i - 1];
buf[len - i - 1] = tmp;
}
}
/***
* @brief
* @param {uint8_t} *arr
* @param {uint8_t} len
* @param {uint8_t} val
* @return {*} TRUE:
*/
BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val)
{
uint16_t i;
for (i = 0; i < len; i++)
{
if (arr[i] == val)
{
return TRUE;
}
}
return FALSE;
}
/**
* crc的值
*
* @param data:
* @param length:
*
* @return crc计算的结果
*/
uint16_t crc16_compute(const uint8_t *const data, uint16_t length)
{
uint16_t crcVal = 0xffff;
const uint8_t *ptr = data;
for (uint16_t i = 0; i < length; i++)
{
crcVal ^= (uint16_t)*ptr++;
for (uint8_t j = 0; j < 8; j++)
{
if (crcVal & 0x0001)
{
crcVal = (crcVal >> 1) ^ 0x8401;
}
else
{
crcVal >>= 1;
}
}
}
return crcVal;
}
/**
* @brief Calculate the CRC32 value of a data buffer.
*
* This function calculates the CRC32 value of a data buffer using the lookup table method.
* The lookup table is generated using the polynomial 0xEDB88320, which is a common polynomial used in CRC32 calculations.
*
* @param data The data buffer to calculate the CRC32 value of.
* @param length The length of the data buffer in bytes.
* @return The CRC32 value of the data buffer.
*/
uint32_t crc32_compute(const uint8_t *const data, uint16_t length)
{
generate_crc32_table();
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < length; i++)
{
crc = (crc >> 8) ^ crc32_table[(crc ^ data[i]) & 0xFF];
}
return ~crc;
}
/**
* @brief 64 CRC
*
* 使 AES-CMAC CRC32 64 CRC
* 使heap设置0x800
*
* @param data
* @param length
*
* @return 64 CRC
*/
uint64_t crc64_compute(const uint8_t *const data, const uint16_t length)
{
uint8_t cmac_key[] = {
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥
uint8_t dst[4];
uint8_t mic[16];
uint8_t *p;
uint32_t lo = 0, hi = 0;
AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表
AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化
AES_CMAC_SetKey(AesCmacCtx, cmac_key); // 完成密钥扩展表数据 // 存放生成校验数据的数组
AES_CMAC_Update(AesCmacCtx, data, length & 0xFF); // 完成数据的奇偶校验
AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表
uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码
p = (uint8_t *)&xor_vol;
osel_memcpy(dst, p, 4);
lo = (uint32_t)dst[0] << 24 | (uint32_t)dst[1] << 16 | (uint32_t)dst[2] << 8 | (uint32_t)dst[3];
hi = crc32_compute(data, length);
return ((uint64_t)hi << 32) | lo;
}
/**
*
*
* @param data:
* @param length:
*
* @return
*/
uint8_t xor_compute(const uint8_t *const data, uint16_t length)
{
uint16_t i;
const uint8_t *ptr = data;
uint8_t xor = 0;
for (i = 0; i < length; i++)
{
xor ^= *ptr;
ptr++;
}
return xor;
}
// 通过bit位获取置1个数量
uint8_t get_bit_num(uint8_t bit)
{
uint8_t num = 0;
while (bit)
{
if (bit & 0x01)
{
num++;
}
bit >>= 1;
}
return num;
}
// 通过bit位获取置1的位置
BOOL is_bit_set(int32_t x, int32_t k)
{
int32_t mask = 1 << k;
return (x & mask) != 0;
}
// 判断数组是否全是同一个值
BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value)
{
uint16_t i;
for (i = 0; i < len; i++)
{
if (buf[i] != value)
{
return FALSE;
}
}
return TRUE;
}
// 检查是否是闰年
uint8_t is_leap_year(uint16_t year)
{
return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);
}
// 检查日期是否合法
BOOL is_valid_date(uint8_t year, uint8_t month, uint8_t day)
{
if (year < 1 || month < 1 || month > 12 || day < 1)
{
return false;
}
uint8_t days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 如果是闰年2月有29天
if (is_leap_year(year))
{
days_in_month[1] = 29;
}
return day <= days_in_month[month - 1];
}
// 检查时间是否合法
BOOL is_valid_time(uint8_t hour, uint8_t minute, uint8_t second)
{
return (hour < 24) &&
(minute < 60) &&
(second < 60);
}
// 检查日期和时间是否合法
BOOL is_valid_datetime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
{
return is_valid_date(year, month, day) && is_valid_time(hour, minute, second);
}
// 计算从1970年1月1日到给定年月日的天数
uint32_t days_since_1970(uint16_t year, uint8_t month, uint8_t day)
{
static const uint8_t month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint32_t days = 0;
uint16_t y = 1970;
// 计算整年过去的天数
while (y < year)
{
days += is_leap_year(y) ? 366 : 365;
y++;
}
// 计算当前年份中过去的天数
for (int32_t m = 0; m < month - 1; m++)
{
days += month_days[m];
if (m == 1 && is_leap_year(year))
{ // 如果是2月且是闰年多加一天
days++;
}
}
// 加上当前月的天数
days += day - 1; // 因为day是从1开始的而我们需要的是从0开始的偏移量
return days;
}
// 将日期转换为秒数
uint32_t date_to_seconds(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
{
uint32_t secs = 0;
uint32_t days = days_since_1970(year, month, day);
secs = days * 24 * 60 * 60; // 一天有24小时每小时有60分钟每分钟有60秒
secs += hour * 60 * 60 + minute * 60 + second;
return secs;
}
// 函数用于将秒数转换为日期和时间,年份4位
void seconds_to_date(uint32_t total_seconds, rtc_date_t *date, rtc_time_t *time)
{
uint16_t year = 1970; // Unix时间戳的起始年份
uint8_t month = 1;
uint8_t day = 1;
uint32_t seconds = total_seconds;
uint8_t hours, minutes, secs;
// 正确处理小时、分钟和秒
hours = (seconds / 3600) % 24;
minutes = (seconds / 60) % 60;
secs = seconds % 60;
// 计算日期
uint32_t days = total_seconds / (24 * 3600);
seconds = total_seconds % (24 * 3600); // 更新seconds为剩余秒数
for (; days > 0; days--)
{
// 当前月份的天数
uint8_t days_in_month = 31;
if (month == 2)
{
days_in_month = is_leap_year(year) ? 29 : 28;
}
else if (month == 4 || month == 6 || month == 9 || month == 11)
{
days_in_month = 30;
}
if (++day > days_in_month)
{
day = 1;
if (++month > 12)
{
month = 1;
year++;
}
}
}
// 将结果存储到结构体中
date->year = year;
date->month = month;
date->day = day;
time->hour = hours;
time->minute = minutes;
time->second = secs;
}
// 计算一年中的第几天
uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day)
{
uint8_t month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint16_t total;
total = day;
if (month > 2 && is_leap_year(year))
total += 1;
for (uint8_t i = 0; i < month - 1; i++)
{
total += month_days[i];
}
return total;
}
// 计算一年中的第几周
uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day)
{
uint16_t day_of_year = dayOfyear(year, month, day);
return (day_of_year - 1) / 7 + 1;
}
// 获取今天星期几
uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day)
{
uint8_t w = 0;
if (month == 1 || month == 2)
{
month += 12;
year--;
}
w = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7;
return w + 1;
}
// 传入十六进制0x23 返回十进制23
uint8_t hex_format_dec(uint8_t hex)
{
char buf[4];
osel_memset((uint8_t *)buf, 0, 4);
sprintf(buf, "%x", hex);
int32_t dec = 0;
int32_t weight = 1;
int32_t len = strlen(buf);
for (int32_t i = len - 1; i >= 0; i--)
{
if (buf[i] >= '0' && buf[i] <= '9')
{
dec += (buf[i] - '0') * weight;
}
else if (buf[i] >= 'A' && buf[i] <= 'F')
{
dec += (buf[i] - 'A' + 10) * weight;
}
else if (buf[i] >= 'a' && buf[i] <= 'f')
{
dec += (buf[i] - 'a' + 10) * weight;
}
weight *= 10;
}
return dec;
}
// 传入十进制23 返回十六进制0x23
uint8_t dec_format_hex(uint8_t dec)
{
char buf[4];
osel_memset((uint8_t *)buf, 0, 4);
sprintf(buf, "%d", dec);
uint8_t hex = 0;
uint8_t len = strlen(buf);
for (uint8_t i = 0; i < len; i++)
{
char c = buf[i];
if (c >= '0' && c <= '9')
{
hex = hex * 16 + (c - '0');
}
else
{
continue;
}
}
return hex;
}
/**
* @brief
* @param {rtc_date_t} date
* @param {rtc_time_t} time
* @return {*}
* @note 2000
*/
uint32_t time2stamp(const rtc_date_t *const date, const rtc_time_t *const time)
{
uint32_t result;
uint16_t year = date->year + 2000;
// (time->hour - 0) * 3600 中的0改成8是北京时间的时区
result = (year - 1970) * 365 * 24 * 3600 + (_month_days[date->month - 1] + date->day - 1) * 24 * 3600 + (time->hour - 0) * 3600 + time->minute * 60 + time->second;
result += (date->month > 2 && (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) * 24 * 3600; // 闰月
year -= 1969;
result += (year / 4 - year / 100 + year / 400) * 24 * 3600; // 闰年
return result;
}
/**
* @brief
* @param {uint32_t} stamp
* @param {rtc_date_t} *date
* @param {rtc_time_t} *time
* @return {*}
* @note
*/
void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time)
{
uint32_t days;
uint16_t leap_num;
time->second = stamp % 60;
stamp /= 60; // 获取分
time->minute = stamp % 60;
// stamp += 8 * 60; // 不需要加8小时
stamp /= 60; // 获取小时
time->hour = stamp % 24;
days = stamp / 24;
leap_num = (days + 365) / 1461;
if (((days + 366) % 1461) == 0)
{
date->year = (days / 366) + 1970 - 2000;
date->month = 12;
date->day = 31;
}
else
{
days -= leap_num;
date->year = (days / 365) + 1970 - 2000;
days %= 365;
days += 1;
if (((date->year % 4) == 0) && (days == 60))
{
date->month = 2;
date->day = 29;
}
else
{
if (((date->year % 4) == 0) && (days > 60))
--days;
for (date->month = 0; _days[date->month] < days; date->month++)
{
days -= _days[date->month];
}
++date->month;
date->day = days;
}
}
}
/**************************排序**************************/
static void swap(uint16_t *a, uint16_t *b)
{
uint16_t t = *a;
*a = *b;
*b = t;
}
static int32_t partition(uint16_t arr[], int32_t low, int32_t high)
{
uint16_t pivot = arr[high];
int32_t i = (low - 1);
for (int32_t j = low; j <= high - 1; j++)
{
if (arr[j] < pivot)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
// 快速排序
void quicksort(uint16_t arr[], int32_t low, int32_t high)
{
if (low < high)
{
int32_t pi = partition(arr, low, high);
quicksort(arr, low, pi - 1);
quicksort(arr, pi + 1, high);
}
}
// 插入排序 数据集小的时候效率高
void insertion_sort(uint16_t arr[], uint16_t n)
{
uint16_t i, j;
uint16_t key;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i;
// 将大于key的元素向后移动一个位置
while (j > 0 && arr[j - 1] > key)
{
arr[j] = arr[j - 1];
j = j - 1;
}
arr[j] = key;
}
}

760
src/lwrb.c Normal file
View File

@ -0,0 +1,760 @@
/**
* @file lwrb.c
* \brief Lightweight ring buffer
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v3.2.0
*/
#include "../inc/lwrb.h"
/* Memory set and copy functions */
#define BUF_MEMSET osel_memset
#define BUF_MEMCPY osel_memcpy
#define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0)
#define BUF_MIN(x, y) ((x) < (y) ? (x) : (y))
#define BUF_MAX(x, y) ((x) > (y) ? (x) : (y))
#define BUF_SEND_EVT(b, type, bp) \
do \
{ \
if ((b)->evt_fn != NULL) \
{ \
(b)->evt_fn((void *)(b), (type), (bp)); \
} \
} while (0)
/* Optional atomic opeartions */
#ifndef LWRB_DISABLE_ATOMIC
#define LWRB_INIT(var, val) (var) = (val)
#define LWRB_LOAD(var, type) (var)
#define LWRB_STORE(var, val, type) (var) = (val)
#else
#define LWRB_INIT(var, val) atomic_init(&(var), (val))
#define LWRB_LOAD(var, type) atomic_load_explicit(&(var), (type))
#define LWRB_STORE(var, val, type) atomic_store_explicit(&(var), (val), (type))
#endif
/**
* \brief Initialize buffer handle to default values with size and buffer data array
* \param[in] buff: Ring buffer instance
* \param[in] buffdata: Pointer to memory to use as buffer data
* \param[in] size: Size of `buffdata` in units of bytes
* Maximum number of bytes buffer can hold is `size - 1`
* \return `1` on success, `0` otherwise
*/
uint8_t
lwrb_init(lwrb_t *buff, void *buffdata, lwrb_sz_t size)
{
if (buff == NULL || buffdata == NULL || size == 0)
{
return 0;
}
buff->evt_fn = NULL;
buff->size = size;
buff->buff = buffdata;
LWRB_INIT(buff->w_ptr, 0);
LWRB_INIT(buff->r_ptr, 0);
return 1;
}
/**
* \brief Check if buff is initialized and ready to use
* \param[in] buff: Ring buffer instance
* \return `1` if ready, `0` otherwise
*/
uint8_t
lwrb_is_ready(lwrb_t *buff)
{
return BUF_IS_VALID(buff);
}
/**
* \brief Free buffer memory
* \note Since implementation does not use dynamic allocation,
* it just sets buffer handle to `NULL`
* \param[in] buff: Ring buffer instance
*/
void lwrb_free(lwrb_t *buff)
{
if (BUF_IS_VALID(buff))
{
buff->buff = NULL;
}
}
/**
* \brief Set event function callback for different buffer operations
* \param[in] buff: Ring buffer instance
* \param[in] evt_fn: Callback function
*/
void lwrb_set_evt_fn(lwrb_t *buff, lwrb_evt_fn evt_fn)
{
if (BUF_IS_VALID(buff))
{
buff->evt_fn = evt_fn;
}
}
/**
* \brief Set custom buffer argument, that can be retrieved in the event function
* \param[in] buff: Ring buffer instance
* \param[in] arg: Custom user argument
*/
void lwrb_set_arg(lwrb_t *buff, void *arg)
{
if (BUF_IS_VALID(buff))
{
buff->arg = arg;
}
}
/**
* \brief Get custom buffer argument, previously set with \ref lwrb_set_arg
* \param[in] buff: Ring buffer instance
* \return User argument, previously set with \ref lwrb_set_arg
*/
void *
lwrb_get_arg(lwrb_t *buff)
{
return buff != NULL ? buff->arg : NULL;
}
/**
* \brief Write data to buffer.
* Copies data from `data` array to buffer and advances the write pointer for a maximum of `btw` number of bytes.
*
* It copies less if there is less memory available in the buffer.
* User must check the return value of the function and compare it to
* the requested write length, to determine if everything has been written
*
* \note Use \ref lwrb_write_ex for more advanced usage
*
* \param[in] buff: Ring buffer instance
* \param[in] data: Pointer to data to write into buffer
* \param[in] btw: Number of bytes to write
* \return Number of bytes written to buffer.
* When returned value is less than `btw`, there was no enough memory available
* to copy full data array.
*/
lwrb_sz_t
lwrb_write(lwrb_t *buff, const void *data, lwrb_sz_t btw)
{
lwrb_sz_t written = 0;
if (lwrb_write_ex(buff, data, btw, &written, 0))
{
return written;
}
return 0;
}
/**
* \brief Write extended functionality
*
* \param buff: Ring buffer instance
* \param data: Pointer to data to write into buffer
* \param btw: Number of bytes to write
* \param bwritten: Output pointer to write number of bytes written into the buffer
* \param flags: Optional flags.
* \ref LWRB_FLAG_WRITE_ALL: Request to write all data (up to btw).
* Will early return if no memory available
* \return `1` if write operation OK, `0` otherwise
*/
uint8_t
lwrb_write_ex(lwrb_t *buff, const void *data, lwrb_sz_t btw, lwrb_sz_t *bwritten, uint16_t flags)
{
lwrb_sz_t tocopy = 0, free = 0, w_ptr = 0;
const uint8_t *d_ptr = data;
if (!BUF_IS_VALID(buff) || data == NULL || btw == 0)
{
return 0;
}
/* Calculate maximum number of bytes available to write */
free = lwrb_get_free(buff);
/* If no memory, or if user wants to write ALL data but no enough space, exit early */
if (free == 0 || (free < btw && (flags & LWRB_FLAG_WRITE_ALL)))
{
return 0;
}
btw = BUF_MIN(free, btw);
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_acquire);
/* Step 1: Write data to linear part of buffer */
tocopy = BUF_MIN(buff->size - w_ptr, btw);
BUF_MEMCPY(&buff->buff[w_ptr], d_ptr, tocopy);
d_ptr += tocopy;
w_ptr += tocopy;
btw -= tocopy;
/* Step 2: Write data to beginning of buffer (overflow part) */
if (btw > 0)
{
BUF_MEMCPY(buff->buff, d_ptr, btw);
w_ptr = btw;
}
/* Step 3: Check end of buffer */
if (w_ptr >= buff->size)
{
w_ptr = 0;
}
/*
* Write final value to the actual running variable.
* This is to ensure no read operation can access intermediate data
*/
LWRB_STORE(buff->w_ptr, w_ptr, memory_order_release);
BUF_SEND_EVT(buff, LWRB_EVT_WRITE, tocopy + btw);
if (bwritten != NULL)
{
*bwritten = tocopy + btw;
}
return 1;
}
/**
* \brief Read data from buffer.
* Copies data from `data` array to buffer and advances the read pointer for a maximum of `btr` number of bytes.
*
* It copies less if there is less data available in the buffer.
*
* \note Use \ref lwrb_read_ex for more advanced usage
*
* \param[in] buff: Ring buffer instance
* \param[out] data: Pointer to output memory to copy buffer data to
* \param[in] btr: Number of bytes to read
* \return Number of bytes read and copied to data array
*/
lwrb_sz_t
lwrb_read(lwrb_t *buff, void *data, lwrb_sz_t btr)
{
lwrb_sz_t read = 0;
if (lwrb_read_ex(buff, data, btr, &read, 0))
{
return read;
}
return 0;
}
/**
* \brief Read extended functionality
*
* \param buff: Ring buffer instance
* \param data: Pointer to memory to write read data from buffer
* \param btr: Number of bytes to read
* \param bread: Output pointer to write number of bytes read from buffer and written to the
* output `data` variable
* \param flags: Optional flags
* \ref LWRB_FLAG_READ_ALL: Request to read all data (up to btr).
* Will early return if no enough bytes in the buffer
* \return `1` if read operation OK, `0` otherwise
*/
uint8_t
lwrb_read_ex(lwrb_t *buff, void *data, lwrb_sz_t btr, lwrb_sz_t *bread, uint16_t flags)
{
lwrb_sz_t tocopy = 0, full = 0, r_ptr = 0;
uint8_t *d_ptr = data;
if (!BUF_IS_VALID(buff) || data == NULL || btr == 0)
{
return 0;
}
/* Calculate maximum number of bytes available to read */
full = lwrb_get_full(buff);
if (full == 0 || (full < btr && (flags & LWRB_FLAG_READ_ALL)))
{
return 0;
}
btr = BUF_MIN(full, btr);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_acquire);
/* Step 1: Read data from linear part of buffer */
tocopy = BUF_MIN(buff->size - r_ptr, btr);
BUF_MEMCPY(d_ptr, &buff->buff[r_ptr], tocopy);
d_ptr += tocopy;
r_ptr += tocopy;
btr -= tocopy;
/* Step 2: Read data from beginning of buffer (overflow part) */
if (btr > 0)
{
BUF_MEMCPY(d_ptr, buff->buff, btr);
r_ptr = btr;
}
/* Step 3: Check end of buffer */
if (r_ptr >= buff->size)
{
r_ptr = 0;
}
/*
* Write final value to the actual running variable.
* This is to ensure no write operation can access intermediate data
*/
LWRB_STORE(buff->r_ptr, r_ptr, memory_order_release);
BUF_SEND_EVT(buff, LWRB_EVT_READ, tocopy + btr);
if (bread != NULL)
{
*bread = tocopy + btr;
}
return 1;
}
/**
* \brief Read from buffer without changing read pointer (peek only)
* \param[in] buff: Ring buffer instance
* \param[in] skip_count: Number of bytes to skip before reading data
* \param[out] data: Pointer to output memory to copy buffer data to
* \param[in] btp: Number of bytes to peek
* \return Number of bytes peeked and written to output array
*/
lwrb_sz_t
lwrb_peek(const lwrb_t *buff, lwrb_sz_t skip_count, void *data, lwrb_sz_t btp)
{
lwrb_sz_t full = 0, tocopy = 0, r_ptr = 0;
uint8_t *d_ptr = data;
if (!BUF_IS_VALID(buff) || data == NULL || btp == 0)
{
return 0;
}
/*
* Calculate maximum number of bytes available to read
* and check if we can even fit to it
*/
full = lwrb_get_full(buff);
if (skip_count >= full)
{
return 0;
}
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
r_ptr += skip_count;
full -= skip_count;
if (r_ptr >= buff->size)
{
r_ptr -= buff->size;
}
/* Check maximum number of bytes available to read after skip */
btp = BUF_MIN(full, btp);
if (btp == 0)
{
return 0;
}
/* Step 1: Read data from linear part of buffer */
tocopy = BUF_MIN(buff->size - r_ptr, btp);
BUF_MEMCPY(d_ptr, &buff->buff[r_ptr], tocopy);
d_ptr += tocopy;
btp -= tocopy;
/* Step 2: Read data from beginning of buffer (overflow part) */
if (btp > 0)
{
BUF_MEMCPY(d_ptr, buff->buff, btp);
}
return tocopy + btp;
}
/**
* \brief Get available size in buffer for write operation
* \param[in] buff: Ring buffer instance
* \return Number of free bytes in memory
*/
lwrb_sz_t
lwrb_get_free(const lwrb_t *buff)
{
lwrb_sz_t size = 0, w_ptr = 0, r_ptr = 0;
if (!BUF_IS_VALID(buff))
{
return 0;
}
/*
* Copy buffer pointers to local variables with atomic access.
*
* To ensure thread safety (only when in single-entry, single-exit FIFO mode use case),
* it is important to write buffer r and w values to local w and r variables.
*
* Local variables will ensure below if statements will always use the same value,
* even if buff->w or buff->r get changed during interrupt processing.
*
* They may change during load operation, important is that
* they do not change during if-else operations following these assignments.
*
* lwrb_get_free is only called for write purpose, and when in FIFO mode, then:
* - buff->w pointer will not change by another process/interrupt because we are in write mode just now
* - buff->r pointer may change by another process. If it gets changed after buff->r has been loaded to local variable,
* buffer will see "free size" less than it actually is. This is not a problem, application can
* always try again to write more data to remaining free memory that was read just during copy operation
*/
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_relaxed);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
if (w_ptr >= r_ptr)
{
size = buff->size - (w_ptr - r_ptr);
}
else
{
size = r_ptr - w_ptr;
}
/* Buffer free size is always 1 less than actual size */
return size - 1;
}
/**
* \brief Get number of bytes currently available in buffer
* \param[in] buff: Ring buffer instance
* \return Number of bytes ready to be read
*/
lwrb_sz_t
lwrb_get_full(const lwrb_t *buff)
{
lwrb_sz_t size = 0, w_ptr = 0, r_ptr = 0;
if (!BUF_IS_VALID(buff))
{
return 0;
}
/*
* Copy buffer pointers to local variables.
*
* To ensure thread safety (only when in single-entry, single-exit FIFO mode use case),
* it is important to write buffer r and w values to local w and r variables.
*
* Local variables will ensure below if statements will always use the same value,
* even if buff->w or buff->r get changed during interrupt processing.
*
* They may change during load operation, important is that
* they do not change during if-else operations following these assignments.
*
* lwrb_get_full is only called for read purpose, and when in FIFO mode, then:
* - buff->r pointer will not change by another process/interrupt because we are in read mode just now
* - buff->w pointer may change by another process. If it gets changed after buff->w has been loaded to local variable,
* buffer will see "full size" less than it really is. This is not a problem, application can
* always try again to read more data from remaining full memory that was written just during copy operation
*/
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_relaxed);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
if (w_ptr >= r_ptr)
{
size = w_ptr - r_ptr;
}
else
{
size = buff->size - (r_ptr - w_ptr);
}
return size;
}
/**
* \brief Resets buffer to default values. Buffer size is not modified
* \note This function is not thread safe.
* When used, application must ensure there is no active read/write operation
* \param[in] buff: Ring buffer instance
*/
void lwrb_reset(lwrb_t *buff)
{
if (BUF_IS_VALID(buff))
{
LWRB_STORE(buff->w_ptr, 0, memory_order_release);
LWRB_STORE(buff->r_ptr, 0, memory_order_release);
BUF_SEND_EVT(buff, LWRB_EVT_RESET, 0);
}
}
/**
* \brief Get linear address for buffer for fast read
* \param[in] buff: Ring buffer instance
* \return Linear buffer start address
*/
void *
lwrb_get_linear_block_read_address(const lwrb_t *buff)
{
lwrb_sz_t ptr = 0;
if (!BUF_IS_VALID(buff))
{
return NULL;
}
ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
return &buff->buff[ptr];
}
/**
* \brief Get length of linear block address before it overflows for read operation
* \param[in] buff: Ring buffer instance
* \return Linear buffer size in units of bytes for read operation
*/
lwrb_sz_t
lwrb_get_linear_block_read_length(const lwrb_t *buff)
{
lwrb_sz_t len = 0, w_ptr = 0, r_ptr = 0;
if (!BUF_IS_VALID(buff))
{
return 0;
}
/*
* Use temporary values in case they are changed during operations.
* See lwrb_buff_free or lwrb_buff_full functions for more information why this is OK.
*/
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_relaxed);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
if (w_ptr > r_ptr)
{
len = w_ptr - r_ptr;
}
else if (r_ptr > w_ptr)
{
len = buff->size - r_ptr;
}
else
{
len = 0;
}
return len;
}
/**
* \brief Skip (ignore; advance read pointer) buffer data
* Marks data as read in the buffer and increases free memory for up to `len` bytes
*
* \note Useful at the end of streaming transfer such as DMA
* \param[in] buff: Ring buffer instance
* \param[in] len: Number of bytes to skip and mark as read
* \return Number of bytes skipped
*/
lwrb_sz_t
lwrb_skip(lwrb_t *buff, lwrb_sz_t len)
{
lwrb_sz_t full = 0, r_ptr = 0;
if (!BUF_IS_VALID(buff) || len == 0)
{
return 0;
}
full = lwrb_get_full(buff);
len = BUF_MIN(len, full);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_acquire);
r_ptr += len;
if (r_ptr >= buff->size)
{
r_ptr -= buff->size;
}
LWRB_STORE(buff->r_ptr, r_ptr, memory_order_release);
BUF_SEND_EVT(buff, LWRB_EVT_READ, len);
return len;
}
/**
* \brief Get linear address for buffer for fast write
* \param[in] buff: Ring buffer instance
* \return Linear buffer start address
*/
void *
lwrb_get_linear_block_write_address(const lwrb_t *buff)
{
lwrb_sz_t ptr = 0;
if (!BUF_IS_VALID(buff))
{
return NULL;
}
ptr = LWRB_LOAD(buff->w_ptr, memory_order_relaxed);
return &buff->buff[ptr];
}
/**
* \brief Get length of linear block address before it overflows for write operation
* \param[in] buff: Ring buffer instance
* \return Linear buffer size in units of bytes for write operation
*/
lwrb_sz_t
lwrb_get_linear_block_write_length(const lwrb_t *buff)
{
lwrb_sz_t len = 0, w_ptr = 0, r_ptr = 0;
if (!BUF_IS_VALID(buff))
{
return 0;
}
/*
* Use temporary values in case they are changed during operations.
* See lwrb_buff_free or lwrb_buff_full functions for more information why this is OK.
*/
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_relaxed);
r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
if (w_ptr >= r_ptr)
{
len = buff->size - w_ptr;
/*
* When read pointer is 0,
* maximal length is one less as if too many bytes
* are written, buffer would be considered empty again (r == w)
*/
if (r_ptr == 0)
{
/*
* Cannot overflow:
* - If r is not 0, statement does not get called
* - buff->size cannot be 0 and if r is 0, len is greater 0
*/
--len;
}
}
else
{
len = r_ptr - w_ptr - 1;
}
return len;
}
/**
* \brief Advance write pointer in the buffer.
* Similar to skip function but modifies write pointer instead of read
*
* \note Useful when hardware is writing to buffer and application needs to increase number
* of bytes written to buffer by hardware
* \param[in] buff: Ring buffer instance
* \param[in] len: Number of bytes to advance
* \return Number of bytes advanced for write operation
*/
lwrb_sz_t
lwrb_advance(lwrb_t *buff, lwrb_sz_t len)
{
lwrb_sz_t free = 0, w_ptr = 0;
if (!BUF_IS_VALID(buff) || len == 0)
{
return 0;
}
/* Use local variables before writing back to main structure */
free = lwrb_get_free(buff);
len = BUF_MIN(len, free);
w_ptr = LWRB_LOAD(buff->w_ptr, memory_order_acquire);
w_ptr += len;
if (w_ptr >= buff->size)
{
w_ptr -= buff->size;
}
LWRB_STORE(buff->w_ptr, w_ptr, memory_order_release);
BUF_SEND_EVT(buff, LWRB_EVT_WRITE, len);
return len;
}
/**
* \brief Searches for a *needle* in an array, starting from given offset.
*
* \note This function is not thread-safe.
*
* \param buff: Ring buffer to search for needle in
* \param bts: Constant byte array sequence to search for in a buffer
* \param len: Length of the \arg bts array
* \param start_offset: Start offset in the buffer
* \param found_idx: Pointer to variable to write index in array where bts has been found
* Must not be set to `NULL`
* \return `1` if \arg bts found, `0` otherwise
*/
uint8_t
lwrb_find(const lwrb_t *buff, const void *bts, lwrb_sz_t len, lwrb_sz_t start_offset, lwrb_sz_t *found_idx)
{
lwrb_sz_t full = 0, r_ptr = 0, buff_r_ptr = 0, max_x = 0;
uint8_t found = 0;
const uint8_t *needle = bts;
if (!BUF_IS_VALID(buff) || needle == NULL || len == 0 || found_idx == NULL)
{
return 0;
}
*found_idx = 0;
full = lwrb_get_full(buff);
/* Verify initial conditions */
if (full < (len + start_offset))
{
return 0;
}
/* Get actual buffer read pointer for this search */
buff_r_ptr = LWRB_LOAD(buff->r_ptr, memory_order_relaxed);
/* Max number of for loops is buff_full - input_len - start_offset of buffer length */
max_x = full - len;
for (lwrb_sz_t skip_x = start_offset; !found && skip_x <= max_x; ++skip_x)
{
found = 1; /* Found by default */
/* Prepare the starting point for reading */
r_ptr = buff_r_ptr + skip_x;
if (r_ptr >= buff->size)
{
r_ptr -= buff->size;
}
/* Search in the buffer */
for (lwrb_sz_t idx = 0; idx < len; ++idx)
{
if (buff->buff[r_ptr] != needle[idx])
{
found = 0;
break;
}
if (++r_ptr >= buff->size)
{
r_ptr = 0;
}
}
if (found)
{
*found_idx = skip_x;
}
}
return found;
}

338
src/malloc.c Normal file
View File

@ -0,0 +1,338 @@
/*
* @Author:
* @Date: 2023-04-11 08:50:25
* @LastEditors: xxx
* @LastEditTime: 2023-06-15 10:23:12
* @Description:
* email:
* Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "../inc/data_type_def.h"
#include "../inc/malloc.h"
/*****************************************************************************
* C语言 *
******************************************************************************
*__align
*
*__attribute__作用
*
*
*
* __align(32) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));
* MEM2_MAX_SIZE32
* 0X68000000
* MEM2_MAX_SIZE为232MEM2_MAX_SIZE为33
* 64
*
*
struct A{
char a;
unsigned int b;
unsigned char c;
char d;
};
:
structB{
char a;
unsigned int b;
unsigned char c;
char d;
}__attribute__((align(8)));
sizeof(A) = 12(12)
sizeof(B) = 8(8)
********************************************************************************/
// 内存池(32字节对齐)
// 可控制的内存大小
__attribute__((aligned(32))) uint8_t mem1base[MEM1_MAX_SIZE]; // 内部SRAM内存池
__attribute__((aligned(32))) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((section(".sram2")));
// __attribute__((aligned(32))) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000))); // 外部SRAM内存池
// 内存管理表
// 可控制的内存控制块个数(每个内存块大小为32字节)
uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; // 内部SRAM内存池MAP
uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE];
// uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000 + MEM2_MAX_SIZE))); // 外部SRAM内存池MAP
// 内存管理参数
// const 定义的变量的值是不允许改变的
// 因为有内部SRAM和外部SRAM所以用数组
const uint32_t memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE, MEM2_ALLOC_TABLE_SIZE}; // 内存表大小(即控制多少内存块)
const uint32_t memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE, MEM2_BLOCK_SIZE}; // 内存分块大小(一块内存块占多少字节内存空间)
const uint32_t memsize[SRAMBANK] = {MEM1_MAX_SIZE, MEM2_MAX_SIZE}; // 内存池大小(即可以分配的内存空间大小)
// 内存管理控制器
struct _m_mallco_dev mallco_dev =
{
my_mem_init, // 内存初始化
my_mem_perused, // 内存使用率
mem1base, mem2base, // 内存池
mem1mapbase, mem2mapbase, // 内存管理状态表
0, 0, // 内存管理未就绪
};
/*******************************************
* ()
* mymemcpy
* void *des void *src uint32_t n
*void
*
* *des
* *src
* n ()
*********************************************/
void mymemcpy(void *des, void *src, uint32_t n)
{
// 一般我们不会对要操作的参数指针进行操作
// 而是通过一个变量指针作为中介,这样是为了出于安全保证
uint8_t *xdes = des;
uint8_t *xsrc = src;
// 变量在++之前,则先用,后++
// 变量在++之后,先++,后使用
while (n--)
*xdes++ = *xsrc++;
}
/*****************************************************
* (0)
* mymemset
* void *s uint8_t c uint32_t count
*void
*
* *s
* c
* count ()
******************************************************/
void mymemset(void *s, uint8_t c, uint32_t count)
{
// 一般我们不会对要操作的参数指针进行操作
// 而是通过一个变量指针作为中介,这样是为了出于安全保证
uint8_t *xs = s;
// 变量在++之前,则先用,后++
// 变量在++之后,先++,后使用
while (count--)
*xs++ = c;
}
/*****************************************************************
*
* my_mem_init
* uint8_t memx
*void
*
* memx:SRAM还是外部SRAM的内存块
*
* ()0
******************************************************************/
void my_mem_init(uint8_t memx)
{
mymemset(mallco_dev.memmap[memx], 0, memtblsize[memx] * 2); // 内存状态表数据清零
mymemset(mallco_dev.membase[memx], 0, memsize[memx]); // 内存池所有数据清零
mallco_dev.memrdy[memx] = 1; // 内存管理初始化OK即内存池和内存表都清0了
}
/*****************************************************************
* 使
* my_mem_perused
* uint8_t memx
*void
*
* memx:SRAM还是外部SRAM的内存块
*
* mem1mapbase或mem2mapbase的数组成员是否非0
* 010
* 10
******************************************************************/
uint8_t my_mem_perused(uint8_t memx)
{
uint32_t used = 0;
uint32_t i;
// memtblsize内存表大小(一共内存块数)
// 遍历内存表数组
for (i = 0; i < memtblsize[memx]; i++)
{
// mallco_dev.memmap[memx]:内存表数组
// 取出每个成员判断是否非0
// 非0则是用了
if (mallco_dev.memmap[memx][i])
used++;
}
// 使用数量/数量总数*100 = 使用率
return (used * 100) / (memtblsize[memx]);
}
/*****************************************************************
* ()------
* my_mem_malloc
* uint8_t memx,uint32_t size
*uint32_t
*
* memx:SRAM还是外部SRAM的内存块
* size:()
* :0XFFFFFFFF,;,
*
*
******************************************************************/
uint32_t my_mem_malloc(uint8_t memx, uint32_t size)
{
signed long offset = 0; // 偏移量变量
uint32_t nmemb; // 需要的内存块数
uint32_t cmemb = 0; // 连续空内存块数,保证我们申请的内存块是连续的
uint32_t i;
// 判断是否已执行了初始化
if (!mallco_dev.memrdy[memx])
mallco_dev.init(memx); // 未初始化,先执行初始化
if (size == 0)
return 0XFFFFFFFF; // 不需要分配
// 内存块数 = 申请空间大小(字节单位) / t一个内存块大小(字节单位)
nmemb = size / memblksize[memx]; // 获取需要分配的连续内存块数
// 申请空间大小(字节单位) / t一个内存块大小(字节单位) = 0
// 如果非0则要多申请一块内存块
if (size % memblksize[memx])
nmemb++;
// 内存表的遍历是从后往前的
for (offset = memtblsize[memx] - 1; offset >= 0; offset--) // 搜索整个内存控制区
{
// 判断该内存块是否被占用了
if (!mallco_dev.memmap[memx][offset])
cmemb++; // 连续空内存块数增加
// 保证内存块的连续性
else
cmemb = 0; // 连续内存块清零
// 确定好所有内存块位置后
if (cmemb == nmemb) // 找到了连续nmemb个空内存块
{
for (i = 0; i < nmemb; i++) // 标注内存块非空
{
// 开始往内存块在内存表数组的位置标记该内存块被占用
mallco_dev.memmap[memx][offset + i] = nmemb;
}
// 确定申请空间在内存池数组位置 在内存表数组位置*一个内存块大小(32字节)
return (offset * memblksize[memx]); // 返回偏移地址
}
}
return 0XFFFFFFFF; // 未找到符合分配条件的内存块
}
/*****************************************************************
* ()------
* my_mem_free
* uint8_t memx,uint32_t offset
*uint32_t
*
* memx:SRAM还是外部SRAM的内存块
* size:()--------
* :0,;1,;
*
******************************************************************/
uint8_t my_mem_free(uint8_t memx, uint32_t offset)
{
int i;
int index;
int nmemb;
// 判断是否初始化
if (!mallco_dev.memrdy[memx]) // 未初始化,先执行初始化
{
mallco_dev.init(memx);
return 1; // 未初始化
}
// 判断这个偏移量是否超出了内存池的大小
if (offset < memsize[memx]) // 偏移在内存池内.
{
// 内存表偏移量 = 内存池偏移量/一块内存块大小
index = offset / memblksize[memx]; // 偏移所在内存块号码
// 内存表数组成员的值就是申请的块数
nmemb = mallco_dev.memmap[memx][index]; // 内存块数量
for (i = 0; i < nmemb; i++) // 内存块清零
{
// 清除申请空间在内存表的标记
mallco_dev.memmap[memx][index + i] = 0;
}
return 0;
}
else
return 1; // 偏移超区了.
}
/*****************************************************************
* ()
* mymalloc
* uint8_t memx,uint32_t size
*void *
*
* memx:SRAM还是外部SRAM的内存块
* size:()
* :
******************************************************************/
void *mymalloc(uint8_t memx, uint32_t size)
{
uint32_t offset; // 在内存池数组的偏移量变量
// 获取在内存池数组的偏移量
offset = my_mem_malloc(memx, size);
// 如果申请错误,则返回空地址
if (offset == 0XFFFFFFFF)
return NULL;
// 如果申请成功,则返回申请空间首地址
else
return (void *)((uint32_t)mallco_dev.membase[memx] + offset);
}
/*****************************************************************
* ()
* myfree
* uint8_t memx,void *ptr
*uint32_t
*
* memx:SRAM还是外部SRAM的内存块
* ptr :
******************************************************************/
void myfree(uint8_t memx, void *ptr)
{
uint32_t offset;
uint32_t n; // 该要释放的空间的空间大小
if (ptr == NULL)
return; // 地址为0.
// 确定申请空间的内存池偏移量
offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx];
// 空间占内存池空间的大小
n = mallco_dev.memmap[memx][offset / memblksize[memx]] * memblksize[memx];
// 释放内存池对应空间的数据
mymemset(ptr, 0, n);
// 释放内存表
my_mem_free(memx, offset); // 释放内存
}
/*****************************************************************
* ()
* myfree
* uint8_t memx,void *ptr
*uint32_t
*
* memx:SRAM还是外部SRAM的内存块
* ptr :
* size:()
******************************************************************/
void *myrealloc(uint8_t memx, void *ptr, uint32_t size)
{
uint32_t offset;
// 申请一个新的空间
offset = my_mem_malloc(memx, size);
if (offset == 0XFFFFFFFF)
return NULL;
else
{
// 把旧空间的数据复制到新空间里
mymemcpy((void *)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); // 拷贝旧内存内容到新内存
// 删掉旧空间
myfree(memx, ptr); // 释放旧内存
// 返回新空间地址
return (void *)((uint32_t)mallco_dev.membase[memx] + offset); // 返回新内存首地址
}
}

149
src/mlist.c Normal file
View File

@ -0,0 +1,149 @@
/*
* @Author:
* @Date: 2023-04-04 08:39:23
* @LastEditors: xxx
* @LastEditTime: 2023-04-21 12:08:31
* @Description:
* email:
* Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "../inc/mlist.h"
#ifndef NULL
#define NULL ((void *)0)
#endif
void list_init(list_head_t *const ptr)
{
(ptr)->next = (ptr);
(ptr)->prev = (ptr);
}
/*
*
*/
static void __list_add(list_head_t *const new_entry,
list_head_t *const prev,
list_head_t *const next)
{
next->prev = new_entry;
new_entry->next = next;
new_entry->prev = prev;
prev->next = new_entry;
}
/**
*
*/
void list_insert_forwards(list_head_t *const new_entry, list_head_t *const pos)
{
__list_add(new_entry, pos->prev, pos);
}
/**
*
*/
void list_insert_backwards(list_head_t *const new_entry, list_head_t *const pos)
{
__list_add(new_entry, pos, pos->next);
}
/**
*
*/
void list_add_to_tail(list_head_t *const new_entry, list_head_t *const list)
{
__list_add(new_entry, list->prev, list);
}
/**
*
*/
void list_add_to_head(list_head_t *const new_entry, list_head_t *const list)
{
__list_add(new_entry, list, list->next);
}
static void __list_del(list_head_t *const prev, list_head_t *const next)
{
next->prev = prev;
prev->next = next;
}
/**
*
*/
void list_del(list_head_t *const elem)
{
__list_del(elem->prev, elem->next);
elem->next = (list_head_t *)NULL;
elem->prev = (list_head_t *)NULL;
}
/*
*
*/
list_head_t *list_curtail(const list_head_t *const head)
{
list_head_t *tail = head->prev;
list_del(tail);
return tail;
}
/**
*
*/
bool list_empty(const list_head_t *const head)
{
return (((head)->next == head) || (head->next == NULL));
}
/**
*
*/
list_head_t *list_first_elem_look(const list_head_t *const head)
{
if (!list_empty(head))
{
return head->next;
}
return NULL;
}
/**
*
*/
list_head_t *list_next_elem_get(const list_head_t *const pos)
{
if (pos == NULL)
{
return NULL;
}
list_head_t *temp = (pos)->next;
if (temp != NULL)
{
list_del(temp);
}
return temp;
}
/**
*
*/
void list_move_to_another_head(list_head_t *const elem, list_head_t *const head)
{
__list_del(elem->prev, elem->next);
list_add_to_head(elem, head);
}
/**
*
*/
void list_move_to_another_tail(list_head_t *const elem, list_head_t *const head)
{
__list_del(elem->prev, elem->next);
list_add_to_tail(elem, head);
}

401
src/pbuf.c Normal file
View File

@ -0,0 +1,401 @@
/*
* pbuf.c
*
* Created on: 2022125
* Author: xushenghao
*/
#include "../inc/debug.h"
#include "../inc/pbuf.h"
#include "../inc/osel_arch.h"
#define PBUF_DATA_SIZE(pbuf) (pbuf->end - pbuf->head)
typedef struct _pbuf_type_t
{
uint8_t type;
uint16_t size;
uint8_t num;
} pbuf_type_t;
static list_head_t pbuf_freez_blocks[PBUF_TYPE_MAX_NUM];
uint8_t pbuf_cnt[PBUF_TYPE_MAX_NUM] = {0};
#if PBUF_DBG_EN > 0
static pbuf_t *pbuf_used_p[PBUF_TYPE_MAX_NUM][PBUF_NUM_MAX];
#endif
static void poly_type_pbuf_init(uint8_t type, uint16_t pkt_len, uint8_t num)
{
void *mem = NULL;
pbuf_t *pbuf = NULL;
list_init(&pbuf_freez_blocks[type]);
if (num == 0)
{
return;
}
mem = osel_mem_alloc((sizeof(pbuf_t) + pkt_len) * num);
DBG_ASSERT(mem != NULL __DBG_LINE);
for (uint8_t i = 0; i < num; i++)
{
pbuf = (pbuf_t *)((uint8_t *)mem + i * (sizeof(pbuf_t) + pkt_len));
pbuf->head = (uint8_t *)pbuf + sizeof(pbuf_t);
pbuf->end = (uint8_t *)pbuf + sizeof(pbuf_t) + pkt_len;
pbuf->data_p = pbuf->head;
list_add_to_head(&pbuf->list, &pbuf_freez_blocks[type]);
}
pbuf_cnt[type] = num;
}
void pbuf_initz(void)
{
poly_type_pbuf_init(SMALL_PBUF,
SMALL_PBUF_BUFFER_SIZE,
SMALL_PBUF_NUM);
poly_type_pbuf_init(MEDIUM_PBUF,
MEDIUM_PBUF_BUFFER_SIZE,
MEDIUM_PBUF_NUM);
poly_type_pbuf_init(LARGE_PBUF,
LARGE_PBUF_BUFFER_SIZE,
LARGE_PBUF_NUM);
}
static pbuf_type_t search_free_pbuf(uint8_t pbuf_type)
{
pbuf_type_t free_pbuf_temp;
switch (pbuf_type)
{ // 没有break让代码顺序执行
case SMALL_PBUF:
if (!list_empty(&pbuf_freez_blocks[SMALL_PBUF]))
{
free_pbuf_temp.type = SMALL_PBUF;
free_pbuf_temp.size = SMALL_PBUF_BUFFER_SIZE;
free_pbuf_temp.num = SMALL_PBUF_NUM;
}
break;
case MEDIUM_PBUF:
if (!list_empty(&pbuf_freez_blocks[MEDIUM_PBUF]))
{
free_pbuf_temp.type = MEDIUM_PBUF;
free_pbuf_temp.size = MEDIUM_PBUF_BUFFER_SIZE;
free_pbuf_temp.num = MEDIUM_PBUF_NUM;
}
break;
case LARGE_PBUF:
if (!list_empty(&pbuf_freez_blocks[LARGE_PBUF]))
{
free_pbuf_temp.type = LARGE_PBUF;
free_pbuf_temp.size = LARGE_PBUF_BUFFER_SIZE;
free_pbuf_temp.num = LARGE_PBUF_NUM;
}
break;
default:
free_pbuf_temp.type = PBUF_TYPE_INVALID;
}
return free_pbuf_temp;
}
static pbuf_type_t pbuf_type_select(uint16_t size)
{
pbuf_type_t free_pbuf;
if (size <= SMALL_PBUF_BUFFER_SIZE)
{
free_pbuf = search_free_pbuf(SMALL_PBUF);
}
else if ((size > SMALL_PBUF_BUFFER_SIZE) && (size <= MEDIUM_PBUF_BUFFER_SIZE))
{
free_pbuf = search_free_pbuf(MEDIUM_PBUF);
}
else if ((size > MEDIUM_PBUF_BUFFER_SIZE) && (size <= LARGE_PBUF_BUFFER_SIZE))
{
free_pbuf = search_free_pbuf(LARGE_PBUF);
}
else
{
DBG_ASSERT(false __DBG_LINE);
}
if (free_pbuf.type == PBUF_TYPE_INVALID)
{
// DBG_ASSERT(false __DBG_LINE);
}
return free_pbuf;
}
#if PBUF_DBG_EN > 0
static void add_to_pbuf_used_ptr(pbuf_t *pbuf, pbuf_type_t pbuf_type)
{
// hal_int_state_t s;
// HAL_ENTER_CRITICAL(s);
for (uint8_t i = 0; i < PBUF_NUM_MAX; i++)
{
if (pbuf_used_p[pbuf_type.type][i] == NULL)
{
pbuf_used_p[pbuf_type.type][i] = pbuf;
break;
}
}
// HAL_EXIT_CRITICAL(s);
}
#endif
pbuf_t *pbuf_allocz(uint16_t size _PLINE1_)
{
pbuf_type_t avilable_pbuf_type;
pbuf_t *pbuf = NULL;
// hal_int_state_t s;
// HAL_ENTER_CRITICAL(s);
avilable_pbuf_type = pbuf_type_select(size);
if (avilable_pbuf_type.type == PBUF_TYPE_INVALID)
{
return NULL;
}
pbuf = list_entry_decap(&pbuf_freez_blocks[avilable_pbuf_type.type],
pbuf_t,
list);
pbuf_cnt[avilable_pbuf_type.type]--;
// HAL_EXIT_CRITICAL(s);
DBG_ASSERT(pbuf != NULL __DBG_LINE);
if (pbuf == NULL)
{
return NULL;
}
osel_memset(pbuf->head, 0, avilable_pbuf_type.size);
osel_memset((uint8_t *)&pbuf->attri, 0, sizeof(pbuf->attri));
// HAL_ENTER_CRITICAL(s);
pbuf->used = true;
pbuf->data_len = 0;
pbuf->data_p = pbuf->head;
list_init(&pbuf->list);
// HAL_EXIT_CRITICAL(s);
#if PBUF_DBG_EN > 0
pbuf->alloc_line = line;
pbuf->free_line = 0;
add_to_pbuf_used_ptr(pbuf, avilable_pbuf_type);
#endif
return pbuf;
}
static pbuf_type_t get_pbuf_type(pbuf_t **pbuf)
{
pbuf_type_t current_pbuf_type;
uint16_t size_temp;
DBG_ASSERT(*pbuf != NULL __DBG_LINE);
DBG_ASSERT(pbuf != NULL __DBG_LINE);
size_temp = (*pbuf)->end - (*pbuf)->head;
if (size_temp == SMALL_PBUF_BUFFER_SIZE)
{
current_pbuf_type.type = SMALL_PBUF;
current_pbuf_type.size = SMALL_PBUF_BUFFER_SIZE;
current_pbuf_type.num = SMALL_PBUF_NUM;
}
else if (size_temp == MEDIUM_PBUF_BUFFER_SIZE)
{
current_pbuf_type.type = MEDIUM_PBUF;
current_pbuf_type.size = MEDIUM_PBUF_BUFFER_SIZE;
current_pbuf_type.num = MEDIUM_PBUF_NUM;
}
else if (size_temp == LARGE_PBUF_BUFFER_SIZE)
{
current_pbuf_type.type = LARGE_PBUF;
current_pbuf_type.size = LARGE_PBUF_BUFFER_SIZE;
current_pbuf_type.num = LARGE_PBUF_NUM;
}
else
{
DBG_ASSERT(false __DBG_LINE);
}
return current_pbuf_type;
}
#if PBUF_DBG_EN > 0
static void delete_from_pbuf_used_ptr(pbuf_t **pbuf, pbuf_type_t pbuf_type_temp)
{
// hal_int_state_t s;
// HAL_ENTER_CRITICAL(s);
for (uint8_t i = 0; i < PBUF_NUM_MAX; i++)
{
if (pbuf_used_p[pbuf_type_temp.type][i] == *pbuf)
{
pbuf_used_p[pbuf_type_temp.type][i] = NULL;
break;
}
}
// HAL_EXIT_CRITICAL(s);
}
#endif
void pbuf_freez(pbuf_t **const pbuf _PLINE2_)
{
pbuf_type_t pbuf_type;
// hal_int_state_t s;
DBG_ASSERT(*pbuf != NULL __DBG_LINE);
DBG_ASSERT(pbuf != NULL __DBG_LINE);
DBG_ASSERT((*pbuf)->used == true __DBG_LINE); // 用于检测嵌套的重复释放
if (pbuf == NULL || *pbuf == NULL || (*pbuf)->used == false)
{
return;
}
pbuf_type = get_pbuf_type(pbuf);
#if PBUF_DBG_EN > 0
delete_from_pbuf_used_ptr(pbuf, pbuf_type);
(*pbuf)->free_line = line;
#endif
osel_memset((*pbuf)->head, 0, pbuf_type.size);
osel_memset((uint8_t *)&((*pbuf)->attri), 0, sizeof((*pbuf)->attri));
// HAL_ENTER_CRITICAL(s);
if ((*pbuf)->data_len > ((*pbuf)->end - (*pbuf)->head))
{
DBG_ASSERT(false __DBG_LINE);
}
(*pbuf)->used = false;
(*pbuf)->data_len = 0;
(*pbuf)->data_p = (*pbuf)->head;
list_init(&(*pbuf)->list);
list_add_to_tail(&(*pbuf)->list, &pbuf_freez_blocks[pbuf_type.type]);
#if PBUF_DBG_EN > 0
uint8_t list_cnt = 0;
list_count(&pbuf_freez_blocks[pbuf_type.type], list_cnt);
DBG_ASSERT(list_cnt != 0 __DBG_LINE);
#endif
pbuf_cnt[pbuf_type.type]++;
#if PBUF_DBG_EN > 0
(*pbuf)->alloc_line = 0;
#endif
// HAL_EXIT_CRITICAL(s);
*pbuf = NULL;
}
uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf, uint8_t len)
{
uint8_t *datap_tmp = NULL;
// hal_int_state_t s;
DBG_ASSERT(pbuf != NULL __DBG_LINE);
if (pbuf == NULL)
{
return NULL;
}
// HAL_ENTER_CRITICAL(s);
if ((pbuf->data_p + len) > pbuf->end)
{
// HAL_EXIT_CRITICAL(s);
return NULL;
}
pbuf->data_p += len;
datap_tmp = pbuf->data_p;
// HAL_EXIT_CRITICAL(s);
return datap_tmp;
}
uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf, uint8_t len)
{
uint8_t *datap_tmp = NULL;
// hal_int_state_t s;
DBG_ASSERT(pbuf != NULL __DBG_LINE);
if (pbuf == NULL)
{
return NULL;
}
// HAL_ENTER_CRITICAL(s);
if ((pbuf->data_p - len) < pbuf->head)
{
// HAL_EXIT_CRITICAL(s);
return NULL;
}
pbuf->data_p -= len;
datap_tmp = pbuf->data_p;
// HAL_EXIT_CRITICAL(s);
return datap_tmp;
}
bool pbuf_copy_data_in(pbuf_t *const pbuf, const uint8_t *const src, uint8_t len)
{
DBG_ASSERT(pbuf != NULL __DBG_LINE);
if (pbuf == NULL)
{
return false;
}
// hal_int_state_t s;
// HAL_ENTER_CRITICAL(s);
if ((pbuf->data_p + len) > pbuf->end)
{
// HAL_EXIT_CRITICAL(s);
return false;
}
else
{
osel_memcpy(pbuf->data_p, src, len);
pbuf->data_p += len;
pbuf->data_len += len;
// HAL_EXIT_CRITICAL(s);
return true;
}
}
bool pbuf_copy_data_out(uint8_t *const dst, pbuf_t *const pbuf, uint8_t len)
{
DBG_ASSERT(pbuf != NULL __DBG_LINE);
if (pbuf == NULL)
{
return false;
}
// hal_int_state_t s;
// HAL_ENTER_CRITICAL(s);
if ((pbuf->data_p + len) > pbuf->end)
{
// HAL_EXIT_CRITICAL(s);
return false;
}
else
{
osel_memcpy(dst, pbuf->data_p, len);
pbuf->data_p += len;
// HAL_EXIT_CRITICAL(s);
return true;
}
}

450
src/sqqueue.c Normal file
View File

@ -0,0 +1,450 @@
/**
* @file sqqueue.c
* @author xxx
* @date 2023-06-25 13:07:02
* @brief
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "../inc/sqqueue.h"
#include "../inc/osel_arch.h"
#define SQQ_ENTRY_SIZE (queue_ptr->entry_size)
#define SQQ_LEN (queue_ptr->sqq_len)
/**
* @brief
* @param p_this
* @param entry_size
* @param sqq_len
* @return {BOOL} truefalse
* @note
*/
static BOOL sqqueue_init(sqqueue_ctrl_t *const p_this,
uint8_t entry_size,
uint16_t sqq_len)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_t *queue_ptr = &(p_this->sqq);
if (queue_ptr != NULL)
{
queue_ptr->entry_size = entry_size;
queue_ptr->sqq_len = sqq_len + 1;
if (queue_ptr->base != NULL)
{
osel_mem_free(queue_ptr->base);
queue_ptr->base = NULL;
}
queue_ptr->base = (uint8_t *)osel_mem_alloc(SQQ_LEN * SQQ_ENTRY_SIZE);
if (queue_ptr->base == NULL)
{
return FALSE;
}
queue_ptr->front = 0;
queue_ptr->rear = 0;
return TRUE;
}
return FALSE;
}
/**
* @brief
*
*
*
* @param p_this
*/
void sqqueue_dinit(sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_t *queue_ptr = &(p_this->sqq);
if (queue_ptr != NULL)
{
if (queue_ptr->base != NULL)
{
osel_mem_free(queue_ptr->base);
queue_ptr->base = NULL;
}
}
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {uint16_t}
* @note
*/
static uint16_t sqqueue_length(const sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
const sqqueue_t *const queue_ptr = &(p_this->sqq);
uint16_t length = 0;
if (p_this != NULL)
{
length = (queue_ptr->rear + SQQ_LEN - queue_ptr->front);
if (length >= SQQ_LEN)
{
length -= SQQ_LEN;
}
}
return length;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {uint16_t}
* @note
*/
static BOOL sqqueue_full(const sqqueue_ctrl_t *const p_this)
{
uint16_t rear = 0;
DBG_ASSERT(p_this != NULL __DBG_LINE);
if (p_this != NULL)
{
const sqqueue_t *const queue_ptr = &(p_this->sqq);
rear = queue_ptr->rear + 1;
if (rear >= SQQ_LEN)
{
rear -= SQQ_LEN;
}
if (rear == queue_ptr->front)
{
return TRUE;
}
}
return FALSE;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @param {void} *e
* @return {BOOL} truefalse
* @note
*/
static BOOL enter_sqqueue(sqqueue_ctrl_t *const p_this, const void *const e)
{
uint16_t rear = 0;
sqqueue_t *queue_ptr = &(p_this->sqq);
if ((p_this != NULL) && (e != NULL))
{
rear = queue_ptr->rear + 1;
if (rear >= SQQ_LEN)
{
rear -= SQQ_LEN;
}
if (rear == queue_ptr->front)
{
return FALSE;
}
/* 根据e的长度进行内存拷贝 */
DBG_ASSERT(queue_ptr->rear != SQQ_LEN __DBG_LINE);
osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE),
e,
SQQ_ENTRY_SIZE);
queue_ptr->rear = rear;
return TRUE;
}
return FALSE;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @param {const void} *string
* @param {uint16_t} cnt
* @return {BOOL} truefalse
* @note
*/
static BOOL string_enter_sqqueue(sqqueue_ctrl_t *const p_this,
const void *const string,
uint16_t cnt)
{
uint16_t rear = 0;
uint16_t length = 0;
sqqueue_t *queue_ptr = &(p_this->sqq);
if ((p_this != NULL) && (string != NULL))
{
/* 判断是否超出队列长度 */
length = sqqueue_length(p_this); // 已有元素个数
if (length == 0xFFFF)
{
return FALSE;
}
length = (SQQ_LEN - 1) - length; // 可写入个数
if (length < cnt)
{
return FALSE;
}
rear = queue_ptr->rear + cnt;
if (rear >= SQQ_LEN)
{
rear -= SQQ_LEN;
uint8_t half = SQQ_LEN - queue_ptr->rear;
osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE),
string, half * SQQ_ENTRY_SIZE);
uint8_t *half_p = (uint8_t *)string;
osel_memcpy(queue_ptr->base, (uint8_t *)&half_p[half], rear * SQQ_ENTRY_SIZE);
}
else
{
osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE),
string, SQQ_ENTRY_SIZE * cnt);
}
queue_ptr->rear = rear;
return TRUE;
}
return FALSE;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {void *} NULL
* @note
*/
static void *delete_sqqueue(sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
uint16_t front = 0;
sqqueue_t *queue_ptr = NULL;
if (p_this != NULL)
{
void *p_elem = NULL;
queue_ptr = &(p_this->sqq);
if (queue_ptr->rear == queue_ptr->front)
{
return NULL;
}
/* 根据元素类型大小计算出偏移量,得到该元素首地址 */
p_elem = (void *)((queue_ptr->base) + (queue_ptr->front * SQQ_ENTRY_SIZE));
front = queue_ptr->front + 1;
if (front >= SQQ_LEN)
{
front -= SQQ_LEN;
}
queue_ptr->front = front;
return p_elem;
}
return NULL;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {*} NULL
* @note
*/
static void *revoke_sqqueue(sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
uint16_t rear = 0;
sqqueue_t *queue_ptr = NULL;
if (p_this != NULL)
{
void *p_elem = NULL;
queue_ptr = &(p_this->sqq);
if (queue_ptr->rear == queue_ptr->front)
{
return NULL;
}
rear = queue_ptr->rear;
if (rear == 0)
{
rear = SQQ_LEN - 1;
}
else
{
rear--;
}
queue_ptr->rear = rear;
/* 根据元素类型大小计算出偏移量,得到该元素首地址*/
p_elem = (void *)((queue_ptr->base) + (queue_ptr->rear * SQQ_ENTRY_SIZE));
return p_elem;
}
return NULL;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {void}
* @note
*/
static void clear_sqq(sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_t *queue_ptr = &(p_this->sqq);
if (p_this != NULL)
{
queue_ptr->front = 0;
queue_ptr->rear = 0;
}
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @param {void (*)(const void *e)} vi
* @return {void}
* @note
*/
static void traverse(sqqueue_ctrl_t *const p_this, void (*vi)(const void *e))
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_t *queue_ptr = NULL;
uint16_t i = 0;
if (p_this != NULL)
{
queue_ptr = &(p_this->sqq);
if (queue_ptr->rear == queue_ptr->front)
{
return;
}
i = queue_ptr->front;
while (i != queue_ptr->rear)
{
vi((void *)((queue_ptr->base) + (i * SQQ_ENTRY_SIZE)));
if (++i >= SQQ_LEN)
{
i = 0;
}
}
}
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @param {uint16_t} offset_to_front
* @return {void}
* @note
*/
static void qremove(sqqueue_ctrl_t *const p_this, uint16_t offset_to_front)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_t *queue_ptr = NULL;
uint16_t i = 0;
if (p_this != NULL)
{
queue_ptr = &(p_this->sqq);
DBG_ASSERT(offset_to_front < SQQ_LEN __DBG_LINE);
if (queue_ptr->rear == queue_ptr->front)
{
return;
}
uint16_t j = 0;
for (i = offset_to_front; i > 0; i--)
{
/* 定位待删除元素在队列中的位置 */
j = queue_ptr->front + i;
if (j >= SQQ_LEN)
{
j -= SQQ_LEN;
}
if (j == 0) // 在翻转位置特殊处理拷贝的源地址
{
osel_memcpy(queue_ptr->base + (0 * SQQ_ENTRY_SIZE),
queue_ptr->base + ((SQQ_LEN - 1) * SQQ_ENTRY_SIZE),
SQQ_ENTRY_SIZE);
}
else
{
osel_memcpy(queue_ptr->base + (j * SQQ_ENTRY_SIZE),
queue_ptr->base + ((j - 1) * SQQ_ENTRY_SIZE),
SQQ_ENTRY_SIZE);
}
}
/* 减少队列长度 */
uint16_t front = queue_ptr->front + 1;
if (front >= SQQ_LEN)
{
front -= SQQ_LEN;
}
queue_ptr->front = front;
}
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @param {uint8_t} entry_size
* @param {uint16_t} sqq_len
* @return {BOOL} truefalse
* @note
*/
BOOL sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this,
uint8_t entry_size,
uint16_t sqq_len)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
if (p_this != NULL)
{
if (sqqueue_init(p_this, entry_size, sqq_len) != FALSE)
{
p_this->enter = enter_sqqueue;
p_this->string_enter = string_enter_sqqueue;
p_this->del = delete_sqqueue;
p_this->revoke = revoke_sqqueue;
p_this->get_len = sqqueue_length;
p_this->full = sqqueue_full;
p_this->clear_sqq = clear_sqq;
p_this->traverse = traverse;
p_this->remove = qremove;
return TRUE;
}
}
return FALSE;
}
/**
* @brief
* @param {sqqueue_ctrl_t} *p_this
* @return {void}
* @note
*/
void sqqueue_ctrl_dinit(sqqueue_ctrl_t *const p_this)
{
DBG_ASSERT(p_this != NULL __DBG_LINE);
sqqueue_dinit(p_this);
}

252
src/storage.c Normal file
View File

@ -0,0 +1,252 @@
#include "storage.h"
/**
* @brief
*
*
*
* @param storage
* @param index
*
* @return NULL
*/
static storage_node_t *storage_node_find(storage_t *storage, uint16_t index)
{
storage_node_t *node = NULL;
for (clist_node_t *p = storage->head; p != NULL; p = p->next)
{
node = (storage_node_t *)p->data;
if (node->index == index)
{
break;
}
else
{
node = NULL;
}
}
return node;
}
/**
* @brief
*
*
*
* @param base_addr
* @param page_size
*
* @return
*/
storage_t *storage_init(uint32_t base_addr, uint16_t page_size)
{
storage_t *storage = (storage_t *)osel_mem_alloc(sizeof(storage_t));
DBG_ASSERT(storage != NULL __DBG_LINE);
osel_memset((uint8_t *)storage, 0, sizeof(storage_t));
clist_init(&storage->head);
storage->params.base_addr = base_addr;
storage->params.page_size = page_size;
return storage;
}
/**
* @brief
*
*
*
* @param storage
*/
void storage_destroy(storage_t *storage)
{
if (storage != NULL)
{
clist_destroy(&storage->head);
osel_mem_free(storage);
}
}
/**
* @brief
*
*
*
* @param storage
* @param index
* @param size
*/
void storage_add_node(storage_t *storage, uint16_t index, uint16_t size)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
storage_node_t *node = (storage_node_t *)osel_mem_alloc(sizeof(storage_node_t));
node->index = index;
node->size = size;
node->address = storage->params.base_addr + storage->params.variable_size;
storage->params.variable_size += size;
storage->params.variable_count++;
storage->params.page_count = storage->params.variable_size / storage->params.page_size;
if (storage->params.variable_size % storage->params.page_size != 0)
{
storage->params.page_count++;
}
clist_push_back(&storage->head, (cnode)node);
}
/**
* @brief
*
*
*
* @param storage
* @param buf
*
* @return TRUEFALSE
*/
BOOL storage_write_all(storage_t *storage, const uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.write != NULL __DBG_LINE);
return storage->ops.write(storage->params.base_addr, (uint8_t *)buf, storage->params.variable_size);
}
/**
* @brief
*
*
*
* @param storage
* @param index
* @param buf
*
* @return TRUEFALSE
*/
BOOL storage_write(storage_t *storage, uint16_t index, const uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.write != NULL __DBG_LINE);
storage_node_t *node = storage_node_find(storage, index);
if (node == NULL)
{
return FALSE;
}
return storage->ops.write(node->address, (uint8_t *)buf, node->size);
}
/**
* @brief
*
*
*
* @param storage
* @param buf
*
* @return TRUE FALSE
*
* @note
*
*/
BOOL storage_read_all(storage_t *storage, uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.read != NULL __DBG_LINE);
return storage->ops.read(storage->params.base_addr, buf, storage->params.variable_size);
}
/**
* @brief
*
*
*
* @param storage
* @param index
* @param buf
*
* @return TRUEFALSE
*/
BOOL storage_read(storage_t *storage, uint16_t index, uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.read != NULL __DBG_LINE);
storage_node_t *node = storage_node_find(storage, index);
if (node == NULL)
{
return FALSE;
}
return storage->ops.read(node->address, buf, node->size);
}
/**
* @brief
*
*
*
* @param storage
* @param index
* @param buf
*
* @return TRUE FALSE
*/
BOOL storage_check(storage_t *storage, uint16_t index, uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.read != NULL __DBG_LINE);
BOOL ret = FALSE;
storage_node_t *node = storage_node_find(storage, index);
if (node == NULL)
{
return FALSE;
}
uint8_t *tmp = (uint8_t *)osel_mem_alloc(node->size);
DBG_ASSERT(tmp != NULL __DBG_LINE);
if (storage->ops.read(node->address, tmp, node->size) == TRUE)
{
if (osel_memcmp(tmp, buf, node->size) == 0)
{
ret = TRUE;
}
}
osel_mem_free(tmp);
return ret;
}
/**
* @brief
*
* storage参数指定buf参数指定
*
* @param storage
* @param buf
*
* @return TRUEFALSE
*
* @note storage和buf均不为NULLstorage->ops.read指向有效的读操作函数
*/
BOOL storage_check_all(storage_t *storage, uint8_t *buf)
{
DBG_ASSERT(storage != NULL __DBG_LINE);
DBG_ASSERT(buf != NULL __DBG_LINE);
DBG_ASSERT(storage->ops.read != NULL __DBG_LINE);
BOOL ret = FALSE;
uint8_t *tmp = (uint8_t *)osel_mem_alloc(storage->params.variable_size);
DBG_ASSERT(tmp != NULL __DBG_LINE);
if (storage->ops.read(storage->params.base_addr, tmp, storage->params.variable_size) == TRUE)
{
if (osel_memcmp(tmp, buf, storage->params.variable_size) == 0)
{
ret = TRUE;
}
else
{
__NOP();
}
}
osel_mem_free(tmp);
return ret;
}

314
src/wl_flash.c Normal file
View File

@ -0,0 +1,314 @@
#include "wl_flash.h"
#include <stdlib.h>
static BOOL flash_is_written(wl_flash_t *cfg, uint32_t address, uint16_t length);
/**
* @brief
*
*
*
* @param cfg
*
* @note cfg是否为空cfg中的srandreadwriteerase_page操作均不为空
* @note FLASH页大小是否为2的幂次方FLASH长度是否为页大小的整数倍FLASH长度是否大于等于data_size
* @note data_size不是write_gran的整数倍
* @note
*/
void wl_flash_init(wl_flash_t *cfg)
{
// 断言cfg不为空
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 断言cfg中的srand操作不为空
DBG_ASSERT(cfg->ops.srand != NULL __DBG_LINE);
// 断言cfg中的read操作不为空
DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
// 断言cfg中的write操作不为空
DBG_ASSERT(cfg->ops.write != NULL __DBG_LINE);
// 断言cfg中的erase_page操作不为空
DBG_ASSERT(cfg->ops.erase_page != NULL __DBG_LINE);
// 检查FLASH页大小是否为2的幂次方
// 检查FLASH页大小
DBG_ASSERT((cfg->page_size & (cfg->page_size - 1)) == 0 __DBG_LINE);
// 检查FLASH长度是否为页大小的整数倍
// 检查FLASH长度
DBG_ASSERT(cfg->len % cfg->page_size == 0 __DBG_LINE);
// 如果data_size不是write_gran的整数倍则向上取整
if (cfg->data_size % cfg->write_gran != 0)
{
cfg->data_size = (cfg->data_size / cfg->write_gran + 1) * cfg->write_gran;
}
// 断言FLASH长度大于等于data_size
DBG_ASSERT(cfg->len >= cfg->data_size __DBG_LINE);
// 初始化起始地址、起始页号、总页数、数据块所占页数和剩余大小
cfg->private.current_address = cfg->addr;
cfg->private.start_page = cfg->addr / cfg->page_size;
cfg->private.page_total = cfg->len / cfg->page_size;
if (cfg->wl_flag == TRUE)
{
cfg->private.block_page = cfg->data_size / cfg->page_size + (cfg->data_size % cfg->page_size != 0 ? 1 : 0);
}
else
{
cfg->private.block_page = cfg->private.page_total;
}
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
}
/**
* @brief
*
*
*
* @param cfg
*
* @note cfg NULL cfg sranderase_page NULL
* write_gran 0
*
* @see DBG_ASSERT
*/
void wl_flash_erase(wl_flash_t *cfg)
{
// 断言cfg不为空
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 断言cfg->ops.srand不为空
DBG_ASSERT(cfg->ops.srand != NULL __DBG_LINE);
// 断言cfg->ops.erase_page不为空
DBG_ASSERT(cfg->ops.erase_page != NULL __DBG_LINE);
// 断言cfg->write_gran不为0
DBG_ASSERT(cfg->write_gran != 0 __DBG_LINE);
// 断言cfg->private.page_total不为0
DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
// 计算起始页号
uint16_t start_page = cfg->addr / cfg->page_size;
// 计算结束页号
uint16_t end_page = (cfg->addr + cfg->len) / cfg->page_size;
// 遍历起始页号到结束页号的每个页
for (uint16_t i = start_page; i < end_page; i++)
{
// 如果该页已被写入
if (flash_is_written(cfg, i * cfg->page_size, cfg->page_size) == TRUE)
{
// 擦除该页
cfg->ops.erase_page(i);
}
}
// 如果wl_flag为TRUE
if (cfg->wl_flag == TRUE)
{
// 调用srand函数
cfg->ops.srand();
// 计算最大值,这里减去一是为了防止超出范围
uint16_t max = cfg->private.page_total / cfg->private.block_page - 1; // 这里减去一是为了防止超出范围
// 计算当前地址
cfg->private.current_address = cfg->addr + (rand() % max) * cfg->private.block_page * cfg->page_size;
// 设置剩余大小为block_page个页的大小
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
}
else
{
// 否则将当前地址设置为cfg->addr
cfg->private.current_address = cfg->addr;
// 设置剩余大小为block_page个页的大小
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
}
}
/**
* @brief
*
*
*
* @param cfg
*
* @return
*/
uint32_t wl_flash_get_current_address(wl_flash_t *cfg)
{
return cfg->private.current_address;
}
/**
* @brief
*
*
*
* @param cfg
*
* @note
*/
void wl_flash_set_next_address(wl_flash_t *cfg)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 断言cfg->private.page_total不为0
DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
BOOL switch_page = FALSE;
uint16_t current_page = cfg->private.current_address / cfg->page_size;
if (cfg->wl_flag == TRUE)
{
// 判断是否需要换到下一个block
if ((cfg->private.residue_size - cfg->data_size) < cfg->data_size)
{
current_page += cfg->private.block_page;
cfg->private.current_address = current_page * cfg->page_size;
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
switch_page = TRUE;
}
else
{
// 有空间可以写入,当前写入地址偏移
cfg->private.current_address += cfg->data_size;
cfg->private.residue_size -= cfg->data_size;
}
if (cfg->private.current_address + cfg->data_size > cfg->addr + cfg->len)
{
cfg->private.current_address = cfg->addr;
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
switch_page = TRUE;
}
}
else
{
// 不使用平衡擦写默认都使用第一页
cfg->private.current_address = cfg->addr;
cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
switch_page = TRUE;
}
// 如果写入区域切换到下一个block则判断是否需要擦除
if (switch_page == TRUE)
{
// 判断准备写入的区域是否已经写入过数据
for (uint8_t i = 0; i < cfg->private.block_page; i++)
{
uint32_t current_address = cfg->private.current_address + (i * cfg->page_size);
if (flash_is_written(cfg, current_address, cfg->page_size) == TRUE)
{
cfg->ops.erase_page(current_address / cfg->page_size);
}
}
}
}
/**
* @brief Flash
*
* Flash
*
* @param cfg Flash
* @param address Flash
*/
void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address)
{
uint16_t current_page = address / cfg->page_size;
uint16_t current_block_page_num = (current_page - cfg->private.start_page) / cfg->private.block_page; // 确定当前的地址在第几个block_page中
uint32_t current_page_start_address = cfg->addr + current_block_page_num * cfg->page_size * cfg->private.block_page; // 当前block_page的起始地址
cfg->private.current_address = address;
// 根据当前地址更新剩余可写字节
cfg->private.residue_size = cfg->private.block_page * cfg->page_size - (address - current_page_start_address);
}
/**
* @brief
*
*
*
* @param cfg
* @param buf
* @param size
*
* @return TRUE FALSE
*/
BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
DBG_ASSERT(cfg->ops.write != NULL __DBG_LINE);
DBG_ASSERT(cfg->write_gran != 0 __DBG_LINE);
DBG_ASSERT(size <= cfg->data_size __DBG_LINE);
// 断言cfg->private.page_total不为0
DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
BOOL res = FALSE;
res = cfg->ops.write(cfg->private.current_address, buf, size);
return res;
}
/**
* @brief Flash
*
* Flash Flash
*
* @param cfg Flash
* @param buf
* @param size
*
* @return TRUE FALSE
*
* @note Flash read
*
* @warning
*/
BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
// 断言cfg->private.page_total不为0
DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
return cfg->ops.read(cfg->private.current_address, buf, size);
}
static BOOL flash_is_written(wl_flash_t *cfg, uint32_t address, uint16_t length)
{
DBG_ASSERT(cfg != NULL __DBG_LINE);
DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
uint8_t *data;
uint16_t count = 0;
BOOL res = FALSE, ret = FALSE;
count = length / cfg->page_size;
if (length % cfg->page_size != 0)
{
count++;
}
data = osel_mem_alloc(cfg->page_size);
DBG_ASSERT(data != NULL __DBG_LINE);
for (uint16_t i = 0; i < count; i++)
{
ret = cfg->ops.read(address + i * cfg->page_size, data, cfg->page_size);
if (ret == TRUE)
{
for (uint16_t j = 0; j < cfg->page_size; j++)
{
if (data[j] != 0xff)
{
res = TRUE;
break;
}
}
}
else
{
res = FALSE;
break;
}
if (res == TRUE)
{
break;
}
res = FALSE;
ret = FALSE;
}
osel_mem_free(data);
return res;
}