Embed/microCLib

.
JiuHuan authored at 2026-04-06 15:37:48
c94c966
Tree
1 Parent(s) cd8f6ff
Summary: 9 changed files with 855 additions and 211 deletions.
Added +66 -0
Added +29 -0
Modified +1 -1
Modified +358 -0
Modified +130 -0
Modified +17 -159
Modified +235 -32
Modified +13 -13
Modified +6 -6
Added +66 -0
diff --git a/Core/AdcFilter.c b/Core/AdcFilter.c
new file mode 100644
index 0000000..0c43834
--- /dev/null
+++ b/Core/AdcFilter.c
@@ -0,0 +1,66 @@
+
+#include "AdcFilter.h"
+#include "math.h"
+
+/// <summary>初始化滤波器</summary>
+bool AdcFilterInit(AdcFilter_t* filter, short size)
+{
+    if(filter == NULL)return false;
+    if(size < 4)size = 4;
+    
+    filter->Data = (short*)malloc(sizeof(short)*size);
+    if(filter->Data == NULL)return false;
+
+    memset(filter->Data, 0, sizeof(short)*size);
+    filter->Size = size;
+    filter->Index = 0;
+    return true;
+}
+
+/// <summary>滤波数据</summary>
+/// <param name="filter">滤波器</param>
+/// <param name="data">原始数据</param>
+/// <returns>数据放入成功</returns>
+bool AdcFilterPush(AdcFilter_t* filter,short data)
+{
+    if(filter == NULL)return false;
+    if(filter->Data == NULL)return false;
+
+    // 保存数据
+    filter->Data[filter->Index] = data;
+    // 更新索引
+    filter->Index++;
+    if(filter->Index >= filter->Size)filter->Index = 0;
+
+    return true;
+}
+
+/// <summary>滤波数据</summary>
+/// <param name="filter">滤波器</param>
+/// <param name="valueMax">X Y 的最大值,绝对值</param>
+/// <param name="outRange">换算为这个范围,ADC数值转换为对外输出范围,绝对值</param>
+/// <returns>滤波之后的数据</returns>
+short AdcFilterCalc(AdcFilter_t* filter, int valueMax, int outRange)
+{
+    // 滤波
+    int sum = 0;
+    int min = INT32_MAX;
+    int max = INT32_MIN;
+    for(int i = 0; i < filter->Size; i++)
+    {
+        sum += filter->Data[i];
+        if(filter->Data[i] < min)min = filter->Data[i];
+        if(filter->Data[i] > max)max = filter->Data[i];
+    }
+    // 去除最大最小值
+    sum -= min;
+    sum -= max;
+    
+    // 滤波后的数值
+    int result = sum / (filter->Size - 2);
+
+    // 范围转换
+    result = (result * outRange) / valueMax;
+    return (short)result;
+}
+
Added +29 -0
diff --git a/Core/AdcFilter.h b/Core/AdcFilter.h
new file mode 100644
index 0000000..f64c6b2
--- /dev/null
+++ b/Core/AdcFilter.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "Type.h"
+
+/// <summary>滤波器</summary>
+typedef struct
+{
+    short* Data;
+    short Size;
+    short Index;
+}AdcFilter_t;
+
+
+/// <summary>初始化滤波器</summary>
+bool AdcFilterInit(AdcFilter_t* filter, short size);
+
+/// <summary>滤波数据</summary>
+/// <param name="filter">滤波器</param>
+/// <param name="data">原始数据</param>
+/// <returns>数据放入成功</returns>
+bool AdcFilterPush(AdcFilter_t* filter,short data);
+
+/// <summary>滤波数据</summary>
+/// <param name="filter">滤波器</param>
+/// <param name="valueMax">X Y 的最大值,绝对值</param>
+/// <param name="outRange">换算为这个范围,ADC数值转换为对外输出范围,绝对值</param>
+/// <returns>滤波之后的数据</returns>
+short AdcFilterCalc(AdcFilter_t* filter, int valueMax, int outRange);
+
Modified +1 -1
diff --git a/Core/cJSON.c b/Core/cJSON.c
index 4e51dec..6e8c278 100644
--- a/Core/cJSON.c
+++ b/Core/cJSON.c
@@ -45,7 +45,7 @@ static char* cJSON_strdup(const char* str)
 // 设置 malloc free
 void cJSON_InitHooks(cJSON_Hooks* hooks)
 {
-	if (!hooks)
+	if (hooks == NULL)
 	{
 		cJSON_malloc = GlobleMalloc;
 		cJSON_free = GlobleFree;
Modified +358 -0
diff --git a/Core/ConfigBase.c b/Core/ConfigBase.c
index fac75b7..91824a3 100644
--- a/Core/ConfigBase.c
+++ b/Core/ConfigBase.c
@@ -100,3 +100,361 @@ bool CleanConfig(uint addr)
 
 	return rs;
 }
+
+
+
+#include "Crc.h"
+#include "Array.h"
+
+// Config 有效性 取决于 MagicNum SaveIdx Crc32
+typedef struct
+{
+	// 配置实际内容。
+	Config_t Config;
+
+	// 魔数  内部使用。 外部不要碰
+	// 默认为 : 'M' 'a' 'g' '&'   0x4D616726
+	uint MagicNum;
+	// 保存号,也是位置号。内部使用。外部不要碰  0-65535
+	ushort Index;
+	// 校验  内部使用。 外部不要碰
+	ushort Crc16;
+}FConfigItem_t;
+
+/// <summary>修正内部数据</summary>
+/// <param name="cfg">配置</param>
+/// <param name="idx">必要条件</param>
+/// <returns></returns>
+static void FixFCfg(FConfigItem_t* cfg, ushort idx)
+{
+	cfg->Index = idx;
+	cfg->MagicNum = 0x4D616726;
+	byte* p = (byte*)cfg;
+	int len = offsetof2(FConfigItem_t,Crc16);
+	cfg->Crc16 = CaclcCRC16_MODBUS(p, len);
+	// cfg->Crc16 = CaclcCRC16_MODBUS(p,sizeof(FConfigItem_t) - 2);
+}
+
+/// <summary>检查配置是否有效</summary>
+/// <param name="cfg"></param>
+/// <returns></returns>
+static bool FCfgIsOK(FConfigItem_t* cfg) 
+{
+	if(cfg == NULL)return false;
+	if(cfg->MagicNum != 0x4D616726)return false;
+	
+	byte* p = (byte*)cfg;
+	int len = offsetof2(FConfigItem_t,Crc16);
+ 	ushort cl = CaclcCRC16_MODBUS(p, len);
+ 	// ushort cl = CaclcCRC16_MODBUS(p,sizeof(FConfigItem_t) - 2);
+	if(cl != cfg->Crc16)return false;
+
+	return true;
+}
+
+/// <summary>所在块的块地址</summary>
+/// <param name="ctl"></param>
+/// <param name="idx"></param>
+/// <returns></returns>
+static uint FCfgSecAddr(FCfgCtrl_t* ctl,int idx)
+{
+	// 块个数
+	int sCnt = 1 << ctl->FSecBit;
+	// 所在块
+	int sec = idx & (sCnt - 1);
+	// 块地址
+	uint addr = ctl->FSecAddrs[sec];
+	return addr;
+}
+
+// #define FSECADDR(ctl,idx)  (ctl->FSecAddrs[(idx & ((1 << ctl->FSecBit) - 1)))])
+// FSECADDR FCfgSecAddr
+
+/// <summary>块内偏移量</summary>
+/// <param name="ctl"></param>
+/// <param name="idx"></param>
+/// <returns></returns>
+static uint FSecOffset(FCfgCtrl_t* ctl,int idx)
+{
+	// 块内编号
+	idx >>=  ctl->FSecBit;
+	// 块内个数
+	int cCnt = 1 << ctl->FSecCfgBit;
+	// 取余
+	int sidx = idx & (cCnt - 1);
+	// 块内偏移
+	uint offset = sizeof(FConfigItem_t) * sidx;
+	return offset;
+}
+
+// #define FSECOFFSET(ctl,idx)  (sizeof(FConfigItem_t) * ((idx >> ctl->FSecBit) & (1 << ctl->FSecCfgBit) - 1))))
+// #define FSECOFFSET FSecOffset
+
+/// <summary>初始化</summary>
+/// <param name="ctl"></param>
+/// <param name="api">NOR FLASH 接口</param>
+/// <param name="sad">FLASH 块地址数组</param>
+/// <param name="sadlen">块数组长度</param>
+/// <param name="ccnt">块内 存放配置的份数</param>
+/// <returns>0 无错</returns>
+int FCfgInit(FCfgCtrl_t* ctl, NorFlash_t* api, uint* sad, byte sadlen, byte ccnt)
+{
+	int err = 0;
+	byte temp = 0;
+	if(ctl == NULL){ err = __LINE__; goto reserr; }
+	if(api == NULL){ err = __LINE__; goto reserr; }
+	if(sad == NULL){ err = __LINE__; goto reserr; }
+	if(sadlen < 2) { err = __LINE__; goto reserr; }
+	if(ccnt < 1)   { err = __LINE__; goto reserr; }
+
+	memcpy(&ctl->FApi,api,sizeof(NorFlash_t));
+	ctl->FSecAddrs = sad;
+
+	// 计算位数
+	temp = 0;
+	for (int i = 1; ; i++)
+	{
+		int cnt = 1 << i;
+		if(sadlen >= cnt)temp = i;
+		else break;
+	}	
+	ctl->FSecBit = temp;
+
+	temp = 0;
+	for (int i = 0; ; i++)
+	{
+		int cnt = 1 << i;
+		if(ccnt >= cnt)temp = i;
+		else break;
+	}
+	ctl->FSecCfgBit = temp;
+	return 0;
+
+	reserr:
+	DebugPrintf("%s [%d] ERROR\r\n",__func__,__LINE__);
+	return err;
+}
+
+/// <summary>扫描整个 FLASH 存储区,找到最新且有效的配置取出来</summary>
+/// <param name="ctl"></param>
+/// <param name="cfg"></param>
+/// <returns></returns>
+bool FCfgLoad(FCfgCtrl_t* ctl, Config_t* cfg) 
+{
+	if(ctl == NULL)return false;
+	if(ctl->FSecAddrs == NULL)return false;
+	if(ctl->FSecBit < 1)return false;
+	if(cfg == NULL)return false;
+
+	// 最大同时存在配置个数
+	int limit = (1 << ctl->FSecBit) *  (1 << ctl->FSecCfgBit);
+	// 已存在最大IDX
+	int max = -1;
+	// 小于limit的,已存在最大IDX
+	int limitMax = -1;
+	
+	FConfigItem_t temp;
+	FConfigItem_t* fp = &temp;
+	// 块个数
+	int slen = 1 << ctl->FSecBit;
+	// 块内配置个数
+	int sCfgCnt = 1 << ctl->FSecCfgBit;
+
+	for (int i = 0; i < slen; i++)
+	{
+		// 块首地址
+		uint base = ctl->FSecAddrs[i];
+		for (int j = 0; j < sCfgCnt; j++)
+		{			
+			// 得到地址
+			uint addr = sizeof(FConfigItem_t) * j + base;
+			
+			if(ctl->FApi.FlashRead != NULL)
+			{
+				// 读取 配置项
+				memset(fp, 0x00, sizeof(FConfigItem_t));
+				if(!ctl->FApi.FlashRead(addr,(byte*)fp,sizeof(FConfigItem_t)))continue;				
+			}
+			else
+			{ 
+				// 直接指针过去
+				fp = (FConfigItem_t*)addr;
+			}
+
+			// 配置有效性检查
+			if(!FCfgIsOK(fp))continue;
+
+			// 选取最后存入的 idx
+			ushort idx = fp->Index;
+			if(idx > max)max = idx;
+			if(idx < limit)
+			{
+				if(idx > limitMax)limitMax = idx;
+			}			
+		}
+	}
+	
+	// 没有任何有效配置
+	if(max == -1)
+	{
+		ctl->CurrIndex = 0;
+		memset(&ctl->CurrCfg,0x00,sizeof(FConfigItem_t));		
+		return false;
+	}
+
+	// 判定最后写入是哪个
+	int last = -1;
+	if((max > 65535 - limit) && (limitMax != -1))
+	{
+		// 刚好跨界了。大的被丢弃。使用小的里面最大的。
+		last = limitMax;
+	}
+	else
+	{
+		last = max;
+	}
+
+	// 块地址 + 块内偏移
+	uint addr = FCfgSecAddr(ctl,last) + FSecOffset(ctl,last);
+	if(ctl->FApi.FlashRead != NULL)
+	{
+		// 读取 配置项
+		memset(fp, 0x00, sizeof(FConfigItem_t));
+		ctl->FApi.FlashRead(addr,(byte*)fp,sizeof(FConfigItem_t));				
+	}
+	else
+	{ 
+		// 直接指针过去
+		fp = (FConfigItem_t*)addr;
+	}
+
+	memcpy(&ctl->CurrCfg,&fp->Config,sizeof(Config_t));
+	ctl->CurrIndex = fp->Index;
+
+	memcpy(cfg,&ctl->CurrCfg,sizeof(Config_t));
+	return true;
+}
+
+/// <summary>写配置进去,地址为块首地址的时候擦除块。</summary>
+/// <param name="ctl"></param>
+/// <param name="cfg"></param>
+/// <returns></returns>
+static bool FCfgWrite(FCfgCtrl_t* ctl, FConfigItem_t* cfg)
+{
+	if(ctl->FApi.FlashWrite == NULL)return false;
+
+	int idx = cfg->Index;
+	// 块地址
+	uint addr = FCfgSecAddr(ctl,idx);
+	// 块内偏移
+	uint offset = FSecOffset(ctl,idx);
+
+	if(offset == 0)
+	{
+		if(ctl->FApi.FlashErase == NULL)return false;
+		if(!ctl->FApi.FlashErase(addr))return false;
+	}
+	
+	// 写
+	return ctl->FApi.FlashWrite(addr + offset, (byte*)cfg, sizeof(FConfigItem_t));
+}
+
+/// <summary>保存配置</summary>
+/// <param name="ctl"></param>
+/// <param name="cfg"></param>
+/// <returns></returns>
+bool FCfgSave(FCfgCtrl_t* ctl, Config_t* cfg)
+{
+	if(ctl == NULL)return false;
+	if(ctl->FSecAddrs == NULL)return false;
+	if(ctl->FSecBit < 1)return false;
+	if(cfg == NULL)return false;
+
+	// 相同,不存。
+	Config_t* curr = &ctl->CurrCfg;
+	if(!ArrayEqual((byte*)cfg, (byte*)curr,sizeof(Config_t)))return true;
+
+	// 下一个位置保存
+	ushort idx = ctl->CurrIndex + 1;
+	FConfigItem_t item;
+	memcpy(&item.Config,cfg,sizeof(Config_t));
+	FixFCfg(&item,idx);
+	bool res = FCfgWrite(ctl, &item);
+	// 保存完成,更新本地信息
+	if(res)
+	{
+		memcpy(&ctl->CurrCfg,cfg,sizeof(Config_t));
+		ctl->CurrIndex = item.Index;
+	}
+
+	return res;
+}
+
+/// <summary>删除一个配置</summary>
+/// <param name="ctl"></param>
+/// <param name="idx"></param>
+/// <returns></returns>
+bool FCfgClean(FCfgCtrl_t* ctl, int idx)
+{
+	if(ctl->FApi.FlashWrite == NULL)return false;
+
+	// 块地址
+	uint addr = FCfgSecAddr(ctl,idx);
+	// 块内偏移
+	uint offset = FSecOffset(ctl,idx);
+
+	// 配置内 magic 位置
+	offset += offsetof2(FConfigItem_t,MagicNum);
+
+	// FLASH 擦完是 ff 只能往 00 写
+	uint magic = 0;
+	return ctl->FApi.FlashWrite(addr+offset, (byte*)&magic, sizeof(magic));
+}
+
+/// <summary>擦除所有 FLASH 区域,一个不留</summary>
+/// <param name="ctl"></param>
+/// <returns></returns>
+bool FCfgCleanAll(FCfgCtrl_t* ctl)
+{
+	if(ctl == NULL)return false;
+	if(ctl->FSecAddrs == NULL)return false;
+	if(ctl->FSecBit < 1)return false;
+	if(ctl->FApi.FlashErase == NULL)return false;
+
+	int slen = 1 << ctl->FSecBit;
+	for (int i = 0; i < slen; i++)
+	{
+		ctl->FApi.FlashErase(ctl->FSecAddrs[i]);
+	}
+	ctl->CurrIndex = 0;
+
+	return true;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Modified +130 -0
diff --git a/Core/ConfigBase.h b/Core/ConfigBase.h
index b6fb9a1..8ce565b 100644
--- a/Core/ConfigBase.h
+++ b/Core/ConfigBase.h
@@ -32,3 +32,133 @@ bool SetConfig(Config_t* cfg, uint addr);
 // 删除配置内容
 bool CleanConfig(uint addr);
 
+/***************************************************************/
+/*
+写很多份配置的驱动。
+NOR FLASH 作为存储载体。
+多擦除块设计。
+处理写入时断电问题。
+*/
+
+// 块:擦除块
+typedef struct
+{
+	// FLASH 写
+	bool (*FlashWrite)(uint address, byte* buf, int len);
+	// 可以直接通过指针访问的 addr ,此函数为 NULL。
+	bool (*FlashRead)(uint address, byte* buf, int len);
+	// FLASH 擦块
+	bool (*FlashErase)(uint address);
+}NorFlash_t;
+
+// 对象
+typedef struct
+{
+	// 内当前最新配置,用于对比是否需要写入。
+	Config_t CurrCfg;
+	// NOR FLASH 接口
+	NorFlash_t FApi;
+	// FLASH Section 地址数组,数组长度是 FlashSecCnt
+    uint* FSecAddrs;
+	// FLASH Section 块个数。 个数 FlashSecCnt = (1 << FSecBit)
+	byte FSecBit;
+	// FLASH Section 存 Config_t 的份数 = (1 << FSecCfgBit)
+	byte FSecCfgBit;
+
+	// 当前使用的 IDEX 。也是存放位置。
+	ushort CurrIndex;    
+}FCfgCtrl_t;
+
+/*
+// FLASH 擦除块地址
+const uint secAddr[] = 
+{ 
+	0    + 0x8000000 + (48 * 1024),
+	1024 + 0x8000000 + (48 * 1024),
+	2048 + 0x8000000 + (48 * 1024),
+	4096 + 0x8000000 + (48 * 1024)
+};
+
+// 单片机内部 NOR FLASH
+NorFlash_t nfunc = 
+{
+	.FlashWrite = XXX
+	.FlashRead = NULL,
+	.FlashErase = XXX,
+};
+
+// 直接定义
+FCfgCtrl_t FCtl =
+{
+	.FlashWrite = xxx,
+	.FlashErase = xxx,
+	.BaseAddrs = secAddr,
+	.FSecCnt = 2, 			// (1<<2) 有4块
+	.FSecCfgCnt = 3,		// (1<<3) 存8份
+	.CfgIndex = 0,
+};
+
+使用 FCfgInit 函数配置
+FCfgInit(&FCtl, &nfunc, secAddr, ArrayLength(secAddr), 8);
+
+*/
+
+/// <summary>初始化</summary>
+/// <param name="ctl"></param>
+/// <param name="api">NOR FLASH 接口</param>
+/// <param name="sad">FLASH 块地址数组</param>
+/// <param name="sadlen">块数组长度</param>
+/// <param name="ccnt">块内 存放配置的份数</param>
+/// <returns>0 无错</returns>
+int FCfgInit(FCfgCtrl_t* ctl, NorFlash_t* api, uint* sad, byte sadlen, byte ccnt);
+
+/// <summary>扫描整个 FLASH 存储区,找到最新且有效的配置取出来</summary>
+/// <param name="ctl"></param>
+/// <param name="cfg"></param>
+/// <returns></returns>
+bool FCfgLoad(FCfgCtrl_t* ctl, Config_t* cfg);
+
+/// <summary>保存配置</summary>
+/// <param name="ctl"></param>
+/// <param name="cfg"></param>
+/// <returns></returns>
+bool FCfgSave(FCfgCtrl_t* ctl, Config_t* cfg);
+
+/// <summary>删除一个配置,应该用不到</summary>
+/// <param name="ctl"></param>
+/// <param name="idx"></param>
+/// <returns></returns>
+bool FCfgClean(FCfgCtrl_t* ctl, int idx);
+
+/// <summary>擦除所有 FLASH 区域,一个不留</summary>
+/// <param name="ctl"></param>
+/// <returns></returns>
+bool FCfgCleanAll(FCfgCtrl_t* ctl);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Modified +17 -159
diff --git a/Core/MyList.c b/Core/MyList.c
index 9357acd..8abea7d 100644
--- a/Core/MyList.c
+++ b/Core/MyList.c
@@ -1,161 +1,19 @@
-
-#include "MyList.h"
-
-// #define ListPrintf		DebugPrintf
-#define ListPrintf(...)
-
-/*
-后期优化措施,减少malloc  free   使用C# List策略    批量申请,自动扩容。
-另外  如果重要数据,上层做处理,定期写入Flash然后 再读出,避免内存泄漏!!!
-*/
-
-void ListInit(MyList_t* list)
-{
-	list->head = NULL;
-	list->count = 0;
-}
-
-bool ListAdd(MyList_t* list, void* data, isEquiFunc isEqui)
-{
-	if ((list->head) == NULL)
-	{
-		MyListItem_t* item = (MyListItem_t*)MyListMalloc(sizeof(MyListItem_t));
-		if (!item)return false;
-		ListPrintf("ListAdd Item %08X : %08X\r\n", item, data);
-		item->Data = data;
-		item->_next = NULL;
-		list->count = 1;
-
-		list->head = item;
-		return true;
-	}
-	else
-	{
-		if (isEqui != NULL)
-		{
-			if (ListFindItem(list, data, isEqui) != NULL)
-			{
-				ListPrintf("ListAdd this data exist.\r\n");
-				return true;
-			}
-		}
-		MyListItem_t* item = (MyListItem_t*)MyListMalloc(sizeof(MyListItem_t));
-		if (!item)return false;
-		ListPrintf("ListAdd Item %08X : %08X\r\n", item, data);
-		item->Data = data;
-		item->_next = list->head;
-
-		list->count++;
-		list->head = item;
-		return true;
-	}
-}
-
-void* ListFind(MyList_t* list, void* data, isEquiFunc isEqui)
+#include "MyList.h"
+
+/**
+ * 获取链表长度
+ * @param head 链表头指针
+ * @return 链表节点数量(不包括头节点)
+ */
+uint ListGetLength(ListHead* head)
 {
-	MyListItem_t* item = list->head;
-	while (1)
-	{
-		if (item == NULL)break;
-
-		if (isEqui(item->Data, data))break;
-
-		item = item->_next;
-	}
-	if (item != NULL) return item->Data;
-	return NULL;
-}
-
-MyListItem_t* ListFindItem(MyList_t* list, void* data, isEquiFunc isEqui)
-{
-	MyListItem_t* item = list->head;
-	while (1)
-	{
-		if (item == NULL)break;
-
-		if (isEqui(item->Data, data))break;
-
-		item = item->_next;
-	}
-	return item;
-}
-
-bool ListRemove(MyList_t* list, void* data, isEquiFunc isEqui)
-{
-	MyListItem_t* pre = list->head;
-	MyListItem_t* item = list->head;
-	while (1)
-	{
-		if (item == NULL)break;
-
-		if (isEqui(item->Data, data))
-		{
-			if (pre == item)
-				list->head = item->_next;
-			else
-				pre->_next = item->_next;
-
-			list->count--;
-			ListPrintf("ListRemove Item %08X : %08X\r\n", item, item->Data);
-			MyListFree(item);
-			return true;
-		}
-		pre = item;
-		item = item->_next;
-	}
-	return false;
-}
-
-bool ListRemoveWithCallBack(MyList_t* list, void* data, isEquiFunc isEqui, ListCallBack callBack)
-{
-	MyListItem_t* pre = list->head;
-	MyListItem_t* item = list->head;
-	while (1)
-	{
-		if (item == NULL)break;
-
-		if (isEqui(item->Data, data))
-		{
-			if (pre == item)
-				list->head = item->_next;
-			else
-				pre->_next = item->_next;
-
-			list->count--;
-			ListPrintf("ListRemove Item %08X : %08X  &  callback:\r\n", item, item->Data);
-			callBack(item->Data);
-			MyListFree(item);		// while内有判断  此处item不为NULL
-			return true;
-		}
-		pre = item;
-		item = item->_next;
-	}
-
-	return false;
-}
-
-void* ListChange(MyList_t* list, void* src, void* dst, isEquiFunc isEqui)
-{
-	// if ((*head) == NULL)return NULL;
-
-	MyListItem_t* item = list->head;
-	while (1)
-	{
-		if (item == NULL)break;;
-
-		if (isEqui(item->Data, src))
-		{
-			ListPrintf("ListChange Item %08X   %08X -> %08X\r\n", item, src, dst);
-			item->Data = dst;
-			break;
-		}
-		item = item->_next;
-	}
-	if (item == NULL)
-	{
-		ListPrintf("ListChange Fail,src exist\r\n");
-		return NULL;
-	}
-
-	return item->Data;
+    uint length = 0;
+    ListNode* node;
+    
+    ListForEach(node, head)
+    {
+        length++;
+    }
+    
+    return length;
 }
Modified +235 -32
diff --git a/Core/MyList.h b/Core/MyList.h
index 713ab3c..53746e8 100644
--- a/Core/MyList.h
+++ b/Core/MyList.h
@@ -6,54 +6,257 @@
 #include "Type.h"
 #include "Debug.h"
 
-#include "FreeRTOS.h"
+/**
+ * 侵入式双向循环链表
+ * 参考Linux内核链表实现
+ * 使用方法:在结构体中包含 ListHead 成员
+ */
 
+/* 链表节点定义 */
+typedef struct ListNode
+{
+    struct ListNode* Previous;
+    struct ListNode* Next;
+} ListNode;
+
+/* 链表头定义(与节点结构相同) */
+typedef ListNode ListHead;
+
+/**
+ * 初始化链表头
+ * @param head 链表头指针
+ */
+static inline void InitListHead(ListHead* head)
+{
+    head->Previous = head;
+    head->Next = head;
+}
+
+/**
+ * 判断链表是否为空
+ * @param head 链表头指针
+ * @return true 表示空,false 表示非空
+ */
+static inline bool ListIsEmpty(const ListHead* head)
+{
+    return head->Next == head;
+}
+
+/**
+ * 判断链表是否只有一个节点(只有头节点)
+ * @param head 链表头指针
+ * @return true 表示只有头节点,false 表示有多于一个节点
+ */
+static inline bool ListIsSingle(const ListHead* head)
+{
+    return head->Next == head->Previous;
+}
+
+/**
+ * 在两个节点之间插入新节点
+ * @param prev 前驱节点
+ * @param next 后继节点
+ * @param newNode 要插入的新节点
+ */
+static inline void ListInsertBetween(ListNode* prev, ListNode* next, ListNode* newNode)
+{
+    next->Previous = newNode;
+    newNode->Next = next;
+    newNode->Previous = prev;
+    prev->Next = newNode;
+}
 
-#define MyListMalloc pvPortMalloc
-#define MyListFree vPortFree
+/**
+ * 在链表头部插入节点(在head之后插入)
+ * @param head 链表头指针
+ * @param newNode 要插入的新节点
+ */
+static inline void ListAdd(ListHead* head, ListNode* newNode)
+{
+    ListInsertBetween(head, head->Next, newNode);
+}
 
-// 内部使用一些Cache,避免 malloc 太占 cpu 资源
-// #define ListItemCacheSize 5
+/**
+ * 在链表尾部插入节点(在head之前插入,即链表末尾)
+ * @param head 链表头指针
+ * @param newNode 要插入的新节点
+ */
+static inline void ListAddTail(ListHead* head, ListNode* newNode)
+{
+    ListInsertBetween(head->Previous, head, newNode);
+}
 
-/*
-	List结构
-	单向链表,一个数据指针,一个结构体next指针。
-	对比数据是否相等,采用钩子函数完成。isEquiFunc  多半函数提供此钩子
-	删除数据项的时候提供其它动作的ListCallBack钩子,可以做数据项释放等操作。
-	强烈建议  定义了List_t 后 ListInit()初始化一下  避免拿到的内存有脏数据。
-*/
+/**
+ * 从链表中删除节点
+ * @param node 要删除的节点
+ */
+static inline void ListDel(ListNode* node)
+{
+    node->Previous->Next = node->Next;
+    node->Next->Previous = node->Previous;
+    node->Previous = NULL;
+    node->Next = NULL;
+}
+
+/**
+ * 从链表中删除节点并重新初始化
+ * @param node 要删除的节点
+ */
+static inline void ListDelInit(ListNode* node)
+{
+    ListDel(node);
+    InitListHead(node);
+}
 
-struct MyListItem
+/**
+ * 将节点从一个链表移动到另一个链表的头部
+ * @param head 目标链表头指针
+ * @param node 要移动的节点
+ */
+static inline void ListMove(ListHead* head, ListNode* node)
 {
-	void*		Data;		// 链表数据项
-	struct MyListItem* _next;	// 链表连接项
-};
-typedef struct MyListItem MyListItem_t;
+    ListDel(node);
+    ListAdd(head, node);
+}
 
-typedef struct
+/**
+ * 将节点从一个链表移动到另一个链表的尾部
+ * @param head 目标链表头指针
+ * @param node 要移动的节点
+ */
+static inline void ListMoveTail(ListHead* head, ListNode* node)
 {
-	MyListItem_t* head;	// 头指针
-	int count;			// 数据项计数
-}MyList_t;
+    ListDel(node);
+    ListAddTail(head, node);
+}
+
+/**
+ * 遍历链表(不安全,不能在遍历时删除节点)
+ * @param pos 当前遍历到的节点指针
+ * @param head 链表头指针
+ */
+#define ListForEach(pos, head) \
+    for (pos = (head)->Next; pos != (head); pos = pos->Next)
+
+/**
+ * 遍历链表(安全版本,可以在遍历时删除节点)
+ * @param pos 当前遍历到的节点指针
+ * @param n 用于临时存储下一个节点的指针
+ * @param head 链表头指针
+ */
+#define ListForEachSafe(pos, n, head) \
+    for (pos = (head)->Next, n = pos->Next; pos != (head); \
+         pos = n, n = pos->Next)
+
+/**
+ * 遍历链表,从尾部开始(不安全)
+ * @param pos 当前遍历到的节点指针
+ * @param head 链表头指针
+ */
+#define ListForEachPrev(pos, head) \
+    for (pos = (head)->Previous; pos != (head); pos = pos->Previous)
+
+/**
+ * 遍历链表,从尾部开始(安全版本)
+ * @param pos 当前遍历到的节点指针
+ * @param n 用于临时存储上一个节点的指针
+ * @param head 链表头指针
+ */
+#define ListForEachPrevSafe(pos, n, head) \
+    for (pos = (head)->Previous, n = pos->Previous; pos != (head); \
+         pos = n, n = pos->Previous)
+
+/**
+ * 通过链表节点获取父结构体指针
+ * @param node 链表节点指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListEntry(node, type, member) \
+    container_of(node, type, member)
 
-typedef bool(*isEquiFunc)(void* data1, void* data2);
-typedef bool(*ListCallBack)(void* data);
+/**
+ * 遍历链表并获取父结构体(不安全版本)
+ * @param pos 存储父结构体指针的变量
+ * @param head 链表头指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListForEachEntry(pos, head, type, member) \
+    for (pos = ListEntry((head)->Next, type, member); \
+         &pos->member != (head); \
+         pos = ListEntry(pos->member.Next, type, member))
 
-void ListInit(MyList_t* list);
+/**
+ * 遍历链表并获取父结构体(安全版本)
+ * @param pos 存储父结构体指针的变量
+ * @param n 临时存储下一个父结构体指针的变量
+ * @param head 链表头指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListForEachEntrySafe(pos, n, head, type, member) \
+    for (pos = ListEntry((head)->Next, type, member), \
+         n = ListEntry(pos->member.Next, type, member); \
+         &pos->member != (head); \
+         pos = n, n = ListEntry(n->member.Next, type, member))
 
-bool ListAdd(MyList_t* list, void* data, isEquiFunc isEqui);
+/**
+ * 遍历链表并获取父结构体,从尾部开始(不安全版本)
+ * @param pos 存储父结构体指针的变量
+ * @param head 链表头指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListForEachEntryPrev(pos, head, type, member) \
+    for (pos = ListEntry((head)->Previous, type, member); \
+         &pos->member != (head); \
+         pos = ListEntry(pos->member.Previous, type, member))
 
-void* ListFind(MyList_t* list, void* data, isEquiFunc isEqui);
+/* 链表相关函数声明 */
 
-bool ListRemove(MyList_t* list, void* data, isEquiFunc isEqui);
+/**
+ * 获取链表长度
+ * @param head 链表头指针
+ * @return 链表节点数量(不包括头节点)
+ */
+uint ListGetLength(ListHead* head);
 
-bool ListRemoveWithCallBack(MyList_t* list, void* data, isEquiFunc isEqui, ListCallBack callBack);
+/**
+ * 获取链表第一个节点的数据(如果为空返回NULL)
+ * @param head 链表头指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListFirstEntry(head, type, member) \
+    (ListIsEmpty(head) ? NULL : ListEntry((head)->Next, type, member))
 
-void* ListChange(MyList_t* list, void* src, void* dst, isEquiFunc isEqui);
+/**
+ * 获取链表最后一个节点的数据(如果为空返回NULL)
+ * @param head 链表头指针
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListLastEntry(head, type, member) \
+    (ListIsEmpty(head) ? NULL : ListEntry((head)->Previous, type, member))
 
-// 纠结是否放出来使用
-MyListItem_t* ListFindItem(MyList_t* list, void* data, isEquiFunc isEqui);
+/**
+ * 获取下一个节点的数据
+ * @param node 当前节点
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListNextEntry(node, type, member) \
+    (ListEntry((node)->member.Next, type, member))
 
+/**
+ * 获取上一个节点的数据
+ * @param node 当前节点
+ * @param type 父结构体类型
+ * @param member 链表节点在父结构体中的成员名
+ */
+#define ListPrevEntry(node, type, member) \
+    (ListEntry((node)->member.Previous, type, member))
 
-#endif // !__List_H__
+#endif
 
Modified +13 -13
diff --git a/Core/StateMachine.c b/Core/StateMachine.c
index 45bb26a..5dc14bb 100644
--- a/Core/StateMachine.c
+++ b/Core/StateMachine.c
@@ -1,17 +1,17 @@
 
 #include "StateMachine.h"
 
-/// @brief 初始化状态机
-/// @param sm 
-/// @param items 
+/// <summary>初始化状态机</summary>
+/// <param name="sm"></param>
+/// <param name="items"></param>
 void StateMachineInit(StateMachine_t* sm, SMItem_t* items)
 {
 	sm->Current = NULL;
 	sm->Next = items;
 }
 
-/// @brief 状态机主循环
-/// @param sm 
+/// <summary>状态机主循环</summary>
+/// <param name="sm"></param>
 void StateMachineMain(StateMachine_t* sm)
 {
     if(sm == NULL)return;
@@ -43,9 +43,9 @@ void StateMachineMain(StateMachine_t* sm)
     }
 }
 
-/// @brief 切换状态
-/// @param sm 
-/// @param next 
+/// <summary>切换状态</summary>
+/// <param name="sm"></param>
+/// <param name="next"></param>
 void StateMachineGo(StateMachine_t* sm, SMItem_t* next)
 {
     if(next == NULL)return;
@@ -54,17 +54,17 @@ void StateMachineGo(StateMachine_t* sm, SMItem_t* next)
 
 /* 延迟状态举例
 
-/// @brief 延迟状态结构
+/// <summary>延迟状态结构</summary>
 typedef struct
 {
     SMItem_t DelayItem;
-    /// @brief 状态机主体,方便处理切换问题
+    /// <summary>状态机主体,方便处理切换问题</summary>
     StateMachine_t* SM;
-    /// @brief 延迟开始时间
+    /// <summary>延迟开始时间</summary>
     Time_t Start;
-    /// @brief 延时时间
+    /// <summary>延时时间</summary>
     int DelayMs;
-    /// @brief 延迟完成后进入的状态
+    /// <summary>延迟完成后进入的状态</summary>
     SMItem_t* Next;
 } SMDelay_t;
 
Modified +6 -6
diff --git a/Core/StateMachine.h b/Core/StateMachine.h
index 1b65765..41718d4 100644
--- a/Core/StateMachine.h
+++ b/Core/StateMachine.h
@@ -6,22 +6,22 @@
 
 typedef struct SMItem
 {
-    /// @brief 状态名称
+    /// <summary>状态名称</summary>
     const char* Name;
 
-    /// @brief 进入状态时执行的动作
+    /// <summary>进入状态时执行的动作</summary>
     void(*Enter)(struct SMItem*, void* sm);
-    /// @brief 运行状态时执行的动作
+    /// <summary>运行状态时执行的动作</summary>
     void (*Run)(struct SMItem*, void* sm);
-    /// @brief 退出状态时执行的动作
+    /// <summary>退出状态时执行的动作</summary>
     void (*Exit)(struct SMItem*, void* sm);
 }SMItem_t;
 
 typedef struct
 {
-    /// @brief 当前状态
+    /// <summary>当前状态</summary>
     struct SMItem* Current;
-    /// @brief 下一个状态
+    /// <summary>下一个状态</summary>
     struct SMItem* Next;
 }StateMachine_t;