فهرست منبع

104协议初版

樊春春 2 سال پیش
والد
کامیت
c417db6838
45فایلهای تغییر یافته به همراه5688 افزوده شده و 1090 حذف شده
  1. 1 3
      Project/GCC/STM32F417IG_FLASH.ld
  2. 2 2
      User/Bsp/armfly_bsp.c
  3. 1 1
      User/Bsp/armfly_bsp.h
  4. 307 423
      User/Bsp/dm9k/dm9k.c
  5. 21 37
      User/Bsp/dm9k/dm9k.h
  6. 0 126
      User/Bsp/eth/stm32f4x7_phy.c
  7. 46 30
      User/Bsp/interface/interface.c
  8. 2 2
      User/Bsp/interface/interface.h
  9. 1 1
      User/Bsp/rtc/rtc.c
  10. 76 153
      User/Bsp/uart/uart1.c
  11. 2 8
      User/Bsp/uart/uart1.h
  12. 1 0
      User/app/fly_config.c
  13. 15 0
      User/app/fly_config.h
  14. 1 0
      User/app/fly_param.c
  15. 1 0
      User/app/fly_param.h
  16. 162 0
      User/app/iec104/PRIO_QUEUE_Iec10x.c
  17. 6 0
      User/app/iec104/PRIO_QUEUE_Iec10x.h
  18. 25 0
      User/app/iec104/common_datatype.h
  19. 0 0
      User/app/iec104/hxcp.c
  20. 1356 0
      User/app/iec104/iec101.c
  21. 198 0
      User/app/iec104/iec101.h
  22. 1575 0
      User/app/iec104/iec104.c
  23. 204 0
      User/app/iec104/iec104.h
  24. 167 0
      User/app/iec104/iec104_init.c
  25. 202 0
      User/app/iec104/iec10x.c
  26. 513 0
      User/app/iec104/iec10x.h
  27. 308 0
      User/app/memory/memory_manager.c
  28. 48 0
      User/app/memory/memory_manager.h
  29. 1 7
      User/app/modbus/modbus.c
  30. 31 1
      User/app/net/net.c
  31. 92 133
      User/config/lwip/lwip_dm9k.c
  32. 1 33
      User/config/lwip/lwip_dm9k.h
  33. 55 22
      User/config/lwip/lwip_eth.c
  34. 3 33
      User/config/lwip/lwip_eth.h
  35. 3 0
      User/config/lwip/lwip_init.c
  36. 30 12
      User/config/lwip/lwip_init.h
  37. 8 8
      User/config/lwip/lwipopts.h
  38. 158 45
      User/config/lwip/port/ethernetif_dm9k.c
  39. 1 1
      User/config/lwip/port/ethernetif_dm9k.h
  40. 8 7
      User/config/lwip/port/ethernetif_eth.c
  41. 0 1
      User/config/lwip/port/ethernetif_eth.h
  42. 19 1
      User/main.c
  43. 2 0
      User/main.h
  44. 31 0
      User/project_var.h
  45. 4 0
      platformio.ini

+ 1 - 3
Project/GCC/STM32F417IG_FLASH.ld

@@ -137,9 +137,7 @@ SECTIONS
   {
     . = ALIGN(4);
     _sccmram = .;       /* create a global symbol at ccmram start */
-    *(.ccmram)
-    *(.ccmram*)
-    
+    KEEP(*(ccmram))
     . = ALIGN(4);
     _eccmram = .;       /* create a global symbol at ccmram end */
   } >CCMRAM AT> FLASH

+ 2 - 2
User/Bsp/armfly_bsp.c

@@ -2,6 +2,8 @@
 
 void bsp_init(void)
 {
+    INT8U err;
+    net_mutex  = OSMutexCreate(15, &err);
     uart1_mbox = OSMboxCreate(NULL);
     uart3_mbox = OSMboxCreate(NULL);
 
@@ -17,8 +19,6 @@ void bsp_init(void)
     uart1_init();
     uart3_init();
 
-    eth_init();
-    dm9k_init();
     lwip_setup();
     // can初始化
     can_network_init();

+ 1 - 1
User/Bsp/armfly_bsp.h

@@ -2,7 +2,6 @@
 #define _ARMFLY_H__
 
 #include "can.h"
-#include "dm9k.h"
 #include "dwt.h"
 #include "fly_param.h"
 #include "interface.h"
@@ -13,4 +12,5 @@
 #include "timer.h"
 #include "uart1.h"
 #include "uart3.h"
+
 #endif

+ 307 - 423
User/Bsp/dm9k/dm9k.c

@@ -17,151 +17,123 @@
 */
 
 #include "dm9k.h"
+#include "interface.h"
+#include "lwip_dm9k.h"
+
+/****************************************************************************
+ * Copyright (C), 2009-2010, www.armfly.com  安富莱电子
+ *
+ * 【本驱动在安富莱STM32F103ZE-EK开发板上调试通过             】
+ * 【QQ: 1295744630, 旺旺:armfly, Email: [email protected]
+ *
+ * 文件名: dm9k_uip.c
+ * 内容简述: Davicom DM9KA uP NIC fast Ethernet driver for uIP.
+ *
+ * 文件历史:
+ * 版本号  日期       作者    说明
+ * v0.1    2010-01-18 armfly  创建该文件
+ *
+ */
 
-uint8_t SendPackOk = 0;
-uint8_t is_fsmc_ok = 0; /* 用于指示FSMC是否初始化 */
+#include "Lwip_init.h"
 
-void dm9k_debug_test(void);
+/* DM9KA 接收函数设置宏 */
+//#define Rx_Int_enable
+#define Max_Int_Count 1
 
-static void dm9k_fsmc(void);
-static void dm9k_initnic(void);
+#define Broadcast_Jump
+#define Max_Broadcast_Lenth 500
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_init
-*	功能说明: uIP 接口函数,初始化网卡.  uIP 接口函数.
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
-void dm9k_init(void)
-{
-    dm9k_fsmc();
+/* DM9KA 传送函数设置宏 */
+#define Max_Send_Pack 2
 
-    is_fsmc_ok = 1;
+//#define FifoPointCheck
+//#define DM9KA_FLOW_CONTROL
+//#define DM9KA_UPTO_100M
+//#define Fifo_Point_Check
+//#define Point_Error_Reset
+#define Fix_Note_Address
+/*=============================================================================
+  系统全域的变量
+  =============================================================================*/
+uint8_t SendPackOk = 0;
 
-    dm9k_initnic(); /* 配置DM9K */
-}
+uint8_t s_FSMC_Init_Ok = 0; /* 用于指示FSMC是否初始化 */
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_fsmc
-*	功能说明: 配置FSMC并口访问时序
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
-static void dm9k_fsmc(void)
-{
-    FSMC_NORSRAMInitTypeDef       FSMC_NORSRAMInitStructure;
-    FSMC_NORSRAMTimingInitTypeDef p;
-
-    /*-- FSMC Configuration ------------------------------------------------------*/
-    /*----------------------- SRAM Bank 3 ----------------------------------------*/
-    /*-- FSMC Configuration ------------------------------------------------------*/
-    p.FSMC_AddressSetupTime      = 6; /* 设置为2会出错; 3正常 */
-    p.FSMC_AddressHoldTime       = 2;
-    p.FSMC_DataSetupTime         = 4; /* 设置为1出错,2正常 */
-    p.FSMC_BusTurnAroundDuration = 1;
-    p.FSMC_CLKDivision           = 0;
-    p.FSMC_DataLatency           = 0;
-    p.FSMC_AccessMode            = FSMC_AccessMode_A;
+//#define printk(...)
+#define printk myprintf
 
-    FSMC_NORSRAMInitStructure.FSMC_Bank                  = FSMC_Bank1_NORSRAM3;
-    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux        = FSMC_DataAddressMux_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_MemoryType            = FSMC_MemoryType_SRAM; // FSMC_MemoryType_PSRAM;
-    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth       = FSMC_MemoryDataWidth_16b;
-    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode       = FSMC_BurstAccessMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait      = FSMC_AsynchronousWait_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity    = FSMC_WaitSignalPolarity_Low;
-    FSMC_NORSRAMInitStructure.FSMC_WrapMode              = FSMC_WrapMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive      = FSMC_WaitSignalActive_BeforeWaitState;
-    FSMC_NORSRAMInitStructure.FSMC_WriteOperation        = FSMC_WriteOperation_Enable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignal            = FSMC_WaitSignal_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode          = FSMC_ExtendedMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WriteBurst            = FSMC_WriteBurst_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
-    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct     = &p;
+void dm9k_debug_test(void);
+void dm9k_udelay(uint16_t time);
 
-    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
+static void dm9k_fsmc(void);
 
-    /*!< Enable FSMC Bank1_SRAM3 Bank */
-    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
+/*******************************************************************************
+ *	函数名: dm9k_udelay
+ *	参  数: time : 延迟时间,不精确,us级别
+ *	返  回: 无
+ *	功  能: 延迟函数
+ */
+void dm9k_udelay(uint16_t time)
+{
+    us_delay(time);
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_ReadReg
-*	功能说明: 读出DM9K指定寄存器的值
-*	形    参: reg 寄存器地址
-*	返 回 值: 寄存器值
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: ior
+ *	参  数: reg :寄存器地址
+ *	返  回: 无
+ *	功  能: 读出寄存器的值
+ */
 uint8_t dm9k_ReadReg(uint8_t reg)
 {
     NET_REG_ADDR = reg;
     return (NET_REG_DATA);
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_WriteReg
-*	功能说明: 读出DM9K指定寄存器的值
-*	形    参: reg :寄存器地址
-*			 writedata : 写入的数据
-*	返 回 值: 无
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: iow
+ *	参  数: reg :寄存器地址
+ *			writedata : 写入的数据
+ *	返  回: 无
+ *	功  能: 写DM9KAE寄存器的值
+ */
 void dm9k_WriteReg(uint8_t reg, uint8_t writedata)
 {
     NET_REG_ADDR = reg;
     NET_REG_DATA = writedata;
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_hash_table
-*	功能说明: 设置 DM9KA MAC 、 广播 、 多播 寄存器
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
-void dm9k_hash_table()
+/*******************************************************************************
+ *	函数名: dm9k_hash_table
+ *	参  数: 无
+ *	返  回: 无
+ *	功  能: 设置 DM9KA MAC 、 广播 、 多播 寄存器
+ */
+void dm9k_hash_table(uint8_t *MacAdd)
 {
     uint8_t i;
 
     /* 设置 网卡 MAC 位置,来自於 MyHardware */
-    dm9k_WriteReg(DM9K_REG_PAR, DM9K_MAC_ADDR0);
-    dm9k_WriteReg(DM9K_REG_PAR + 1, DM9K_MAC_ADDR1);
-    dm9k_WriteReg(DM9K_REG_PAR + 2, DM9K_MAC_ADDR2);
-    dm9k_WriteReg(DM9K_REG_PAR + 3, DM9K_MAC_ADDR3);
-    dm9k_WriteReg(DM9K_REG_PAR + 4, DM9K_MAC_ADDR4);
-    dm9k_WriteReg(DM9K_REG_PAR + 5, DM9K_MAC_ADDR5);
-
-    /* 清除 网卡多播设置 */
-    for (i = 0; i < 8; i++)
-    {
-        dm9k_WriteReg(DM9K_REG_MAR + i, 0x00);
-    }
+    for (i = 0; i < 6; i++)
+        dm9k_WriteReg(DM9K_REG_PAR + i, MacAdd[i]);
 
-    /* 设置 广播包 设置 */
-    dm9k_WriteReg(DM9K_REG_MAR + 7, 0x80);
+    for (i = 0; i < 8; i++) /* 清除 网卡多播设置 */
+        dm9k_WriteReg(DM9K_REG_MAR + i, 0xff);
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_reset
-*	功能说明: 软件复位DM9KAE
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: dm9k_reset
+ *	参  数: 无
+ *	返  回: 无
+ *	功  能: 对DM9KAE进行软件复位
+ */
 void dm9k_reset(void)
 {
     dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET); /* 对 DM9KA 进行软件重置 */
-    us_delay(10);                                /* delay 10us */
+    dm9k_udelay(10);                             /* delay 10us */
     dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET); /* 对 DM9KA 进行软件重置 */
-    us_delay(10);                                /* delay 10us */
+    dm9k_udelay(10);                             /* delay 10us */
 
     /* 基本记存器相关设置 */
     dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF);   /* 开启内存自环模式 */
@@ -194,15 +166,13 @@ void dm9k_reset(void)
     SendPackOk = 0;
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_phy_write
-*	功能说明: 软件复位DM9KAE
-*	形    参: phy_reg : PHY寄存器地址
-*			  writedata : 写入的数据
-*	返 回 值: 无
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: dm9k_phy_write
+ *	参  数: phy_reg : 寄存器地址
+ *			writedata : 写入的数据
+ *	返  回: 无
+ *	功  能: 写DM9KA PHY 寄存器
+ */
 void dm9k_phy_write(uint8_t phy_reg, uint16_t writedata)
 {
     /* 设置写入 PHY 寄存器的位置 */
@@ -213,78 +183,178 @@ void dm9k_phy_write(uint8_t phy_reg, uint16_t writedata)
     dm9k_WriteReg(DM9K_REG_EPDRL, writedata & 0xff);
 
     dm9k_WriteReg(DM9K_REG_EPCR, 0x0a); /* 将资料写入 PHY 寄存器 */
+
     while (dm9k_ReadReg(DM9K_REG_EPCR) & 0x01)
-        ;                               /* 查寻是否执行结束 */
+        ; /* 查寻是否执行结束 */
+
     dm9k_WriteReg(DM9K_REG_EPCR, 0x08); /* 清除写入命令 */
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_initnic
-*	功能说明: 配置DM9KAE芯片(初始化)
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
-static void dm9k_initnic(void)
+/*******************************************************************************
+ *	函数名: dm9k_phy_read
+ *	参  数: phy_reg : 寄存器地址
+ *	返  回: 无
+ *	功  能: 读DM9KA PHY 寄存器
+ */
+uint16_t dm9k_phy_read(uint8_t phy_reg)
+{
+    uint16_t temp;
+
+    /* 设置写入 PHY 寄存器的位置 */
+    dm9k_WriteReg(DM9K_REG_EPAR, phy_reg | DM9K_PHY);
+
+    /* 设置写入 PHY 寄存器的值 */
+    dm9k_WriteReg(DM9K_REG_EPCR, 0x0C); //选中PHY,发送读命令
+
+    while (dm9k_ReadReg(DM9K_REG_EPCR) & 0x01)
+        ; /* 查寻是否执行结束 */
+
+    dm9k_WriteReg(DM9K_REG_EPCR, 0x00); //清除读命令
+    temp = (dm9k_ReadReg(DM9K_REG_EPDRH) << 8) | (dm9k_ReadReg(DM9K_REG_EPDRL));
+
+    return temp;
+}
+
+/*******************************************************************************
+ *	函数名: dm9k_linkstat
+ *	参  数: 无
+ *	返  回: 0,未连接
+ *			1,已连接
+ *	功  能: 获取DM9K的连接状态
+ */
+uint8_t dm9k_linkstat(void)
+{
+    uint8_t linkchanged = 0;
+
+    linkchanged = (dm9k_ReadReg(DM9K_PHY_BMSR) >> 6) & 0x01;
+
+    return linkchanged;
+}
+
+/*******************************************************************************
+ *	函数名: DM9K_Get_SpeedAndDuplex
+ *	参  数: 无
+ *	返  回: 0,100M半双工
+ *			1,100M全双工
+ *			2,10M半双工
+ *			3,10M全双工
+ *			0XFF,连接失败!
+ *	功  能: 获取DM9K的连接速度和双工模式
+ */
+uint8_t DM9K_Get_SpeedAndDuplex(void)
 {
+    uint8_t temp;
+    uint8_t i = 0;
+
+    while (!(dm9k_phy_read(DM9K_PHY_BMSR) & 0x0020)) //等待自动协商完成
+    {
+        ms_delay(100);
+        i++;
+
+        if (i > 100)
+            return 0XFF; //自动协商失败
+    }
+
+    temp = ((dm9k_ReadReg(DM9K_REG_NSR) >> 6) & 0x02);  //获取DM9K的连接速度 0:100M 1:10M
+    temp |= ((dm9k_ReadReg(DM9K_REG_NCR) >> 3) & 0x01); //获取DM9K的双工状态
+
+    return temp;
+}
+
+/*******************************************************************************
+ *	函数名: dm9k_initnic
+ *	参  数: 无
+ *	返  回: 无
+ *	功  能: 初始化DM9KAE
+ */
+void dm9k_initnic(void)
+{
+    //	uint8_t temp;
+
+    if (DM9KA_ID != dm9k_ReadID()) /* 进行 设备ID读取判断 */
+        return;
+
+    dm9k_WriteReg(DM9K_REG_GPCR, 0x01); /* 设置GPCR bit[0]=1,使DM9K为GPIO0为输出 */
+    dm9k_WriteReg(DM9K_REG_GPR, 0x00);  /* GPR bit[0]=0,使GPIO0输出低电平以激活内部PHY */
+    ms_delay(5);
+
+    dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET); /* 对 DM9KA 进行软件重置 */
+    dm9k_udelay(100);                            /* delay 100us */
     dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET); /* 对 DM9KA 进行软件重置 */
-    us_delay(10);                                /* delay 10us */
+    dm9k_udelay(100);                            /* delay 100us */
 
-    dm9k_hash_table(); /* 设置 DM9KA MAC 及 多播*/
+    /* 清除多余资讯 */
+    dm9k_WriteReg(DM9K_REG_NCR, 0x00); /* 复位完成,设置正常工作模式 */
+    dm9k_WriteReg(DM9K_REG_NSR, 0x2c); /* 清除各种状态标志位 */
+    dm9k_WriteReg(DM9K_REG_TCR, 0x00); /* 清除 发送控制寄存器 */
+    dm9k_WriteReg(DM9K_REG_ISR, 0x3f); /* 清除 中断状态寄存器 */
+
+    /* 基本记存器相关设置 */
+    dm9k_WriteReg(DM9K_REG_IMR, 0x80);  /* 开启内存自环模式 */
+    dm9k_WriteReg(DM9K_REG_TCR2, 0x80); /* 设置 LED 显示模式1:全双工亮,半双工灭 */
+
+    dm9k_WriteReg(DM9K_REG_BPTR, 0x3F); /* 半双工流控设置 默认 0x37 */
+    dm9k_WriteReg(DM9K_REG_FCTR, 0x38); /* 全双工流控设置 默认 0x38 */
 
-    dm9k_reset(); /* 进行 DM9KA 软件设置 */
+    dm9k_WriteReg(DM9K_REG_RCR, DM9K_RCR_SET); /* 开启 接收工能 */
+
+    dm9k_hash_table(dm9kdev.mac); /* 设置 DM9KA MAC 及 多播*/
 
     dm9k_WriteReg(DM9K_REG_GPR, DM9K_PHY_OFF); /* 关闭 PHY ,进行 PHY 设置*/
-    dm9k_phy_write(0x00, 0x8000);              /* 重置 PHY 的寄存器 */
-#ifdef DM9KA_FLOW_CONTROL
-    dm9k_phy_write(0x04, 0x01e1 | 0x0400); /* 设置 自适应模式相容表 */
-#else
-    dm9k_phy_write(0x04, 0x01e1);              /* 设置 自适应模式相容表 */
-#endif
-    // dm9k_phy_write(0x00, 0x1000);					/* 设置 基本连接模式 */
+    dm9k_phy_write(DM9K_PHY_BMCR, 0x8000);     /* 重置 PHY 的寄存器 */
+
     /* 连接模式设置
-      0x0000 : 固定10M半双工
-      0x0100 : 固定10M全双工
-      0x2000 : 固定100M半双工
-      0x2100 : 固定100M全双工
-      0x1000 : 自适应模式
+      0x0000 : 固定10M半双工	ANAR_Value:0x21
+      0x0100 : 固定10M全双工	ANAR_Value:0x41
+      0x2000 : 固定100M半双工	ANAR_Value:0x81
+      0x2100 : 固定100M全双工	ANAR_Value:0x0101
+      0x1000 : 自适应模式		ANAR_Value:0x01E1
     */
-    dm9k_phy_write(0x00, 0x1000); /* 设置 基本连接模式 */
+    dm9k_phy_write(DM9K_PHY_BMCR, 0x1000); /* 设置 基本连接模式 */
+    dm9k_phy_write(DM9K_PHY_ANAR, 0x01E1); /* 设置 自适应模式相容表 */
 
     dm9k_WriteReg(DM9K_REG_GPR, DM9K_PHY_ON); /* 结束 PHY 设置, 开启 PHY */
 
+    //	temp = DM9K_Get_SpeedAndDuplex();				/* 获取DM9K的连接速度和双工状态 */
+    //	if(temp != 0xFF)								/* 连接成功,通过串口显示连接速度和双工状态 */
+    //	{
+    //		myprintf("DM9K Speed:%dMbps,Duplex:%s duplex mode\r\n", (temp & 0x02) ? 10 : 100, (temp & 0x01) ? "Full" : "Half");
+    //	}
+    //	else
+    //	{
+    //		myprintf("DM9K Establish Link Failed!\r\n");
+    //	}
+
     dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 设置中断 */
 
     EXTI_InitTypeDef EXTI_InitStructure;
     NVIC_InitTypeDef NVIC_InitStructure;
 
-    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource14);
-
+    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, GPIO_PinSource15);
     /* 配置 EXTI LineXXX */
-    EXTI_InitStructure.EXTI_Line    = EXTI_Line2 | EXTI_Line3 | EXTI_Line7 | EXTI_Line8 | EXTI_Line11 | EXTI_Line13 | EXTI_Line14;
+    EXTI_InitStructure.EXTI_Line    = EXTI_Line15;
     EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
 
+    EXTI_ClearITPendingBit(EXTI_Line15);
+
     NVIC_InitStructure.NVIC_IRQChannel                   = EXTI15_10_IRQn;
-    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
 
-    // dm9k_debug_test();
+    SendPackOk = 0;
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_receive_packet
-*	功能说明: 配置DM9KAE芯片(初始化)
-*	形    参: _uip_buf : 接收结果存放的缓冲区指针
-*	返 回 值: > 0 表示接收的数据长度, 0表示没有数据
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: dm9k_receive_packet
+ *	参  数: _uip_buf : 接收缓冲区
+ *	返  回: > 0 表示接收的数据长度, 0表示没有数据
+ *	功  能: 读取一包数据
+ */
 uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
 {
     uint16_t  ReceiveLength;
@@ -329,8 +399,10 @@ uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
             /* 计算下一个包的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/
             /* 若是超过 0x3fff ,则需回归绕到 0x0c00 起始位置 */
             calc_MRR += (rx_length + 4);
+
             if (rx_length & 0x01)
                 calc_MRR++;
+
             if (calc_MRR > 0x3fff)
                 calc_MRR -= 0x3400;
 
@@ -344,6 +416,7 @@ uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
 
             /* 开始将内存的资料搬到到系统中,每次移动一个 word */
             calc_len = (rx_length + 1) >> 1;
+
             for (i = 0; i < calc_len; i++)
                 ReceiveData[i] = NET_REG_DATA;
 
@@ -353,6 +426,7 @@ uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
             rx_int_count++; /* 累计收包次数 */
 
 #ifdef FifoPointCheck
+
             if (calc_MRR != ((dm9k_ReadReg(DM9K_REG_MRRH) << 8) + dm9k_ReadReg(DM9K_REG_MRRL)))
             {
 #ifdef Point_Error_Reset
@@ -363,6 +437,7 @@ uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
                 dm9k_WriteReg(DM9K_REG_MRRH, (calc_MRR >> 8) & 0xff);
                 dm9k_WriteReg(DM9K_REG_MRRL, calc_MRR & 0xff);
             }
+
 #endif
             return ReceiveLength;
         }
@@ -374,22 +449,23 @@ uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
             }
             else
             {
-                dm9k_reset(); /* 接收指针出错,重置 */
+                dm9k_initnic(); /* 接收指针出错,重置 */
             }
+
             return (0);
         }
     } while (rx_int_count < Max_Int_Count); /* 是否超过最多接收封包计数 */
+
     return 0;
 }
 
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_send_packet
-*	功能说明: 发送一包数据
-*	形    参: p_char : 发送数据缓冲区
-*	返 回 值: length : 数据长度
-*********************************************************************************************************
-*/
+/*******************************************************************************
+ *	函数名: dm9k_send_packet
+ *	参  数: p_char : 发送数据缓冲区
+ *			length : 数据长度
+ *	返  回: 无
+ *	功  能: 发送一包数据
+ */
 void dm9k_send_packet(uint8_t *p_char, uint16_t length)
 {
     uint16_t      SendLength = length;
@@ -398,27 +474,18 @@ void dm9k_send_packet(uint8_t *p_char, uint16_t length)
     uint16_t      calc_len;
     __IO uint16_t calc_MWR;
 
-    /* 检查 DM9KA 是否还在传送中!若是等待直到传送结束 */
-    if (SendPackOk == Max_Send_Pack)
-    {
-        while (dm9k_ReadReg(DM9K_REG_TCR) & DM9K_TCR_SET)
-        {
-            us_delay(5);
-        }
-        SendPackOk = 0;
-    }
-
-    SendPackOk++; /* 设置传送计数 */
-
 #ifdef FifoPointCheck
     /* 计算下一个传送的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/
     /* 若是超过 0x0bff ,则需回归绕到 0x0000 起始位置 */
     calc_MWR = (dm9k_ReadReg(DM9K_REG_MWRH) << 8) + dm9k_ReadReg(DM9K_REG_MWRL);
     calc_MWR += SendLength;
+
     if (SendLength & 0x01)
         calc_MWR++;
+
     if (calc_MWR > 0x0bff)
         calc_MWR -= 0x0c00;
+
 #endif
 
     dm9k_WriteReg(DM9K_REG_TXPLH, (SendLength >> 8) & 0xff); /* 设置传送封包的长度 */
@@ -427,18 +494,24 @@ void dm9k_send_packet(uint8_t *p_char, uint16_t length)
     /* 开始将系统的资料搬到到内存中,每次移动一个 word */
     NET_REG_ADDR = DM9K_REG_MWCMD;
     calc_len     = (SendLength + 1) >> 1;
+
     for (i = 0; i < calc_len; i++)
+    {
         NET_REG_DATA = SendData[i];
+    }
 
     dm9k_WriteReg(DM9K_REG_TCR, DM9K_TCR_SET); /* 进行传送 */
 
 #ifdef FifoPointCheck
+
     if (calc_MWR != ((dm9k_ReadReg(DM9K_REG_MWRH) << 8) + dm9k_ReadReg(DM9K_REG_MWRL)))
     {
 #ifdef Point_Error_Reset
+
         /* 若是指针出错,等待此一封包送完 , 之後进行重置 */
         while (dm9k_ReadReg(DM9K_REG_TCR) & DM9K_TCR_SET)
-            bsp_DelayUS(5);
+            dm9k_udelay(5);
+
         dm9k_reset();
         return;
 #endif
@@ -446,10 +519,26 @@ void dm9k_send_packet(uint8_t *p_char, uint16_t length)
         dm9k_WriteReg(DM9K_REG_MWRH, (calc_MWR >> 8) & 0xff);
         dm9k_WriteReg(DM9K_REG_MWRL, calc_MWR & 0xff);
     }
+
 #endif
     return;
 }
 
+/*******************************************************************************
+ *	函数名: dm9k_init
+ *	参  数: 无
+ *	返  回: 无
+ *	功  能: uIP 接口函数,初始化网卡
+ */
+void dm9k_init(void)
+{
+    dm9k_fsmc();
+
+    s_FSMC_Init_Ok = 1;
+
+    dm9k_initnic();
+}
+
 /*******************************************************************************
  *	函数名: etherdev_send
  *	参  数: p_char : 数据缓冲区
@@ -480,35 +569,8 @@ void etherdev_chkmedia(void)
 
     while (!(dm9k_ReadReg(DM9K_REG_NSR) & DM9K_PHY))
     {
-        us_delay(2000);
-    }
-}
-
-/*
-*********************************************************************************************************
-*	函 数 名: dm9k_interrupt
-*	功能说明: 中断处理函数 (webserver例程未使用中断)
-*	形    参: 无
-*	返 回 值: 无
-*********************************************************************************************************
-*/
-void dm9k_interrupt(void)
-{
-    uint8_t  save_reg;
-    uint16_t isr_status;
-
-    save_reg = NET_REG_ADDR; /* 暂存所使用的位置 */
-
-    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 DM9KA 中断 */
-    isr_status = dm9k_ReadReg(DM9K_REG_ISR);   /* 取得中断产生值 */
-
-    if (isr_status & DM9K_RX_INTR)
-    { /* 检查是否为接收中断 */
-        // dm9k_receive_packet();							/* 执行接收处理程序 */
+        dm9k_udelay(2000);
     }
-
-    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 DM9KA 中断 */
-    NET_REG_ADDR = save_reg;                   /* 回复所使用的位置 */
 }
 
 /*******************************************************************************
@@ -521,234 +583,56 @@ uint32_t dm9k_ReadID(void)
 {
     uint8_t vid1, vid2, pid1, pid2;
 
-    if (is_fsmc_ok == 0)
+    if (s_FSMC_Init_Ok == 0)
     {
+
         dm9k_fsmc();
 
-        is_fsmc_ok = 1;
+        s_FSMC_Init_Ok = 1;
     }
+
     vid1 = dm9k_ReadReg(DM9K_REG_VID_L) & 0xFF;
     vid2 = dm9k_ReadReg(DM9K_REG_VID_H) & 0xFF;
     pid1 = dm9k_ReadReg(DM9K_REG_PID_L) & 0xFF;
     pid2 = dm9k_ReadReg(DM9K_REG_PID_H) & 0xFF;
 
-    return (vid2 << 24) | (vid1 << 16) | (pid2 << 8) | pid1;
+    return (pid2 << 24) | (pid1 << 16) | (vid2 << 8) | vid1;
 }
 
-uint8_t dm9k_linkstat(void)
+static void dm9k_fsmc(void)
 {
-    uint8_t linkchanged = 0;
-
-    linkchanged = (dm9k_ReadReg(DM9K_PHY_BMSR) >> 6) & 0x01;
+    FSMC_NORSRAMInitTypeDef       FSMC_NORSRAMInitStructure;
+    FSMC_NORSRAMTimingInitTypeDef p;
 
-    return linkchanged;
-}
+    /*-- FSMC Configuration ------------------------------------------------------*/
+    /*----------------------- SRAM Bank 3 ----------------------------------------*/
+    /*-- FSMC Configuration ------------------------------------------------------*/
+    p.FSMC_AddressSetupTime      = 3; /* 设置为2会出错; 3正常 */
+    p.FSMC_AddressHoldTime       = 0;
+    p.FSMC_DataSetupTime         = 3; /* 设置为1出错,2正常 */
+    p.FSMC_BusTurnAroundDuration = 0;
+    p.FSMC_CLKDivision           = 0;
+    p.FSMC_DataLatency           = 0;
+    p.FSMC_AccessMode            = FSMC_AccessMode_A;
 
-#if 0
-	/*
-	*********************************************************************************************************
-	*	函 数 名: dm9k_debug_test
-	*	功能说明: 测试DM9KAE的函数,用于排错
-	*	形    参: 无
-	*	返 回 值: 无
-	*********************************************************************************************************
-	*/
-	void dm9k_debug_test(void)
-	{
-		uint32_t check_device;
-		uint8_t  check_iomode;
-		uint8_t  check_reg_fail = 0;
-		uint8_t  check_fifo_fail = 0;
-		uint16_t i;
-		uint16_t j;
-
-		dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET);			/* 对 DM9KA 进行软件重置 */
-		us_delay(10);								/* delay 10us */
-		dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET);			/* 对 DM9KA 进行软件重置 */
-		us_delay(10);								/* delay 10us */
-
-		check_device  = dm9k_ReadReg(DM9K_REG_VID_L);
-		check_device |= dm9k_ReadReg(DM9K_REG_VID_H) << 8;
-		check_device |= dm9k_ReadReg(DM9K_REG_PID_L) << 16;
-		check_device |= dm9k_ReadReg(DM9K_REG_PID_H) << 24;
-
-		if(check_device != 0x90000A46)
-		{
-			printk("DM9K_DEBUG ==> DEIVCE NOT FOUND, SYSTEM HOLD !!\n");
-			while(1);
-		}
-		else
-		{
-			printk("DM9K_DEBUG ==> DEIVCE FOUND !!\n");
-		}
-
-		check_iomode = dm9k_ReadReg(DM9K_REG_ISR) >> 6;
-		if(check_iomode != DM9K_WORD_MODE)
-		{
-			printk("DM9K_DEBUG ==> DEIVCE NOT WORD MODE, SYSTEM HOLD !!\n");
-			while(1);
-		}
-		else
-		{
-			printk("DM9K_DEBUG ==> DEIVCE IS WORD MODE !!\n");
-		}
-
-		printk("DM9K_DEBUG ==> REGISTER R/W TEST !!\n");
-		NET_REG_ADDR = DM9K_REG_MAR;
-		for(i = 0; i < 0x0100; i++)
-		{
-			NET_REG_DATA = i;
-			if(i != (NET_REG_DATA & 0xff))
-			{
-				printk("             > error W %02x , R %02x \n", i , NET_REG_DATA);
-				check_reg_fail = 1;
-			}
-		}
-
-		if(check_reg_fail)
-		{
-			printk("DM9K_DEBUG ==> REGISTER R/W FAIL, SYSTEM HOLD !!\n");
-			while(1);
-		}
-
-		printk("DM9K_DEBUG ==> FIFO R/W TEST !!\n");
-		printk("DM9K_DEBUG ==> FIFO WRITE START POINT 0x%02x%02x \n",
-				dm9k_ReadReg(DM9K_REG_MWRH), dm9k_ReadReg(DM9K_REG_MWRL));
-
-		NET_REG_ADDR = DM9K_REG_MWCMD;
-		for(i = 0; i < 0x1000; i++)
-			NET_REG_DATA = ((i & 0xff) * 0x0101);
-
-		printk("DM9K_DEBUG ==> FIFO WRITE END POINT 0x%02x%02x \n",
-				dm9k_ReadReg(DM9K_REG_MWRH), dm9k_ReadReg(DM9K_REG_MWRL));
-
-		if((dm9k_ReadReg(DM9K_REG_MWRH) != 0x20) || (dm9k_ReadReg(DM9K_REG_MWRL) != 0x00))
-		{
-			printk("DM9K_DEBUG ==> FIFO WRITE FAIL, SYSTEM HOLD !!\n");
-			while(1);
-		}
-
-		dm9k_ReadReg(DM9K_REG_MRCMDX);
-		printk("DM9K_DEBUG ==> FIFO READ START POINT 0x%02x%02x \n",
-				dm9k_ReadReg(DM9K_REG_MRRH), dm9k_ReadReg(DM9K_REG_MRRL));
-		dm9k_ReadReg(DM9K_REG_MRCMDX);
-
-		NET_REG_ADDR = DM9K_REG_MRCMD;
-		for(i = 0; i < 0x1000; i++)
-		{
-			j = NET_REG_DATA;
-
-			if(((i & 0xff) * 0x0101) != j)
-			{
-				//printk("             > error W %04x , R %04x \n",
-				//		((i & 0xff) * 0x0101) , j);
-				check_fifo_fail = 1;
-			}
-		}
-
-		printk("DM9K_DEBUG ==> FIFO READ END POINT 0x%02x%02x \n",
-				dm9k_ReadReg(DM9K_REG_MRRH), dm9k_ReadReg(DM9K_REG_MRRL));
-
-		if((dm9k_ReadReg(DM9K_REG_MRRH) != 0x20) || (dm9k_ReadReg(DM9K_REG_MRRL) != 0x00))
-		{
-			printk("DM9K_DEBUG ==> FIFO WRITE FAIL, SYSTEM HOLD !!\n");
-			while(1);
-		}
-
-			if(check_fifo_fail)
-		{
-			printk("DM9K_DEBUG ==> FIFO R/W DATA FAIL, SYSTEM HOLD !!\n");
-			while(1);
-		}
-
-		printk("DM9K_DEBUG ==> PACKET SEND & INT TEST !! \n");
-		dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET);
-		us_delay(10);
-		dm9k_WriteReg(DM9K_REG_NCR, DM9K_REG_RESET);
-		us_delay(10);
-
-		dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF | DM9K_TX_INTR);
-
-		dm9k_WriteReg(DM9K_REG_TXPLH, 0x01);
-		dm9k_WriteReg(DM9K_REG_TXPLL, 0x00);
-
-		do
-		{
-			dm9k_WriteReg(DM9K_REG_ISR, DM9K_TX_INTR);
-			printk("DM9K_DEBUG ==> INT PIN IS OFF\n");
-
-			NET_REG_ADDR = DM9K_REG_MWCMD;
-			for(i = 0; i < (0x0100 / 2); i++)
-			{
-				if(i < 3)
-					NET_REG_DATA = 0xffff;
-				else
-					NET_REG_DATA = i * 0x0101;
-			}
-
-			printk("DM9K_DEBUG ==> PACKET IS SEND \n");
-			dm9k_WriteReg(DM9K_REG_TCR, DM9K_TCR_SET);
-
-			while(dm9k_ReadReg(DM9K_REG_TCR) & DM9K_TCR_SET) bsp_DelayUS (5);
-			if(dm9k_ReadReg(DM9K_REG_ISR) & DM9K_TX_INTR)
-				printk("DM9K_DEBUG ==> INT PIN IS ACTIVE \n");
-			else
-				printk("DM9K_DEBUG ==> INT PIN IS NOT ACTIVE \n");
-
-			for(i = 0; i < 10; i++)
-				bsp_DelayUS(1000);
-
-		}while(1);
-	}
-
-	/*
-	*********************************************************************************************************
-	*	函 数 名: etherdev_chkmedia
-	*	功能说明: 检测网络连接状态
-	*	形    参: 无
-	*	返 回 值: 无
-	*********************************************************************************************************
-	*/
-	void etherdev_chkmedia(void)
-	{
-	//	uint8_t status;
-
-		while(!(dm9k_ReadReg(DM9K_REG_NSR) & DM9K_PHY))
-		{
-			bsp_DelayUS(2000);
-		}
-	}
-
-
-	/*******************************************************************************
-	*	函数名: etherdev_poll
-	*	参  数: 无
-	*	返  回: 无
-	*	功  能: uIP 接口函数, 采用查询方式接收一个IP包
-	*/
-	/*
-	                              etherdev_poll()
-
-	    This function will read an entire IP packet into the uip_buf.
-	    If it must wait for more than 0.5 seconds, it will return with
-	    the return value 0. Otherwise, when a full packet has been read
-	    into the uip_buf buffer, the length of the packet is returned.
-	*/
-	uint16_t etherdev_poll(void)
-	{
-		uint16_t bytes_read = 0;
-#if 0
-
-		/* tick_count threshold should be 12 for 0.5 sec bail-out
-			One second (24) worked better for me, but socket recycling
-			is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
-			to counter this. Retransmission timing etc. is affected also. */
-		while ((!(bytes_read = etherdev_read())) && (timer0_tick() < 12)) continue;
-
-		timer0_reset();
+    FSMC_NORSRAMInitStructure.FSMC_Bank                  = FSMC_Bank1_NORSRAM3;
+    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux        = FSMC_DataAddressMux_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_MemoryType            = FSMC_MemoryType_SRAM; // FSMC_MemoryType_PSRAM;
+    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth       = FSMC_MemoryDataWidth_16b;
+    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode       = FSMC_BurstAccessMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait      = FSMC_AsynchronousWait_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity    = FSMC_WaitSignalPolarity_Low;
+    FSMC_NORSRAMInitStructure.FSMC_WrapMode              = FSMC_WrapMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive      = FSMC_WaitSignalActive_BeforeWaitState;
+    FSMC_NORSRAMInitStructure.FSMC_WriteOperation        = FSMC_WriteOperation_Enable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignal            = FSMC_WaitSignal_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode          = FSMC_ExtendedMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WriteBurst            = FSMC_WriteBurst_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
+    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct     = &p;
 
-#endif
-		return bytes_read;
-	}
+    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
 
-#endif
+    /*!< Enable FSMC Bank1_SRAM3 Bank */
+    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
+}

+ 21 - 37
User/Bsp/dm9k/dm9k.h

@@ -15,37 +15,9 @@
 
 #include "dwt.h"
 #include "includes.h"
-#include "lwip_dm9k.h"
+#include "lwip_init.h"
 #include <inttypes.h>
 
-// #define TCP_PORT 8080
-
-#define NET_BASE_ADDR 0x68400000
-#define NET_REG_ADDR  (*((volatile uint16_t *)NET_BASE_ADDR))
-#define NET_REG_DATA  (*((volatile uint16_t *)(NET_BASE_ADDR + 0x00080000)))
-
-//#define DM9KA_FLOW_CONTROL
-//#define DM9KA_UPTO_100M
-//#define Fifo_Point_Check
-//#define Point_Error_Reset
-#define Fix_Note_Address
-//#define FifoPointCheck
-
-/* DM9KA 接收函数设置宏 */
-//#define Rx_Int_enable
-#define Max_Int_Count      1
-#define Max_Ethernet_Lenth 1536
-#define Broadcast_Jump
-#define Max_Broadcast_Lenth 500
-
-/* DM9KA 传送函数设置宏 */
-#define Max_Send_Pack 2
-
-#define ETH_ADDR_LEN 6
-
-// uint8_t SendPackOk = 0;
-// uint8_t is_fsmc_ok = 0; /* 用于指示FSMC是否初始化 */
-
 /* DM9K REGISTER LIST */
 #define DM9K_REG_NCR    0x00
 #define DM9K_REG_NSR    0x01
@@ -92,7 +64,7 @@
 #define DM9K_REG_IMR    0xFF
 
 /* 相关宏设置 */
-#define DM9KA_ID_OK 0x0A469000
+#define DM9KA_ID 0x90000A46
 
 #define DM9K_BYTE_MODE 0x01
 #define DM9K_WORD_MODE 0x00
@@ -136,17 +108,29 @@
 #define DM9K_PHY_PWDOR   0x13
 #define DM9K_PHY_SCR     0x14
 
+#define DM9K_INTPORT GPIOA
+#define DM9K_INTPIN  GPIO_PIN_15
+
+#define NET_BASE_ADDR 0x68400000
+#define NET_REG_ADDR  (*((volatile uint16_t *)NET_BASE_ADDR))
+#define NET_REG_DATA  (*((volatile uint16_t *)(NET_BASE_ADDR + 0x00080000)))
+
+#define Max_Ethernet_Lenth 1536
+
 /* EXPORTED SUBPROGRAM SPECIFICATIONS */
-void     dm9k_init(void);
-uint8_t  dm9k_linkstat(void);
-void     dm9k_send_packet(uint8_t *p_char, uint16_t length);
-uint16_t dm9k_receive_packet(uint8_t *_uip_buf);
+void    dm9k_init(void);
+uint8_t dm9k_linkstat(void);
+
+uint8_t dm9k_ReadReg(uint8_t reg);
+void    dm9k_WriteReg(uint8_t reg, uint8_t writedata);
+
 void     etherdev_send(uint8_t *p_char, uint16_t length);
 uint16_t etherdev_read(uint8_t *p_char);
-void     dm9k_WriteReg(uint8_t reg, uint8_t writedata);
-uint8_t  dm9k_ReadReg(uint8_t reg);
-void     etherdev_chkmedia(void);
+uint16_t dm9k_receive_packet(uint8_t *_uip_buf);
 
+void     etherdev_chkmedia(void);
 uint32_t dm9k_ReadID(void);
 
+void dm9k_debug_test(void);
+
 #endif

+ 0 - 126
User/Bsp/eth/stm32f4x7_phy.c

@@ -243,129 +243,3 @@ uint32_t Eth_Link_PHYITConfig(uint16_t PHYAddress)
     /* Return SUCCESS */
     return ETH_SUCCESS;
 }
-
-/**
- * @brief  Link callback function, this function is called on change of link status.
- * @param  The network interface
- * @retval None
- */
-void ETH_link_callback(struct netif *netif)
-{
-    __IO uint32_t   timeout = 0;
-    uint32_t        tmpreg;
-    uint16_t        RegValue;
-    struct ip4_addr ipaddr;
-    struct ip4_addr netmask;
-    struct ip4_addr gw;
-
-    if (netif_is_link_up(netif))
-    {
-        /* Restart the auto-negotiation */
-        if (ETH_InitStructure.ETH_AutoNegotiation !=
-            ETH_AutoNegotiation_Disable)
-        {
-            /* Reset Timeout counter */
-            timeout = 0;
-            /* Enable auto-negotiation */
-            ETH_WritePHYRegister(ETHERNET_PHY_ADDRESS, PHY_BCR,
-                                 PHY_AutoNegotiation);
-            /* Wait until the auto-negotiation will be completed */
-            do
-            {
-                timeout++;
-            } while (!(ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO));
-
-            /* Reset Timeout counter */
-            timeout = 0;
-            /* Read the result of the auto-negotiation */
-            RegValue = ETH_ReadPHYRegister(ETHERNET_PHY_ADDRESS, PHY_SR);
-
-            if ((RegValue & PHY_DUPLEX_STATUS) != (uint16_t)RESET)
-            {
-                ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
-            }
-            else
-            {
-                ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex;
-            }
-            if (RegValue & PHY_SPEED_STATUS)
-            {
-                /* Set Ethernet speed to 10M following the auto-negotiation */
-                ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
-            }
-            else
-            {
-                /* Set Ethernet speed to 100M following the auto-negotiation */
-                ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
-            }
-
-            /*------------ ETHERNET MACCR Re-Configuration -------------
-
-            /* Get the ETHERNET MACCR value */
-            tmpreg = ETH->MACCR;
-
-            /* Set the FES bit according to ETH_Speed value */
-            /* Set the DM bit according to ETH_Mode value */
-            tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Speed |
-                                 ETH_InitStructure.ETH_Mode);
-
-            /* Write to ETHERNET MACCR */
-            ETH->MACCR = (uint32_t)tmpreg;
-
-            _eth_delay_(ETH_REG_WRITE_DELAY);
-            tmpreg     = ETH->MACCR;
-            ETH->MACCR = tmpreg;
-        }
-
-        /* Restart MAC interface */
-        ETH_Start();
-
-#ifdef USE_DHCP
-        ipaddr.addr  = 0;
-        netmask.addr = 0;
-        gw.addr      = 0;
-        DHCP_state   = DHCP_START;
-#else
-        IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
-        IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
-        IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
-#endif /* USE_DHCP */
-
-        netif_set_addr(&gnetif, &ipaddr, &netmask, &gw);
-
-        /* When the netif is fully configured this function must be called.*/
-        netif_set_up(&gnetif);
-
-        // EthLinkStatus = 0;
-    }
-    else
-    {
-        ETH_Stop();
-#ifdef USE_DHCP
-        DHCP_state = DHCP_LINK_DOWN;
-        dhcp_stop(netif);
-#endif /* USE_DHCP */
-
-        /*  When the netif link is down this function must be called.*/
-        netif_set_down(&gnetif);
-    }
-}
-
-// void ETH_IRQHandler(void)
-// {
-//     OSIntEnter();
-
-//     /* frame received */
-//     if (SET == ETH_GetDMAITStatus(ETH_DMA_FLAG_R))
-//     {
-//         Eth_Link_ITHandler(0x01);
-//         /* clear the enet DMA Rx interrupt pending bits */
-//         ETH_DMAClearITPendingBit(ETH_DMA_FLAG_R);
-//         ETH_DMAClearITPendingBit(ETH_DMA_FLAG_NIS);
-
-//         /* give the semaphore to wakeup LwIP task */
-//         OSSemPost(g_enet_rx_sem);
-//     }
-
-//     OSIntExit();
-// }

+ 46 - 30
User/Bsp/interface/interface.c

@@ -27,7 +27,7 @@ Gpio_Clock clock_info[] = {
     {.type = kEthernet_dm9101, .RCC_AXBPeriph = RCC_AHB1Periph, .AF_Clock = RCC_AHB1Periph_ETH_MAC_Tx},
     {.type = kEthernet_dm9101, .RCC_AXBPeriph = RCC_AHB1Periph, .AF_Clock = RCC_AHB1Periph_ETH_MAC_Rx},
     {.type = kEthernet_dm9101, .RCC_AXBPeriph = RCC_AHB1Periph, .AF_Clock = RCC_AHB1Periph_ETH_MAC_PTP},
-    {.type = kEthernet_dm9k, .RCC_AXBPeriph = RCC_AHB3Periph, .AF_Clock = RCC_AHB3Periph_FSMC},
+    {.type = kFSMC, .RCC_AXBPeriph = RCC_AHB3Periph, .AF_Clock = RCC_AHB3Periph_FSMC},
     // {.type = kPMU, .AXBPeriph_Clock = RCU_PMU},
     {.type = kDMA1, .RCC_AXBPeriph = RCC_AHB1Periph, .AF_Clock = RCC_AHB1Periph_DMA1},
     // //    {.type = kTIMER1,   .AXBPeriph_Clock = RCU_TIMER1},
@@ -89,35 +89,51 @@ Interface_struct interface_info[] = {
     {.type = kEthernet_dm9101, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_ETH}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
     {.type = kEthernet_dm9101, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_ETH}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
     {.type = kEthernet_dm9101, .GPIOx = ETH_RESET_PORT, .GPIO_Pin = ETH_RESET_PIN, .GPIO_Mode = GPIO_Mode_OUT, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
-    //         //    {.type = kEthernet_dm9101, .GPIOx = ETH_RXER_PORT,  .GPIO_Pin = ETH_RXER_PIN,  .GPIO_Mode = GPIO_MODE_INPUT,  .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_PuPd = GPIO_PuPd_DOWN},
-
-    // ethernet-dm9k
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_0, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource0, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_1, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource1, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_8, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource8, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_9, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource9, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource15, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_7, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource7, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_8, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource8, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_9, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource9, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_11, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource11, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_12, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource12, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource15, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
-    {.type = kEthernet_dm9k, .GPIOx = DM9K_RESET_PORT, .GPIO_Pin = DM9K_RESET_PIN, .GPIO_Mode = GPIO_Mode_OUT, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_PuPd = GPIO_PuPd_UP},
-    //         // input
-    //         {.type = kInput, .In_Type = kLDetect, .GPIOx = LDetect1_PORT, .GPIO_Pin = LDetect1_PIN, .GPIO_Mode = GPIO_MODE_INPUT, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_High_Speed, .GPIO_PuPd = GPIO_PuPd_NOPULL},
+
+    // fsmc
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_0, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource0, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_1, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource1, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_8, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource8, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_9, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource9, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_11, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource11, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_12, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource12, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOD, .GPIO_Pin = GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOD, .GPIO_PinSource = GPIO_PinSource15, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_7, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource7, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_8, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource8, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_9, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource9, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_11, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource11, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_12, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource12, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOE, .GPIO_Pin = GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOE, .GPIO_PinSource = GPIO_PinSource15, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_0, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource0, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_1, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource1, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_2, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource2, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_3, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource3, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_12, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource12, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_13, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource13, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_14, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource14, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOF, .GPIO_Pin = GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOF, .GPIO_PinSource = GPIO_PinSource15, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_0, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource0, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_1, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource1, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_2, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource2, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_3, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource3, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_4, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource4, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    // {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_5, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource5, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+    {.type = kFSMC, .GPIOx = GPIOG, .GPIO_Pin = GPIO_Pin_10, .GPIO_Mode = GPIO_Mode_AF, .AF_Info = {.GPIOx = GPIOG, .GPIO_PinSource = GPIO_PinSource10, .GPIO_AF = GPIO_AF_FSMC}, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_UP},
+
+    // input
+    {.type = kInput, .In_Type = DM9K_INIT, .GPIOx = DM9K_RESET_PORT, .GPIO_Pin = DM9K_RESET_PIN, .GPIO_Mode = GPIO_Mode_IN, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_Speed_100MHz, .GPIO_PuPd = GPIO_PuPd_NOPULL},
 
     // output
     {.type = kOutput, .Out_Type = kRunLed, .GPIOx = LED0_RUN_PORT, .GPIO_Pin = LED0_RUN_PIN, .GPIO_Mode = GPIO_Mode_OUT, .GPIO_OType = GPIO_OType_PP, .GPIO_Speed = GPIO_High_Speed, .GPIO_PuPd = GPIO_PuPd_DOWN},

+ 2 - 2
User/Bsp/interface/interface.h

@@ -18,7 +18,7 @@ typedef enum
     kCAN1,
     kCAN2,
     kEthernet_dm9101,
-    kEthernet_dm9k,
+    kFSMC,
     kInput,
     kOutput,
     kPMU,
@@ -66,7 +66,7 @@ typedef enum
 
 typedef enum
 {
-    kLDetect,
+    DM9K_INIT,
     kInputEnd,
 } Input_type;
 

+ 1 - 1
User/Bsp/rtc/rtc.c

@@ -72,7 +72,7 @@ u8 MyRTC_Init(void)
         while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪
         {
             retry++;
-            bsp_DelayMS(10);
+            ms_delay(10);
         }
         if (retry == 0)
             return 1; // LSE 开启失败.

+ 76 - 153
User/Bsp/uart/uart1.c

@@ -11,24 +11,66 @@
 #include "uart1.h"
 #include "queue.h"
 
+static INT8U uart1_tx_buf[UART1_TX_LEN]  = {0};
+static INT8U uart1_rx_buf[UART1_REC_LEN] = {0};
+
+__IO INT8U rx_index = 0x00;
+
+__IO INT8U tx_index = 0x00;
+
+__IO INT8U TimeOut = 0x00;
+
 //  重定义fputc函数
 #ifdef __GNUC__
 
-int _write(int fd, char *pBuffer, int size)
+int _write(int fd, char *buffer, int size)
 {
-    while (RESET != USART_GetITStatus(USART1, USART_IT_TC))
-        ;
-    uart1_dma_send((INT8U *)pBuffer, size);
+    /* 写一个字节到USART1 */
+    for (int i = 0; i < size; i++)
+    {
+        USART_SendData(USART1, buffer[i]);
+        /* 等待发送结束 */
+        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
+            ;
+    }
+
     return size;
 }
-#endif
-
-static INT8U uart1_tx_buf[UART1_TX_LEN]  = {0};
-static INT8U uart1_rx_buf[UART1_REC_LEN] = {0};
+int _read(int fd, char *buffer, int size)
+{
 
-UartFrame_TypeDef Uart1FrameStruct[UART1_MAX_MSG_NUM];
+    for (int i = 0; i < size; i++)
+    {
+        /* 等待串口1输入数据 */
+        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
+            ;
+        buffer[i] = USART_ReceiveData(USART1);
+    }
+    return size;
+}
+// int _write(int fd, char *buffer, int size)
+// {
+//     uart1_dma_send((INT8U *)buffer, size);
+//     while (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
+//         ;
+//     return size;
+// }
+
+// int _read(int fd, char *buffer, int size)
+// {
+
+//     /* 等待串口1输入数据 */
+//     while (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
+//         ;
+//     // INT8U err = 0;
+//     // UartFrame_TypeDef *msg;
+
+//     // msg = (UartFrame_TypeDef *)OSMboxPend(uart1_mbox, 50, &err);
+//     // return msg->len;
+//     return (int)USART_ReceiveData(USART1);
+// }
 
-extern OS_EVENT *uart1_mbox;
+#endif
 
 void uart1_nvic_config(void)
 {
@@ -41,72 +83,6 @@ void uart1_nvic_config(void)
     NVIC_Init(&NVIC_InitStructure);                                     //根据指定的参数初始化VIC寄存器
 }
 
-void uart1_dma_init(void)
-{
-    DMA_InitTypeDef DMA_InitStructure;
-    if ((u32)UART1_DMA_TXCH > (u32)DMA2) //得到当前stream是属于DMA2还是DMA1
-    {
-        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能
-    }
-    else
-    {
-        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // DMA1时钟使能
-    }
-
-    DMA_DeInit(UART1_DMA_TXCH);
-    while (DMA_GetCmdStatus(UART1_DMA_TXCH) != DISABLE)
-    {
-    } //等待DMA可配置
-    /* 配置 DMA Stream */
-    DMA_InitStructure.DMA_Channel            = UART1_DMA;                   //通道选择
-    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;            // DMA外设地址
-    DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)uart1_tx_buf;           // DMA 存储器0地址
-    DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral;  //存储器到外设模式
-    DMA_InitStructure.DMA_BufferSize         = UART1_TX_LEN;                //数据传输量
-    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   //外设非增量模式
-    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        //存储器增量模式
-    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位
-    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     //存储器数据长度:8位
-    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;             // 使用普通模式
-    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;         //中等优先级6
-    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;
-    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;
-    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器突发单次传输
-    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设突发单次传输      // DMA 存储器0地址
-    DMA_Init(UART1_DMA_TXCH, &DMA_InitStructure);                          //初始化DMA Stream
-
-    if ((u32)UART1_DMA_RXCH > (u32)DMA2) //得到当前stream是属于DMA2还是DMA1
-    {
-        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能
-    }
-    else
-    {
-        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // DMA1时钟使能
-    }
-
-    DMA_DeInit(UART1_DMA_RXCH);
-    while (DMA_GetCmdStatus(UART1_DMA_RXCH) != DISABLE)
-    {
-    }
-
-    DMA_InitStructure.DMA_Channel            = UART1_DMA;                   //通道选择
-    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;            // DMA外设地址
-    DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)uart1_rx_buf;           // DMA 存储器0地址
-    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;  //外设到存储器模式
-    DMA_InitStructure.DMA_BufferSize         = UART1_REC_LEN;               //数据传输量
-    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   //外设非增量模式
-    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        //存储器增量模式
-    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位
-    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     //存储器数据长度:8位
-    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;           // 使用循环模式
-    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;         //中等优先级
-    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;
-    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;
-    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;     //存储器突发单次传输
-    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single; //外设突发单次传输
-    DMA_Init(UART1_DMA_RXCH, &DMA_InitStructure);
-}
-
 void uart1_config(void)
 {
     USART_InitTypeDef USART_InitStructure;
@@ -121,98 +97,45 @@ void uart1_config(void)
     USART_Cmd(USART1, ENABLE); //使能串口1
 }
 
-void Uart1DMA_Enable(DMA_Stream_TypeDef *DMA_Streamx, u16 count)
-{
-    DMA_Cmd(DMA_Streamx, DISABLE); //关闭DMA传输
-    while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE)
-    {
-    } //确保DMA可以被设置
-
-    DMA_SetCurrDataCounter(DMA_Streamx, count); //数据传输量
-    DMA_Cmd(DMA_Streamx, ENABLE);               //开启DMA传输
-}
-
 void uart1_init(void)
 {
     uart1_config();
-    uart1_dma_init();
     uart1_nvic_config();
-    /* USART DMA enable*/
-    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); // 使能串口DMA接收数据
-    Uart1DMA_Enable(UART1_DMA_RXCH, UART1_REC_LEN);
-    /*configure DMA interrupt*/
-    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); //开启空闲中断
-    USART_ITConfig(USART1, USART_IT_TC, ENABLE);
-}
 
-/****************************************************
- *  函 数 名:Uart1_Send_Data
- *  函数功能:串口1发送数据
- *  入口参数:buf 待发送数据  len 数据长度
- *  说    明:
- *****************************************************/
-void Uart1_Send_Data(const u8 *buf, u16 len)
-{
-    u8 i;
-    for (i = 0; i < len; i++) //循环发送数据
-    {
-        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
-            ;
-        USART_SendData(USART1, buf[i]);
-    }
-    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
-        ;
-}
-
-void uart1_dma_send(const INT8U *buf, INT16U len)
-{
-    if (RESET != DMA_GetFlagStatus(UART1_DMA_TXCH, DMA_FLAG_TCIF7))
-    {
-        DMA_ClearFlag(UART1_DMA_TXCH, DMA_FLAG_TCIF7);
-    }
-    if (len > UART1_TX_LEN)
-    {
-        len = UART1_TX_LEN;
-    }
-    memcpy(uart1_tx_buf, buf, len);
-    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 使能DMA串口发送数据
-    Uart1DMA_Enable(UART1_DMA_TXCH, len);
+    /* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
+    如下语句解决第1个字节无法正确发送出去的问题 */
+    USART_ClearFlag(USART1, USART_FLAG_TC);
 }
 
 void USART1_IRQHandler(void)
 {
-    static INT8U   u1_index = 0;
-    volatile INT8U clear    = 0;
-    INT8U          rec_cnt  = 0;
-    if (RESET != USART_GetITStatus(USART1, USART_IT_IDLE))
+    /* 处理接收中断 */
+    if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
     {
-        clear = USART1->SR;
-        clear = USART1->DR; // 先读SR, 再读DR, 就是为了消除IDLE中断
-
-        DMA_Cmd(UART1_DMA_RXCH, DISABLE);
-        DMA_ClearFlag(UART1_DMA_RXCH, DMA_FLAG_TCIF5);
-        rec_cnt = UART1_REC_LEN - DMA_GetCurrDataCounter(UART1_DMA_RXCH); // 获得接收帧帧长  特别注意: 帧长不是DMA_GetCurrDataCounter(DMA2_Stream5)
-
-        memcpy(Uart1FrameStruct[u1_index].buf, uart1_rx_buf, rec_cnt);
-        Uart1FrameStruct[u1_index].len = rec_cnt;
-
-        OSMboxPost(uart1_mbox, &Uart1FrameStruct[u1_index]);
-        if (u1_index < UART1_MAX_MSG_NUM - 1)
+        if (rx_index < UART1_REC_LEN)
         {
-            u1_index++;
+            /* 接收数据 */
+            uart1_rx_buf[rx_index++] = USART_ReceiveData(USART1);
         }
         else
         {
-            u1_index = 0;
+            /* 禁止接收中断 */
+            USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
         }
-        DMA_SetCurrDataCounter(UART1_DMA_RXCH, UART1_REC_LEN);
-        DMA_Cmd(UART1_DMA_RXCH, ENABLE);
     }
-    else if (RESET != USART_GetITStatus(USART1, USART_IT_TC))
+    /* 处理发送缓冲区空中断 */
+    if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
+
     {
-        USART_ClearITPendingBit(USART1, USART_IT_TC);   // 清除发送完成标标志位
-        Uart1DMA_Enable(UART1_DMA_RXCH, UART1_REC_LEN); // DMA接收使能
-        DMA_Cmd(UART1_DMA_TXCH, DISABLE);               // 关闭发送DMA
-        DMA_SetCurrDataCounter(UART1_DMA_TXCH, 0);      // 清除发送数据长度
+        if (tx_index < UART1_TX_LEN)
+        {
+            /* 发送数据 */
+            USART_SendData(USART1, uart1_tx_buf[tx_index++]);
+        }
+        else
+        {
+            /* 禁止发送缓冲区空中断 */
+            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
+        }
     }
-}
+}

+ 2 - 8
User/Bsp/uart/uart1.h

@@ -6,15 +6,9 @@
 #include "stm32f4xx_usart.h"
 #include "string.h"
 
-#define UART1_REC_LEN     128
-#define UART1_TX_LEN      128
-#define UART1_MAX_MSG_NUM 10
-
-#define UART1_DMA      DMA_Channel_4
-#define UART1_DMA_RXCH DMA2_Stream5
-#define UART1_DMA_TXCH DMA2_Stream7
+#define UART1_REC_LEN 128
+#define UART1_TX_LEN  128
 
 void uart1_init(void);
-void uart1_dma_send(const INT8U *buf, INT16U len);
 
 #endif // __UART_H

+ 1 - 0
User/app/fly_config.c

@@ -0,0 +1 @@
+// #include "fly_config.h"

+ 15 - 0
User/app/fly_config.h

@@ -0,0 +1,15 @@
+// #ifndef FLY_CONFIG_H
+// #define FLY_CONFIG_H
+// #include "includes.h"
+
+// typedef struct
+// {
+//     uint8_t mac[6];      // MAC地址
+//     uint8_t remoteip[4]; //远端主机IP地址
+//     uint8_t ip[4];       //本机IP地址
+//     uint8_t netmask[4];  //子网掩码
+//     uint8_t gateway[4];  //默认网关的IP地址
+//     uint8_t dhcpstatus;  // dhcp状态
+// } __lwip_dev;
+
+// #endif

+ 1 - 0
User/app/fly_param.c

@@ -3,6 +3,7 @@
 
 OS_EVENT *bmu_mutex    = NULL;
 OS_EVENT *bms_mutex    = NULL;
+OS_EVENT *net_mutex    = NULL;
 OS_EVENT *config_mutex = NULL;
 OS_EVENT *can1_sem     = NULL;
 OS_EVENT *can2_sem     = NULL;

+ 1 - 0
User/app/fly_param.h

@@ -24,6 +24,7 @@
 #define UART1_TASK_STK_SIZE 256
 #define UART3_TASK_STK_SIZE 256
 
+extern OS_EVENT *net_mutex;
 extern OS_EVENT *can1_sem;
 extern OS_EVENT *can2_sem;
 extern OS_EVENT *uart1_mbox;

+ 162 - 0
User/app/iec104/PRIO_QUEUE_Iec10x.c

@@ -0,0 +1,162 @@
+/*******************************************************************
+Copyright (C):
+File name    :    PRIO_QUEUE.C
+DESCRIPTION  :
+AUTHOR       :
+Version      :    1.0
+Date         :    2014/02/26
+Others       :
+History      :
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+1) Date: 2014/02/26         Author: ChenDajie
+   content:
+
+*******************************************************************/
+#include "PRIO_QUEUE_Iec10x.h"
+#include "common_datatype.h"
+#include "iec10x.h"
+#include "includes.h"
+#include "project_var.h"
+#include <stdio.h>
+
+extern PIEC10X_T          IEC10X;
+extern Iec10x_PrioQueue_T Iec10x_PrioQueueArray[IEC10X_PRIO_MAX];
+
+#ifdef PRIO_QUEUE
+
+/*******************************************************************************
+* Function Name  : HighestPrio
+* Description    :
+* Input          : None
+* Output         : None
+* Return         : RET_ERROR failure
+                   len sucess
+*******************************************************************************/
+char IEC10X_HighestPrio(void)
+{
+
+    int     i, prio;
+    uint8_t flag = 0;
+    prio         = -1;
+    // LOG("%s \r\n",__FUNCTION__);
+    for (i = 0; i < IEC10X_PRIO_MAX; i++)
+    {
+        if (Iec10x_PrioQueueArray[i].ElementNum > 0 && !flag)
+        {
+            // return i;
+            prio = i;
+            flag = 1;
+            LOG("<%s>Prio[%d],Num%d. \n", __FUNCTION__, i, Iec10x_PrioQueueArray[i].ElementNum);
+        }
+        LOG("[%d]%d.", i, Iec10x_PrioQueueArray[i].ElementNum);
+    }
+    LOG("out(%d)\r\n", prio);
+    return prio;
+}
+
+void IEC10X_PrioInitQueue(Iec10x_PrioQueue_T *PrioQueue)
+{
+
+    PrioQueue->Header     = NULL;
+    PrioQueue->Tail       = NULL;
+    PrioQueue->ElementNum = 0;
+}
+uint8_t IEC10X_PrioEnQueue(Iec10x_PrioQueue_T *QueueHdr, Iec10x_PrioNode_T *new_p)
+{
+
+    new_p->Next = NULL;
+
+    if (QueueHdr->Header == NULL)
+    {
+        QueueHdr->Header = new_p;
+        QueueHdr->Tail   = new_p;
+    }
+    else
+    {
+        QueueHdr->Tail->Next = new_p;
+        QueueHdr->Tail       = new_p;
+    }
+
+    QueueHdr->ElementNum++;
+    // LOG("%s ElementNum(%d) \r\n",__FUNCTION__,QueueHdr->ElementNum);
+    return RET_SUCESS;
+}
+
+Iec10x_PrioNode_T *IEC10X_PrioDeQueue(Iec10x_PrioQueue_T *QueueHdr)
+{
+
+    Iec10x_PrioNode_T *PrioNode_DeQ;
+    if (QueueHdr->Header == NULL)
+    {
+        // LOG("PrioDeQueue,error \r\n");
+        return NULL;
+    }
+    PrioNode_DeQ = QueueHdr->Header;
+
+    QueueHdr->Header = QueueHdr->Header->Next;
+    if (QueueHdr->Header == NULL)
+    {
+        QueueHdr->Tail = NULL;
+    }
+
+    // LOG("PrioDeQueue(%d) \r\n",PrioNode_DeQ->Length);
+
+    return PrioNode_DeQ;
+}
+
+Iec10x_PrioNode_T *IEC10X_PrioFindQueueHead(Iec10x_PrioQueue_T *QueueHdr)
+{
+
+    Iec10x_PrioNode_T *PrioNode_DeQ;
+    if (QueueHdr->Header == NULL)
+    {
+        // LOG("PrioDeQueue,error \r\n");
+        return NULL;
+    }
+    PrioNode_DeQ = QueueHdr->Header;
+
+    // LOG("PrioDeQueue(%d) \r\n",PrioNode_DeQ->Length);
+
+    return PrioNode_DeQ;
+}
+
+void *IEC10X_PeekQueue(Iec10x_PrioQueue_T *QueueHdr)
+{
+
+    if (QueueHdr->Header == NULL)
+    {
+        // LOG("   ");
+        return NULL;
+    }
+    return QueueHdr->Header->value;
+}
+
+int IEC10X_Prio_IsEmptyQueue(Iec10x_PrioQueue_T *QueueHdr)
+{
+
+    if (QueueHdr->Header == NULL)
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void IEC10X_Prio_ClearQueue(Iec10x_PrioQueue_T *QueueHdr)
+{
+
+    Iec10x_PrioNode_T *p = QueueHdr->Header;
+    while (p != NULL)
+    {
+        QueueHdr->Header = QueueHdr->Header->Next;
+        IEC10X->Free(p);
+        p = QueueHdr->Header;
+    }
+    QueueHdr->Tail       = NULL;
+    QueueHdr->ElementNum = 0;
+    return;
+}
+
+#endif

+ 6 - 0
User/app/iec104/PRIO_QUEUE_Iec10x.h

@@ -0,0 +1,6 @@
+#ifndef __IEC10X_PRIO_QUEUE_H__
+#define __IEC10X_PRIO_QUEUE_H__
+
+#include "iec10x.h"
+
+#endif

+ 25 - 0
User/app/iec104/common_datatype.h

@@ -0,0 +1,25 @@
+// /* There is some amount of overlap with <sys/types.h> as known by inet code */
+// #ifndef __int8_t_defined
+// #define __int8_t_defined
+// typedef signed char int8_t;
+// typedef short int   int16_t;
+// typedef int         int32_t;
+// #if __WORDSIZE == 64
+// typedef long int int64_t;
+// #else
+// __extension__ typedef long long int int64_t;
+// #endif
+// #endif
+
+// /* Unsigned.  */
+// typedef unsigned char      uint8_t;
+// typedef unsigned short int uint16_t;
+// #ifndef __uint32_t_defined
+// typedef unsigned int uint32_t;
+// #define __uint32_t_defined
+// #endif
+// #if __WORDSIZE == 64
+// typedef unsigned long int uint64_t;
+// #else
+// __extension__ typedef unsigned long long int uint64_t;
+// #endif

+ 0 - 0
User/app/iec104/hxcp.c


+ 1356 - 0
User/app/iec104/iec101.c

@@ -0,0 +1,1356 @@
+
+
+#include "iec101.h"
+#include "project_var.h"
+#ifdef IEC101_STM32
+/*
+ * GLOABLE VARIALBLE
+ */
+uint8_t Iec101_Respon_Confirm = 0;
+uint8_t Iec101_Sendbuf[IEC101_MAX_BUF_LEN];
+
+uint8_t  IEC10X_Call_AllQoi   = 0;
+uint8_t  IEC10X_Call_GroupQoi = 0;
+uint16_t IEC101_Pulse_Cnt     = 0;
+
+/*
+ * STATE
+ * */
+uint8_t IEC101_STATE_FLAG_INIT    = IEC101_FLAG_LINK_CLOSED;
+uint8_t IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_LINK_CLOSED;
+uint8_t IEC101_STATE_FLAG_GROUP   = IEC101_FLAG_LINK_CLOSED;
+uint8_t IEC101_STATE_FLAG_CLOCK   = IEC101_FLAG_LINK_CLOSED;
+uint8_t IEC101_STATE_FLAG_DELAY   = IEC101_FLAG_LINK_CLOSED;
+uint8_t IEC101_STATE_FLAG_PULSE   = IEC101_FLAG_LINK_CLOSED;
+
+uint8_t IEC10X_RetStatusOk(uint16_t addr)
+{
+
+    uint16_t     len;
+    PIEC101_10_T Iec10x = (PIEC101_10_T)Iec101_Sendbuf;
+
+    len = IEC101_STABLE_LEN;
+
+    Iec10x->_begin = IEC101_STABLE_BEGING;
+
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_SLAVE;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CAN_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_RES_LINK_STATUS;
+
+    Iec10x->_addr = addr;
+    Iec10x->_cs   = Iec101_Sendbuf[1] + Iec101_Sendbuf[2] + Iec101_Sendbuf[3];
+    Iec10x->_end  = IEC101_STABLE_END;
+
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+static uint8_t IEC10X_ResConfirm(uint8_t Prio)
+{
+
+    uint16_t len;
+
+    PIEC101_10_T Iec10x = (PIEC101_10_T)Iec101_Sendbuf;
+
+    len = IEC101_STABLE_LEN;
+
+    Iec10x->_begin = IEC101_STABLE_BEGING;
+
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_SLAVE;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CAN_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_RES_CONFIRM;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    Iec10x->_cs   = Iec101_Sendbuf[1] + Iec101_Sendbuf[2] + Iec101_Sendbuf[3];
+    Iec10x->_end  = IEC101_STABLE_END;
+
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC10X_ReqLinkStatus()
+{
+
+    uint16_t len;
+
+    PIEC101_10_T Iec10x = (PIEC101_10_T)Iec101_Sendbuf;
+
+    LOG("%s \n", __FUNCTION__);
+
+    len = IEC101_STABLE_LEN;
+
+    Iec10x->_begin = IEC101_STABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.down._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.down._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.down._fcb = IEC101_CTRL_FCB_OPPO_NONE;
+    Iec10x->_ctrl.down._fcv = IEC101_CTRL_FCV_DISABLE;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_REQ_LINK_STATUS;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    Iec10x->_cs   = Iec101_Sendbuf[1] + Iec101_Sendbuf[2] + Iec101_Sendbuf[3];
+    Iec10x->_end  = IEC101_STABLE_END;
+
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC10X_ResetLink(void)
+{
+
+    uint16_t len;
+
+    PIEC101_10_T Iec10x = (PIEC101_10_T)Iec101_Sendbuf;
+
+    len = IEC101_STABLE_LEN;
+
+    Iec10x->_begin = IEC101_STABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.down._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.down._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.down._fcb = IEC101_CTRL_FCB_OPPO_NONE;
+    Iec10x->_ctrl.down._fcv = IEC101_CTRL_FCV_DISABLE;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_RESET_LINK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    Iec10x->_cs   = Iec101_Sendbuf[1] + Iec101_Sendbuf[2] + Iec101_Sendbuf[3];
+    Iec10x->_end  = IEC101_STABLE_END;
+
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC101_BuildFinInit(void)
+{
+
+    uint16_t len     = 0;
+    uint8_t  cs_temp = 0, i;
+
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_WITH_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = Iec10x_M_EI_NA_1;
+    asdu->_num._num       = 1;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_INIT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr       = IEC10X_INFO_ADDR_NONE;
+    info->_element[0] = 0;
+
+    /*len*/
+    len          = IEC101_VARIABLE_LEN + asdu->_num._num;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC101_BuildActConfirm(uint8_t qoi, uint8_t Prio)
+{
+
+    uint16_t len     = 0;
+    uint8_t  cs_temp = 0, i;
+
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = IEC10X_C_IC_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTCON;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr       = IEC10X_INFO_ADDR_NONE;
+    info->_element[0] = qoi;
+    /*len*/
+    len          = IEC101_VARIABLE_LEN + asdu->_num._num;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC101_BuildActFinish(uint8_t qoi, uint8_t Prio)
+{
+
+    uint16_t len     = 0;
+    uint8_t  cs_temp = 0, i;
+
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_WITH_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = IEC10X_C_IC_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTTERM;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr       = IEC10X_INFO_ADDR_NONE;
+    info->_element[0] = qoi;
+
+    /*len*/
+    len          = IEC101_VARIABLE_LEN + asdu->_num._num;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC101_BuildSignal(uint8_t reason, uint8_t Prio)
+{
+
+    uint16_t len     = 0, addr;
+    uint8_t  cs_temp = 0, i, asdu_num = 0, *ptr = NULL, signal, sum;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    IEC10X->GetStationInfo(&addr, 0, &asdu_num);
+    len = IEC101_STABLE_LEN;
+    LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num);
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_WITH_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = IEC10X_M_SP_NA_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = reason;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr = IEC10X_INFO_ADDR_SIG_BASE + IEC10X_INFO_ADDR_SIG_TEMP_HX_OFF;
+
+    /*signal value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        if (IEC10X->GetStationInfo(&addr, i, &asdu_num) == RET_SUCESS)
+            *ptr = 1;
+        else
+            *ptr = 0;
+        ptr++;
+    }
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC101_BuildDetect(uint8_t reason, uint8_t type, uint8_t Prio)
+{
+
+    uint16_t           len     = 0, addr;
+    uint8_t            cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+    PIEC10X_DETECT_T   detect   = NULL;
+    PIEC10X_DETECT_F_T detect_f = NULL;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    IEC10X->GetStationInfo(&addr, 0, &asdu_num);
+    LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num);
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = type;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = reason;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*info*/
+    info->_addr = IEC10X_INFO_ADDR_DET + IEC10X_INFO_ADDR_DET_TEMP_HX_OFF;
+
+    /*Detect value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        /*short int*/
+        if (type == IEC10X_M_ME_NA_1)
+        {
+            detect          = (PIEC10X_DETECT_T)ptr;
+            detect->_detect = IEC10X->GetStaTemp(i);
+            detect->_qds    = 0;
+            ptr += sizeof(IEC10X_DETECT_T);
+        }
+        /*float*/
+        else if (type == IEC10X_M_ME_NC_1)
+        {
+            detect_f          = (PIEC10X_DETECT_F_T)ptr;
+            detect_f->_detect = IEC10X->GetStaTemp(i);
+            detect_f->_qds    = 0;
+            ptr += sizeof(IEC10X_DETECT_F_T);
+        }
+    }
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;       /* add cs+end*/
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC101_BuildSignal_Spont(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV)
+{
+
+    uint16_t      len     = 0;
+    uint8_t       cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+    PCP56Time2a_T time = NULL;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+    LOG("-%s-, time flag(%d) signalV(%d) \n", __FUNCTION__, TimeFlag, signalV);
+    /*get value*/
+    asdu_num = 1;
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_WITH_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_SP_NA_1;
+    else
+        asdu->_type = IEC10X_M_SP_TB_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr = addrV;
+
+    /*signal value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        *ptr = signalV;
+        ptr++;
+    }
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC101_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV)
+{
+
+    uint16_t         len     = 0;
+    uint8_t          cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+    PIEC10X_DETECT_T detect = NULL;
+    PCP56Time2a_T    time   = NULL;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+
+    /*get value*/
+    asdu_num = 1;
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_ME_NA_1;
+    else
+        asdu->_type = IEC10X_M_ME_TD_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*info*/
+    info->_addr = addrV;
+
+    /*Detect value*/
+    ptr             = info->_element;
+    detect          = (PIEC10X_DETECT_T)ptr;
+    detect->_detect = detectV->_detect;
+    detect->_qds    = detectV->_qds;
+    ptr += sizeof(IEC10X_DETECT_T);
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;       /* add cs+end*/
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC101_BuildDetectF_Spont(uint8_t TimeFlag, float detectV, uint16_t addrV)
+{
+
+    uint16_t           len     = 0;
+    uint8_t            cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+    PIEC10X_DETECT_F_T detect = NULL;
+    PCP56Time2a_T      time   = NULL;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+
+    /*get value*/
+    asdu_num = 1;
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_ME_NC_1;
+    else
+        asdu->_type = IEC10X_M_ME_TF_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*info*/
+    info->_addr = addrV;
+
+    /*Detect value*/
+    ptr             = info->_element;
+    detect          = (PIEC10X_DETECT_F_T)ptr;
+    detect->_detect = detectV;
+    detect->_qds    = 0;
+    ptr += sizeof(IEC10X_DETECT_F_T);
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;       /* add cs+end*/
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC101_BuildDelayAct(uint16_t delay_time)
+{
+
+    uint16_t len     = 0;
+    uint8_t  cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+    uint16_t cp16time2a = delay_time;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    asdu_num = 1;
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = IEC10X_C_CD_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_COT_ACTCON;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr = IEC10X_INFO_ADDR_NONE;
+
+    /*delay value*/
+    ptr              = info->_element;
+    *(uint16_t *)ptr = IEC10X_Cp16time2a;
+    ptr += 2;
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_DELAY, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC101_BuildClockAct()
+{
+
+    uint16_t len     = 0;
+    uint8_t  cs_temp = 0, i, asdu_num = 0, *ptr = NULL;
+
+    /*init struct*/
+    PIEC101_68_T   Iec10x = (PIEC101_68_T)Iec101_Sendbuf;
+    PIEC10X_ASDU_T asdu   = (PIEC10X_ASDU_T)(Iec10x->_asdu);
+    PASDU_INFO_T   info   = (PASDU_INFO_T)(asdu->_info);
+    PCP56Time2a_T  time   = (PCP56Time2a_T)(info->_element);
+
+    /*get value*/
+    asdu_num = 1;
+
+    len = IEC101_STABLE_LEN;
+
+    /*head*/
+    Iec10x->_begin = Iec10x->_begin_cfm = IEC101_VARIABLE_BEGING;
+
+    /*Ctrol*/
+    Iec10x->_ctrl.up._dir = IEC101_CTRL_DIR_UP;
+    Iec10x->_ctrl.up._prm = IEC101_CTRL_PRM_MASTER;
+    Iec10x->_ctrl.up._acd = IEC101_CTRL_ACD_NONE_DATA;
+    Iec10x->_ctrl.up._dfc = IEC101_CTRL_DFC_CANNOT_REC;
+
+    Iec10x->_ctrl.up._func = IEC101_CTRL_SEND_USR_DATA_ACK;
+
+    Iec10x->_addr = Iec10x_Sta_Addr;
+    /*asdu*/
+    asdu->_type           = IEC10X_C_CS_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._pn     = 0;
+    asdu->_reason._test   = 0;
+    asdu->_reason._reason = IEC10X_COT_ACTCON;
+    asdu->_addr           = Iec10x_Sta_Addr;
+    /*info*/
+    info->_addr = IEC10X_INFO_ADDR_NONE;
+
+    /*clock value*/
+    ptr = info->_element;
+    // time;
+    IEC10X->GetTime(time);
+    ptr += sizeof(CP56Time2a_T);
+
+    /*len*/
+    len          = ptr + 2 - Iec101_Sendbuf;
+    Iec10x->_len = Iec10x->_len_cfm = len - 4 - 2; /*-start-len-len-start   -cs-end*/
+
+    /*end*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += Iec101_Sendbuf[i];
+    }
+    Iec101_Sendbuf[len - 2] = cs_temp;
+    Iec101_Sendbuf[len - 1] = IEC101_VARIABLE_END;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec101_Sendbuf, len, IEC10X_PRIO_CLOCK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+IEC10X_ASDU_CALL_Qoi(uint8_t qoi)
+{
+
+    switch (qoi)
+    {
+    case IEC10X_CALL_QOI_TOTAL:
+        LOG("-%s- call cmd active \n", __FUNCTION__);
+        IEC101_BuildSignal(IEC10X_COT_INTROGEN, IEC10X_PRIO_CALLALL);
+        IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_CALL_SIG_TOTAL;
+        break;
+    case IEC10X_CALL_QOI_GROUP1:
+        LOG("-%s- call cmd call group1 \n", __FUNCTION__);
+        IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROUP;
+        IEC101_BuildSignal(IEC10X_COT_INTRO1, IEC10X_PRIO_CALLGROUP);
+        break;
+    case IEC10X_CALL_QOI_GROUP2:
+        LOG("-%s- call cmd call group2 \n", __FUNCTION__);
+        IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROUP;
+        IEC101_BuildSignal(IEC10X_COT_INTRO2, IEC10X_PRIO_CALLGROUP);
+        break;
+    case IEC10X_CALL_QOI_GROUP9:
+        LOG("-%s- call cmd call group9 \n", __FUNCTION__);
+        IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROUP;
+        IEC101_BuildDetect(IEC10X_COT_INTRO9, IEC10X_M_ME_NA_1, IEC10X_PRIO_CALLGROUP);
+        break;
+    case IEC10X_CALL_QOI_GROUP10:
+        LOG("-%s- call cmd call group10 \n", __FUNCTION__);
+        IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROUP;
+        IEC101_BuildDetect(IEC10X_COT_INTRO10, IEC10X_M_ME_NA_1, IEC10X_PRIO_CALLGROUP);
+        break;
+    default:
+        LOG("-%s- call cmd active error(%d) \n", __FUNCTION__, qoi);
+        break;
+    }
+}
+
+uint8_t IEC10X_ASDU_Call(PIEC10X_ASDU_T Iec10x_Asdu)
+{
+
+    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+    uint8_t      qoi       = asdu_info->_element[0];
+    uint8_t      Prio      = 0;
+
+    if (asdu_info->_addr != 0)
+    {
+        LOG("-%s- call cmd active error addr(%x) \n", __FUNCTION__, asdu_info->_addr);
+        return RET_ERROR;
+    }
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_ASDU_REASON_ACT:
+        switch (qoi)
+        {
+        case IEC10X_CALL_QOI_TOTAL:
+            Prio                      = IEC10X_PRIO_CALLALL;
+            IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_CALL_ACT_RET;
+            IEC10X_Call_AllQoi        = qoi;
+            break;
+        case IEC10X_CALL_QOI_GROUP1:
+        case IEC10X_CALL_QOI_GROUP2:
+        case IEC10X_CALL_QOI_GROUP9:
+        case IEC10X_CALL_QOI_GROUP10:
+            Prio                    = IEC10X_PRIO_CALLGROUP;
+            IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_ACT_RET;
+            IEC10X_Call_GroupQoi    = qoi;
+            break;
+        default:
+            LOG("-%s- call cmd error qoi(%d) \n", __FUNCTION__, qoi);
+            return RET_ERROR;
+        }
+        IEC10X_ResConfirm(Prio);
+        IEC101_BuildActConfirm(qoi, Prio);
+        break;
+
+    default:
+        LOG("-%s- call cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        break;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t IEC10X_ASDU_Delay(PIEC10X_ASDU_T Iec10x_Asdu)
+{
+
+    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+
+    if (asdu_info->_addr != 0)
+    {
+        LOG("-%s- delay cmd error addr(%d) \n", __FUNCTION__, asdu_info->_addr);
+        return RET_ERROR;
+    }
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_COT_ACT:
+        IEC10X_Cp16time2a = *(uint16_t *)(asdu_info->_element);
+        LOG("-%s- delay cmd (0x%x%x)(%d)ms \n", __FUNCTION__, asdu_info->_element[0], asdu_info->_element[1], IEC10X_Cp16time2a);
+        IEC101_STATE_FLAG_DELAY = IEC101_FLAG_DELAY_ACT;
+        IEC10X_ResConfirm(IEC10X_PRIO_DELAY);
+        IEC101_BuildDelayAct(IEC10X_Cp16time2a);
+        break;
+    case IEC10X_COT_SPONT:
+        IEC10X_Cp16time2a_V = *(uint16_t *)(asdu_info->_element);
+        LOG("-%s- delay cmd delay value(%d)ms \n", __FUNCTION__, IEC10X_Cp16time2a_V);
+        IEC10X_ResConfirm(IEC10X_PRIO_DELAY);
+        break;
+    default:
+        LOG("-%s- delay cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        break;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t IEC10X_ASDU_CLOCK(PIEC10X_ASDU_T Iec10x_Asdu)
+{
+
+    PASDU_INFO_T  asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+    PCP56Time2a_T time      = (PCP56Time2a_T)(asdu_info->_element);
+
+    memcpy(&IEC10X_Cp56time2a, asdu_info->_element, sizeof(CP56Time2a_T));
+
+    if (asdu_info->_addr != 0)
+    {
+        LOG("-%s- Clock cmd error addr(%d) \n", __FUNCTION__, asdu_info->_addr);
+        return RET_ERROR;
+    }
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_COT_ACT:
+        LOG("-%s- Clock cmd (20%d-%d-%d %d %d:%d:%d) delay(%d) \n", __FUNCTION__, IEC10X_Cp56time2a._year._year, IEC10X_Cp56time2a._month._month, IEC10X_Cp56time2a._day._dayofmonth,
+            IEC10X_Cp56time2a._day._dayofweek, IEC10X_Cp56time2a._hour._hours, IEC10X_Cp56time2a._min._minutes, IEC10X_Cp56time2a._milliseconds, IEC10X_Cp16time2a_V);
+        IEC10X_Cp56time2a._milliseconds += IEC10X_Cp16time2a_V;
+        /*get time*/
+        /*...*/
+        IEC10X->SetTime(&IEC10X_Cp56time2a);
+        IEC101_STATE_FLAG_DELAY = IEC101_FLAG_CLOCK_SYS;
+        IEC10X_ResConfirm(IEC10X_PRIO_CLOCK);
+        IEC101_BuildClockAct();
+        break;
+    case IEC10X_COT_SPONT:
+        LOG("-%s- Clock cmd spont \n", __FUNCTION__);
+        break;
+    default:
+        LOG("-%s- Clock cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        break;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t Iec10x_Deal_10(uint8_t *buf, uint16_t len)
+{
+
+    uint8_t      cfun, sta, i;
+    uint8_t      cs_temp   = 0;
+    PIEC101_10_T Iec10x_10 = NULL;
+
+    Iec10x_10 = (PIEC101_10_T)buf;
+    /* check check_sum*/
+    for (i = 1; i < len - 2; i++)
+    {
+        cs_temp += buf[i];
+    }
+    if (Iec10x_10->_cs != cs_temp)
+    {
+        LOG("-%s-,check sum error(%x) \n", __FUNCTION__, cs_temp);
+        return RET_ERROR;
+    }
+    /* check end of the frame*/
+    if (Iec10x_10->_end != 0x16)
+    {
+        LOG("-%s-,iec10x_10 end error(%d) \n", __FUNCTION__, Iec10x_10->_end);
+        return RET_ERROR;
+    }
+    /*deal the function code*/
+    cfun = Iec10x_10->_ctrl.down._func;
+    sta  = Iec10x_10->_ctrl.down._prm;
+    // IEC10X->GetLinkAddr();
+#ifdef IEC10XLOCK
+    if (IEC10X->LOCK != NULL)
+        IEC10X->LOCK();
+#endif
+    if (sta == IEC101_CTRL_PRM_MASTER)
+    {
+        switch (cfun)
+        {
+
+        case IEC101_CTRL_RESET_LINK:
+            LOG("++++Reset link... \n");
+            IEC101_STATE_FLAG_INIT = IEC101_FLAG_RESET_LINK;
+            break;
+        case IEC101_CTRL_PULSE:
+            LOG("++++PULSE... \n");
+            IEC101_STATE_FLAG_PULSE = IEC101_FLAG_PULSE;
+            IEC10X_ResConfirm(IEC10X_PRIO_PULSE);
+            break;
+        case IEC101_CTRL_SEND_DATA:
+            LOG("++++Send data... \n");
+            break;
+        case IEC101_CTRL_REQ_LINK_STATUS:
+            LOG("++++Request link status... \n");
+            IEC101_STATE_FLAG_INIT = IEC101_FLAG_INIT_LINK;
+            // Iec10x_Sta_Addr = IEC10X->GetLinkAddr();
+
+            // Iec10x_Sta_Addr = 0x138a;
+            // IEC10X_RetStatusOk(Iec10x_Sta_Addr);
+            break;
+        default:
+            LOG("++++error DOWN function code (%d)... \n", cfun);
+            break;
+        }
+    }
+    else if (sta == IEC101_CTRL_PRM_SLAVE)
+    {
+
+        switch (cfun)
+        {
+        case IEC101_CTRL_RES_LINK_STATUS:
+            LOG("++++Respon link status... \n");
+            LOG("IEC101_FLAG_RESET_REMOTE_LINK \n");
+            IEC10X_ResetLink();
+            IEC101_STATE_FLAG_INIT = IEC101_FLAG_RESET_REMOTE_LINK;
+            break;
+        case IEC101_CTRL_RES_CONFIRM:
+            LOG("++++Respon confirm... \n");
+            Iec101_Respon_Confirm = 1;
+            break;
+        default:
+            LOG("++++error UP function code (%d)... \n", cfun);
+            break;
+        }
+    }
+#ifdef IEC10XLOCK
+    if (IEC10X->UNLOCK != NULL)
+        IEC10X->UNLOCK();
+#endif
+    return RET_SUCESS;
+}
+
+uint8_t Iec10x_Deal_68(uint8_t *buf, uint16_t len)
+{
+
+    uint8_t        cfun, sta, i;
+    uint8_t        cs_temp     = 0;
+    PIEC101_68_T   Iec10x_68   = NULL;
+    PIEC10X_ASDU_T Iec10x_Asdu = NULL;
+
+    Iec10x_68   = (PIEC101_68_T)buf;
+    Iec10x_Asdu = (PIEC10X_ASDU_T)Iec10x_68->_asdu;
+
+    /* check check_sum*/
+    for (i = 4; i < len - 2; i++)
+    {
+        cs_temp += buf[i];
+    }
+    if (buf[len - 2] != cs_temp)
+    {
+        LOG("-%s-,iec10x_68 check sum error (%d)(%d) \n", __FUNCTION__, buf[len - 2], cs_temp);
+        return RET_ERROR;
+    }
+    /* check end of the frame*/
+    if (buf[len - 1] != IEC101_VARIABLE_END)
+    {
+        LOG("-%s-,iec10x_68 end error(%d) \n", __FUNCTION__, buf[len - 1]);
+        return RET_ERROR;
+    }
+    /* check len of the receive frame */
+    if (Iec10x_68->_len + 6 != len)
+    {
+        LOG("-%s-,iec10x_68 rec len error(%d)(%d) \n", __FUNCTION__, Iec10x_68->_len, len);
+        return RET_ERROR;
+    }
+    /* check len of the frame */
+    if (Iec10x_68->_len != Iec10x_68->_len_cfm)
+    {
+        LOG("-%s-,iec10x_68 len error(%d)(%d) \n", __FUNCTION__, Iec10x_68->_len, Iec10x_68->_len_cfm);
+        return RET_ERROR;
+    }
+    /*deal the function code*/
+    cfun = Iec10x_68->_ctrl.down._func;
+    sta  = Iec10x_68->_ctrl.down._prm;
+#ifdef IEC10XLOCK
+    if (IEC10X->LOCK != NULL)
+        IEC10X->LOCK();
+#endif
+    switch (cfun)
+    {
+    case IEC101_CTRL_SEND_USR_DATA_ACK:
+        Iec101_Respon_Confirm = 0;
+        LOG("++++Send user data need ack... \n");
+        switch (Iec10x_Asdu->_type)
+        {
+        case IEC10X_C_IC_NA_1:
+            LOG("++++asdu type call cmd... \n");
+            IEC10X_ASDU_Call(Iec10x_Asdu);
+            break;
+        case IEC10X_C_CD_NA_1:
+            LOG("++++asdu type delay active... \n");
+            IEC10X_ASDU_Delay(Iec10x_Asdu);
+            break;
+        case IEC10X_C_CS_NA_1:
+            LOG("++++asdu type clock active... \n");
+            IEC10X_ASDU_CLOCK(Iec10x_Asdu);
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        LOG("++++error function code (%d)... \n", cfun);
+        break;
+    }
+#ifdef IEC10XLOCK
+    if (IEC10X->UNLOCK != NULL)
+        IEC10X->UNLOCK();
+#endif
+    return RET_SUCESS;
+}
+
+void Iex101_main(uint8_t *buf, uint16_t len)
+{
+
+    uint8_t *BufTemp = NULL;
+    int16_t  LenRemain, LenTmp;
+
+    if (buf == NULL)
+    {
+        LOG("-%s-,buffer (null)", __FUNCTION__);
+        return;
+    }
+    if (len <= 0 || len > IEC101_MAX_BUF_LEN)
+    {
+        LOG("-%s-,buffer len error(%d) \n", __FUNCTION__, len);
+        return;
+    }
+
+    BufTemp   = buf;
+    LenRemain = len;
+    while (BufTemp < buf + len)
+    {
+
+        if (BufTemp[0] == IEC101_STABLE_BEGING)
+        {
+            LenTmp           = 6;
+            IEC101_Pulse_Cnt = 0;
+            if (LenRemain < 6)
+            {
+                LOG("_%s_,len error(%d) \n", __FUNCTION__, len);
+                return;
+            }
+            Iec10x_Deal_10(BufTemp, LenTmp);
+        }
+        else if (BufTemp[0] == IEC101_VARIABLE_BEGING)
+        {
+            LenTmp           = BufTemp[1] + 6;
+            IEC101_Pulse_Cnt = 0;
+            if (BufTemp[1] != BufTemp[2])
+            {
+                LOG("_%s_,len error(%d)(%d) \n", __FUNCTION__, BufTemp[1], BufTemp[2]);
+                return;
+            }
+            Iec10x_Deal_68(BufTemp, LenTmp);
+        }
+        else
+        {
+            LOG("-%s-,head type error(%d) \n", __FUNCTION__, BufTemp[0]);
+            return;
+        }
+        BufTemp += LenTmp;
+        LenRemain -= LenTmp;
+    }
+    return;
+}
+
+uint8_t Iec101_StateMachine(void)
+{
+
+    /*Init link*/
+
+    switch (IEC101_STATE_FLAG_INIT)
+    {
+
+    case IEC101_FLAG_LINK_CLOSED:
+        break;
+    case IEC101_FLAG_INIT_LINK:
+        LOG("IEC101_FLAG_INIT_LINK \n");
+        Iec101_Respon_Confirm = 0;
+        Iec10x_Sta_Addr       = IEC10X->GetLinkAddr();
+        IEC10X_RetStatusOk(Iec10x_Sta_Addr);
+        IEC101_STATE_FLAG_INIT = IEC101_FLAG_LINK_IDLE;
+        break;
+    case IEC101_FLAG_RESET_LINK:
+        LOG("IEC101_FLAG_RESET_LINK \n");
+        IEC10X_ClearQ();
+        IEC10X_ResConfirm(IEC10X_PRIO_INITLINK);
+
+        IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_LINK_CLOSED;
+        IEC101_STATE_FLAG_GROUP   = IEC101_FLAG_LINK_CLOSED;
+        IEC101_STATE_FLAG_DELAY   = IEC101_FLAG_LINK_CLOSED;
+        IEC101_STATE_FLAG_PULSE   = IEC101_FLAG_LINK_CLOSED;
+
+        IEC101_STATE_FLAG_INIT = IEC101_FLAG_REQ_LINK;
+        break;
+    case IEC101_FLAG_REQ_LINK:
+        LOG("IEC101_FLAG_REQ_LINK \n");
+        IEC10X_ReqLinkStatus();
+        IEC101_STATE_FLAG_INIT = IEC101_FLAG_LINK_IDLE;
+        break;
+    case IEC101_FLAG_RESET_REMOTE_LINK:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm  = 0;
+            IEC101_STATE_FLAG_INIT = IEC101_FLAG_INIT_FIN;
+            LOG("IEC101_FLAG_INIT_FIN! \n");
+            IEC101_BuildFinInit();
+        }
+        break;
+    case IEC101_FLAG_INIT_FIN:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm  = 0;
+            IEC101_STATE_FLAG_INIT = IEC101_FLAG_CONNECT_OK;
+        }
+        break;
+    case IEC101_FLAG_CONNECT_OK:
+    case IEC101_FLAG_LINK_IDLE:
+    default:
+        break;
+    }
+
+    /*total call*/
+    switch (IEC101_STATE_FLAG_CALLALL)
+    {
+    case IEC101_FLAG_CALL_ACT:
+        break;
+    case IEC101_FLAG_CALL_ACT_RET:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm = 0;
+            IEC10X_ASDU_CALL_Qoi(IEC10X_Call_AllQoi);
+        }
+        break;
+    case IEC101_FLAG_CALL_SIG_TOTAL:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm     = 0;
+            IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_CALL_DET_TOTAL;
+            IEC101_BuildDetect(IEC10X_COT_INTROGEN, IEC10X_M_ME_NA_1, IEC10X_PRIO_CALLALL);
+        }
+        break;
+    case IEC101_FLAG_CALL_DET_TOTAL:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm = 0;
+            IEC101_BuildActFinish(IEC10X_Call_AllQoi, IEC10X_PRIO_CALLALL);
+            IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_CALL_ACT_FIN;
+        }
+        break;
+    case IEC101_FLAG_CALL_ACT_FIN:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm     = 0;
+            IEC101_STATE_FLAG_CALLALL = IEC101_FLAG_LINK_IDLE;
+        }
+        break;
+    case IEC101_FLAG_LINK_IDLE:
+    default:
+        break;
+    }
+
+    /*group call*/
+    switch (IEC101_STATE_FLAG_GROUP)
+    {
+    case IEC101_FLAG_CALL_ACT:
+        break;
+    case IEC101_FLAG_CALL_ACT_RET:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm = 0;
+            IEC10X_ASDU_CALL_Qoi(IEC10X_Call_GroupQoi);
+        }
+        break;
+    case IEC101_FLAG_CALL_GROUP:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm   = 0;
+            IEC101_STATE_FLAG_GROUP = IEC101_FLAG_CALL_ACT_FIN;
+            IEC101_BuildActFinish(IEC10X_Call_GroupQoi, IEC10X_PRIO_CALLGROUP);
+        }
+        break;
+    case IEC101_FLAG_CALL_ACT_FIN:
+        if (Iec101_Respon_Confirm)
+        {
+            Iec101_Respon_Confirm   = 0;
+            IEC101_STATE_FLAG_GROUP = IEC101_FLAG_LINK_IDLE;
+        }
+        break;
+    case IEC101_FLAG_LINK_IDLE:
+    default:
+        break;
+    }
+
+    /*delay and clock*/
+    switch (IEC101_STATE_FLAG_DELAY)
+    {
+
+    case IEC101_FLAG_DELAY_ACT:
+        break;
+    case IEC101_FLAG_CLOCK_SYS:
+        IEC101_STATE_FLAG_DELAY = IEC101_FLAG_LINK_IDLE;
+        break;
+    case IEC101_FLAG_LINK_IDLE:
+    default:
+        break;
+    }
+
+    /*pulse*/
+    switch (IEC101_STATE_FLAG_PULSE)
+    {
+    case IEC101_FLAG_PULSE:
+        break;
+    case IEC101_FLAG_LINK_IDLE:
+        break;
+    default:
+        break;
+    }
+    return RET_SUCESS;
+}
+
+#endif

+ 198 - 0
User/app/iec104/iec101.h

@@ -0,0 +1,198 @@
+/*******************************************************************
+Copyright (C):
+File name    :    Iec101.h
+DESCRIPTION  :
+AUTHOR       :
+Version      :    1.0
+Date         :    2014/07/23
+Others       :
+History      :
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+1) Date: 2014/07/23         Author: ChenDajie
+   content:
+
+*******************************************************************/
+
+#ifndef _IEC101_H
+#define _IEC101_H
+
+#include "PRIO_QUEUE_Iec10x.h"
+#include "iec10x.h"
+#include "project_var.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef IEC101_STM32
+#define ARM_PACK __packed
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                           FUNCTION CODE
+    *********************************************************************************************************
+    */
+    /*
+     * down
+     * */
+#define IEC101_CTRL_RESET_LINK        0
+#define IEC101_CTRL_PULSE             2
+#define IEC101_CTRL_SEND_USR_DATA_ACK 3
+#define IEC101_CTRL_SEND_DATA         4
+#define IEC101_CTRL_REQ_LINK_STATUS   9
+
+/*
+ * up
+ * */
+#define IEC101_CTRL_RES_CONFIRM     0x00
+#define IEC101_CTRL_RES_LINK_STATUS 0x0B
+/*
+ * DIR, PRM, FCB, FCV, ACD, DFC
+ * */
+#define IEC101_CTRL_DIR_DOWN       0x01
+#define IEC101_CTRL_DIR_UP         0x00
+#define IEC101_CTRL_FCB_OPPO_BIT   0x01
+#define IEC101_CTRL_FCB_OPPO_NONE  0x00
+#define IEC101_CTRL_PRM_MASTER     0x01
+#define IEC101_CTRL_PRM_SLAVE      0x00
+#define IEC101_CTRL_FCV_ENABLE     0x01
+#define IEC101_CTRL_FCV_DISABLE    0x00
+#define IEC101_CTRL_ACD_WITH_DATA  0x01
+#define IEC101_CTRL_ACD_NONE_DATA  0x00
+#define IEC101_CTRL_DFC_CAN_REC    0x00
+#define IEC101_CTRL_DFC_CANNOT_REC 0x01
+
+    /*
+    *********************************************************************************************************
+    *                           FRAME  VALUE
+    *********************************************************************************************************
+    */
+#define IEC101_STABLE_BEGING 0X10
+#define IEC101_STABLE_END    0X16
+#define IEC101_STABLE_LEN    0X06
+/*
+ * variable
+ * */
+#define IEC101_VARIABLE_BEGING 0X68
+#define IEC101_VARIABLE_END    0X16
+    /*
+     * length of variable
+     * */
+#define IEC101_VARIABLE_HEAD_LEN (sizeof(IEC101_68_T) - 1)
+#define IEC101_VARIABLE_ASDU_LEN (sizeof(IEC10X_ASDU_T) - 1)
+#define IEC101_VARIABLE_INFO_LEN (sizeof(ASDU_INFO_T) - 1)
+#define IEC101_VARIABLE_LEN      (IEC101_VARIABLE_HEAD_LEN + IEC101_VARIABLE_ASDU_LEN + IEC101_VARIABLE_INFO_LEN + 2) /*add cs+end*/
+
+#pragma pack(1)
+
+#define IEC101_MAX_BUF_LEN 256
+
+    /*
+     * Control Code
+     * */
+    typedef __packed struct
+    {
+
+        uint8_t _func : 4; /* function */
+        uint8_t _fcv  : 1;
+        uint8_t _fcb  : 1; /* Frame calculate bit */
+        uint8_t _prm  : 1; /* 1:from start station, 0:from end station */
+        uint8_t _dir  : 1;
+
+    } CTRL_DOWN_T;
+
+    typedef __packed struct
+    {
+
+        uint8_t _func : 4; /*function*/
+        uint8_t _dfc  : 1;
+        uint8_t _acd  : 1;
+        uint8_t _prm  : 1;
+        uint8_t _dir  : 1;
+
+    } CTRL_UP_T;
+
+    typedef __packed union
+    {
+        CTRL_UP_T   up;
+        CTRL_DOWN_T down;
+        uint8_t     val;
+    } CTRL_T, *PCTRL_T;
+
+    /*
+     *  regular frame   head:10
+     * */
+    typedef __packed struct
+    {
+        uint8_t  _begin;
+        CTRL_T   _ctrl;
+        uint16_t _addr;
+        uint8_t  _cs;
+        uint8_t  _end;
+    } IEC101_10_T, *PIEC101_10_T;
+
+    /*
+     *  variable fram   head:68
+     * */
+    typedef __packed struct
+    {
+        uint8_t  _begin;
+        uint8_t  _len;
+        uint8_t  _len_cfm;
+        uint8_t  _begin_cfm;
+        CTRL_T   _ctrl;
+        uint16_t _addr;
+        uint8_t  _asdu[1];
+    } IEC101_68_T, *PIEC101_68_T;
+
+#pragma pack()
+
+    /* IEC101 STATE-MACHINE */
+    enum
+    {
+        IEC101_FLAG_LINK_CLOSED,
+        IEC101_FLAG_LINK_IDLE,
+        IEC101_FLAG_INIT_LINK,
+        IEC101_FLAG_RESET_LINK,
+        IEC101_FLAG_REQ_LINK,
+        IEC101_FLAG_RESET_REMOTE_LINK,
+        IEC101_FLAG_INIT_FIN,
+        IEC101_FLAG_CALL_ACT,
+        IEC101_FLAG_CALL_ACT_FIN,
+        IEC101_FLAG_CALL_ACT_RET,
+        IEC101_FLAG_CALL_SIG_TOTAL,
+        IEC101_FLAG_CALL_DET_TOTAL,
+        IEC101_FLAG_DELAY_ACT,
+        IEC101_FLAG_CLOCK_SYS,
+        IEC101_FLAG_PULSE,
+        IEC101_FLAG_CALL_GROUP,
+        IEC101_FLAG_CONNECT_OK,
+    };
+
+    /*
+    *********************************************************************************************************
+    *                                           GLOABLE VARIABLE
+    *********************************************************************************************************
+    */
+    extern uint16_t IEC101_Pulse_Cnt;
+    extern uint8_t  IEC101_STATE_FLAG_INIT;
+    /*
+    *********************************************************************************************************
+    *                                          FUNCTION PROTOTYPES
+    *********************************************************************************************************
+    */
+
+    void    Iex101_main(uint8_t *buf, uint16_t len);
+    uint8_t Iec101_StateMachine(void);
+
+    uint8_t IEC101_BuildSignal_Spont(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV);
+    uint8_t IEC101_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV);
+    uint8_t IEC101_BuildDetectF_Spont(uint8_t TimeFlag, float detectV, uint16_t addrV);
+
+#ifdef __cplusplus
+}
+#endif /*IEC101_STM32*/
+#endif
+#endif /*_IEC101_H*/

+ 1575 - 0
User/app/iec104/iec104.c

@@ -0,0 +1,1575 @@
+/*******************************************************************
+Copyright (C):
+File name    :    Iec104.c
+DESCRIPTION  :
+AUTHOR       :
+Version      :    1.0
+Date         :    2014/07/31
+Others       :
+History      :
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+1) Date: 2014/07/31         Author: ChenDajie
+   content:
+
+*******************************************************************/
+#include "iec104.h"
+#include "project_var.h"
+
+/*
+ * GLOABLE VARIALBLE
+ */
+
+uint8_t Iec104_Sendbuf[IEC104_MAX_BUF_LEN];
+/*
+ * STATE
+ * */
+uint8_t IEC104_STATE_FLAG_INIT    = IEC104_FLAG_CLOSED;
+uint8_t IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CLOSED;
+uint8_t IEC104_STATE_FLAG_GROUP   = IEC104_FLAG_CLOSED;
+uint8_t IEC104_STATE_FLAG_CLOCK   = IEC104_FLAG_CLOSED;
+uint8_t IEC104_STATE_FLAG_TESTER  = IEC104_FLAG_IDLE;
+uint8_t IEC104_STATE_FLAG_S_ACK   = IEC104_FLAG_CLOSED;
+/*
+ * receive and send serial number
+ * */
+int32_t Iec104_BuildSendSn = 0;
+int32_t Iec104_BuildRecvSn = 0;
+int32_t Iec104_DealSendSn  = -1;
+int32_t Iec104_DealRecvSn  = 0;
+
+uint8_t IEC104_Call_AllQoi   = 0;
+uint8_t IEC104_Call_GroupQoi = 0;
+
+#define IEC104_CYCLE_TIME_MS       100             /*100ms*/
+#define IEC104_RESEND_TIME_MS      (30 * 1000)     /*30s*/
+#define IEC104_S_ACK_TIMEOUT       (5 * 1000)      /*5s*/
+#define IEC104_TESTER_IDLE_TIMEOUT (1 * 30 * 1000) /*2min*/
+uint32_t Iec104_TimeCount            = 0;
+uint32_t Iec104_TimeCycle            = IEC104_RESEND_TIME_MS;
+uint32_t Iec104_TimeCycle_S          = 0;
+uint32_t Iec104_TimeCycle_TesterIdle = 0;
+uint8_t  Iec104_TesterCount          = 0;
+
+uint32_t Iec10x_Update_SeekAddr = 0;
+uint16_t FirmFlagCount          = 0;
+
+uint8_t IEC104_UploadAddr(void)
+{
+
+    uint8_t  len    = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = IEC104_ASDU_TYPE_M_DTU_INF_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._reason = IEC10X_ASDU_COT_UNKNOW;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info*/
+    ptr    = info->_addr;
+    Temp32 = 0;
+    memcpy(ptr, &Temp32, 3);
+
+    ptr    = info->_element;
+    Temp32 = IEC104_INFO_SIGNATURE;
+    memcpy(ptr, &Temp32, 4);
+
+    ptr += 4;
+    Temp32 = Iec10x_Sta_Addr;
+    memcpy(ptr, &Temp32, 2);
+
+    ptr += 2;
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_Build_InitFin(void)
+{
+
+    uint8_t  len    = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = Iec10x_M_EI_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_INIT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info*/
+    ptr    = info->_addr;
+    Temp32 = 0;
+    memcpy(ptr, &Temp32, 3);
+
+    ptr = info->_element;
+    // Temp32 = 0;
+    // memcpy(ptr, &Temp32, 4);
+    info->_element[0] = 0;
+
+    ptr++;
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildCallACK(uint8_t qoi, uint8_t Prio)
+{
+
+    uint8_t  len    = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = IEC10X_C_IC_NA_1;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTCON;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info*/
+    ptr    = info->_addr;
+    Temp32 = 0;
+    memcpy(ptr, &Temp32, 3);
+
+    ptr    = info->_element;
+    ptr[0] = qoi;
+
+    ptr += 1;
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    DumpHEX(Iec104_Sendbuf, len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildSignal_Spon(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV)
+{
+
+    uint8_t       len = 0, asdu_num = 0, i;
+    uint8_t      *ptr    = NULL;
+    uint32_t      Temp32 = 0;
+    PCP56Time2a_T time   = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /* check Time flag */
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+    LOG("-%s-, time flag(%d) signalV(%d) \n", __FUNCTION__, TimeFlag, signalV);
+    /*get value*/
+    asdu_num = 1;
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_SP_NA_1;
+    else
+        asdu->_type = IEC10X_M_SP_TB_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr    = info->_addr;
+    Temp32 = addrV;
+    memcpy(ptr, &Temp32, 3);
+
+    /*build info value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        *ptr = signalV;
+        ptr++;
+    }
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC104_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV)
+{
+
+    uint8_t          len = 0, asdu_num = 0;
+    uint8_t         *ptr    = NULL;
+    uint32_t         Temp32 = 0;
+    PIEC10X_DETECT_T detect = NULL;
+    PCP56Time2a_T    time   = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /* check Time flag */
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+    /*get value*/
+    asdu_num = 1;
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_ME_NA_1;
+    else
+        asdu->_type = IEC10X_M_ME_TD_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr    = info->_addr;
+    Temp32 = addrV;
+    memcpy(ptr, &Temp32, 3);
+
+    /*build info value*/
+    ptr             = info->_element;
+    detect          = (PIEC10X_DETECT_T)ptr;
+    detect->_detect = detectV->_detect;
+    detect->_qds    = detectV->_qds;
+    ptr += sizeof(IEC10X_DETECT_T);
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildDetectF_Spont(uint8_t TimeFlag, float detectV, uint16_t addrV)
+{
+
+    uint8_t            len = 0, asdu_num = 0;
+    uint8_t           *ptr    = NULL;
+    uint32_t           Temp32 = 0;
+    PIEC10X_DETECT_F_T detect = NULL;
+    PCP56Time2a_T      time   = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /* check Time flag */
+    if (TimeFlag != 1 && TimeFlag != 0)
+    {
+        LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag);
+        return RET_ERROR;
+    }
+    /*get value*/
+    asdu_num = 1;
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    if (TimeFlag == 0)
+        asdu->_type = IEC10X_M_ME_NC_1;
+    else
+        asdu->_type = IEC10X_M_ME_TF_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = IEC10X_COT_SPONT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr    = info->_addr;
+    Temp32 = addrV;
+    memcpy(ptr, &Temp32, 3);
+
+    /*build info value*/
+    ptr             = info->_element;
+    detect          = (PIEC10X_DETECT_F_T)ptr;
+    detect->_detect = detectV;
+    detect->_qds    = 0;
+    ptr += sizeof(IEC10X_DETECT_F_T);
+    if (TimeFlag == 1)
+    {
+        time = (PCP56Time2a_T)ptr;
+        IEC10X->GetTime(time);
+        ptr += sizeof(CP56Time2a_T);
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC104_BuildSignal(uint8_t reason, uint8_t Prio, uint8_t DevType)
+{
+
+    uint8_t  len = 0, asdu_num = 0;
+    uint16_t i      = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    IEC10X->GetInfoNum(&asdu_num, DevType);
+    LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = IEC10X_M_SP_NA_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = reason;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr = info->_addr;
+    if (DevType == ENDDEVICE_TYPE_HXTM)
+    {
+        Temp32 = IEC104_INFOADDR_STATE_HXTM;
+    }
+    else if (DevType == ENDDEVICE_TYPE_HXGF)
+    {
+        Temp32 = IEC104_INFOADDR_STATE_HXGF;
+    }
+    else
+    {
+        LOG("-%s-, error dev type:%d \n", __FUNCTION__, DevType);
+        return RET_ERROR;
+    }
+
+    memcpy(ptr, &Temp32, 3);
+
+    /*build info value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        *ptr = IEC10X->GetStationState(i, DevType);
+        ptr++;
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildDetect(uint8_t reason, uint8_t ValueType, uint8_t Prio, uint8_t DevType)
+{
+
+    uint8_t            len = 0, asdu_num = 0, i;
+    uint8_t           *ptr      = NULL;
+    uint32_t           Temp32   = 0;
+    PIEC10X_DETECT_T   detect   = NULL;
+    PIEC10X_DETECT_F_T detect_f = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    IEC10X->GetInfoNum(&asdu_num, DevType);
+    LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = ValueType;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = reason;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr = info->_addr;
+    if (DevType == ENDDEVICE_TYPE_HXTM)
+    {
+        Temp32 = IEC104_INFOADDR_VALUE_HXTM;
+    }
+    else if (DevType == ENDDEVICE_TYPE_HXGF)
+    {
+        Temp32 = IEC104_INFOADDR_VALUE_HXGF;
+    }
+    else
+    {
+        LOG("-%s-, error dev type:%d \n", __FUNCTION__, DevType);
+        return RET_ERROR;
+    }
+    memcpy(ptr, &Temp32, 3);
+
+    /*Build Detect value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+        /*short int*/
+        if (ValueType == IEC10X_M_ME_NA_1)
+        {
+            detect          = (PIEC10X_DETECT_T)ptr;
+            detect->_detect = IEC10X->GetStaValue(i, DevType);
+            detect->_qds    = 0;
+            ptr += sizeof(IEC10X_DETECT_T);
+        }
+        /*float*/
+        else if (ValueType == IEC10X_M_ME_NC_1)
+        {
+            detect_f          = (PIEC10X_DETECT_F_T)ptr;
+            detect_f->_detect = IEC10X->GetStaValue(i, DevType);
+            detect_f->_qds    = 0;
+            ptr += sizeof(IEC10X_DETECT_F_T);
+        }
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildUpload(uint8_t ValueType, uint8_t Prio, uint8_t DevType)
+{
+
+    uint8_t          len = 0, asdu_num = 0, i;
+    uint8_t         *ptr    = NULL;
+    uint32_t         Temp32 = 0;
+    PIEC10X_DETECT_T detect = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*get value*/
+    IEC10X->GetInfoNum(&asdu_num, DevType);
+    LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = ValueType;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = AP_COT_BASE_INFO;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr = info->_addr;
+
+    Temp32 = IEC104_INFOADDR_BASE_DEVINFO;
+    memcpy(ptr, &Temp32, 3);
+    ptr += 3;
+    /*Build Detect value*/
+    ptr = info->_element;
+    for (i = 0; i < asdu_num; i++)
+    {
+
+        detect          = (PIEC10X_DETECT_T)ptr;
+        detect->_detect = IEC10X->GetStaValue(i, DevType);
+        detect->_qds    = 0;
+        ptr += sizeof(IEC10X_DETECT_T);
+    }
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_BuildActFinish(uint8_t qoi, uint8_t Prio)
+{
+
+    uint8_t  len = 0, asdu_num = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = IEC10X_C_IC_NA_1;
+    asdu->_num._sq        = 1;
+    asdu->_num._num       = asdu_num;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTTERM;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info addr*/
+    ptr    = info->_addr;
+    Temp32 = IEC10X_INFO_ADDR_SIG_BASE + IEC10X_INFO_ADDR_SIG_TEMP_HX_OFF;
+    memcpy(ptr, &Temp32, 3);
+
+    /*Build Detect value*/
+    ptr    = info->_element;
+    ptr[0] = qoi;
+
+    ptr += 1;
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_Build_U(uint8_t UType, uint8_t Ack)
+{
+
+    uint8_t  len = 0, Tester, Start, Stop;
+    uint8_t *ptr = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    if (Ack)
+    {
+        Tester = IEC104_U_FUNC_TESTER_ACK;
+        Start  = IEC104_U_FUNC_STARTDT_ACK;
+        Stop   = IEC104_U_FUNC_STOPDT_ACK;
+    }
+    else
+    {
+        Tester = IEC104_U_FUNC_TESTER;
+        Start  = IEC104_U_FUNC_STARTDT;
+        Stop   = IEC104_U_FUNC_STOPDT;
+    }
+
+    switch (UType)
+    {
+
+    case IEC104_U_FUNC_STARTDT:
+        Iec104Data->Ctrl.Func.Func = Start;
+        break;
+    case IEC104_U_FUNC_STOPDT:
+        Iec104Data->Ctrl.Func.Func = Stop;
+        break;
+    case IEC104_U_FUNC_TESTER:
+        Iec104Data->Ctrl.Func.Func = Tester;
+        break;
+    default:
+        LOG(">%s<, U Type Error(%d) !\n", __FUNCTION__, UType);
+        return RET_ERROR;
+    }
+
+    /*build ASDU , COT ,Addr*/
+    ptr = Iec104Data->Asdu;
+
+    /*build info*/
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_Build_S_Ack(void)
+{
+
+    uint8_t  len = 0;
+    uint8_t *ptr = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.S.Type1 = 1;
+    Iec104Data->Ctrl.S.Type2 = 0;
+
+    Iec104Data->Ctrl.S.Reserve = 0;
+    Iec104Data->Ctrl.S.RecvSn  = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    ptr = Iec104Data->Asdu;
+
+    /*build info*/
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+    // DumpHEX(Iec101_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL);
+
+    return RET_SUCESS;
+}
+uint8_t IEC104_ASDU_Call(PIEC10X_ASDU_T Iec10x_Asdu)
+{
+
+    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+    uint8_t      qoi       = asdu_info->_element[0];
+    uint8_t      Prio      = 0;
+
+    uint32_t InfoAddr = 0;
+
+    /* check info addrest */
+    memcpy(&InfoAddr, asdu_info->_addr, 3);
+    if (InfoAddr != 0)
+    {
+        LOG("-%s- call cmd active error addr(%x) \n", __FUNCTION__, InfoAddr);
+        return RET_ERROR;
+    }
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_ASDU_REASON_ACT:
+        switch (qoi)
+        {
+        case IEC10X_CALL_QOI_TOTAL:
+            Prio                      = IEC10X_PRIO_CALLALL;
+            IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CALL_ALLDATA;
+            IEC104_Call_AllQoi        = qoi;
+            break;
+        case IEC10X_CALL_QOI_GROUP1:
+        case IEC10X_CALL_QOI_GROUP2:
+        case IEC10X_CALL_QOI_GROUP9:
+        case IEC10X_CALL_QOI_GROUP10:
+            Prio                    = IEC10X_PRIO_CALLGROUP;
+            IEC104_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROURPDATA;
+            IEC104_Call_GroupQoi    = qoi;
+            break;
+        default:
+            LOG("-%s- call cmd error qoi(%d) \n", __FUNCTION__, qoi);
+            return RET_ERROR;
+        }
+        IEC104_BuildCallACK(qoi, Prio);
+        /**/
+        IEC104_BuildSignal(qoi, Prio, ENDDEVICE_TYPE_HXTM);
+        IEC104_BuildDetect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXTM);
+        /**/
+        IEC104_BuildSignal(qoi, Prio, ENDDEVICE_TYPE_HXGF);
+        IEC104_BuildDetect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXGF);
+        IEC104_BuildActFinish(qoi, Prio);
+        break;
+
+    default:
+        LOG("-%s- call cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        break;
+    }
+    return RET_SUCESS;
+}
+uint8_t Iec104_Aadu_Clock(PIEC10X_ASDU_T Iec10x_Asdu)
+{
+
+    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+
+    memcpy(&IEC10X_Cp56time2a, asdu_info->_element, sizeof(CP56Time2a_T));
+
+    if (asdu_info->_addr[0] != 0 || asdu_info->_addr[1] != 0 || asdu_info->_addr[2] != 0)
+    {
+        LOG("-%s- Clock cmd error addr(0x%02x:%02x:%02x) \n", __FUNCTION__, asdu_info->_addr[0], asdu_info->_addr[2], asdu_info->_addr[2]);
+        return RET_ERROR;
+    }
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_COT_ACT:
+        LOG("-%s- Clock cmd (20%d-%d-%d %d %d:%d:%d) \n", __FUNCTION__, IEC10X_Cp56time2a._year._year, IEC10X_Cp56time2a._month._month, IEC10X_Cp56time2a._day._dayofmonth,
+            IEC10X_Cp56time2a._day._dayofweek, IEC10X_Cp56time2a._hour._hours, IEC10X_Cp56time2a._min._minutes, IEC10X_Cp56time2a._milliseconds);
+        /*get time*/
+        /*...*/
+        IEC10X->SetTime(&IEC10X_Cp56time2a);
+        // IEC104_Build_S_Ack();
+
+        break;
+    case IEC10X_COT_SPONT:
+        LOG("-%s- Clock cmd spont \n", __FUNCTION__);
+        break;
+    default:
+        LOG("-%s- Clock cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        break;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_ASDU_SetAct(PIEC10X_ASDU_T Iec10x_Asdu, uint8_t Type)
+{
+
+    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
+    uint8_t     *ptr       = NULL;
+    uint8_t      n = Iec10x_Asdu->_num._num, Sq = Iec10x_Asdu->_num._sq, i;
+    float        Value    = 0.0;
+    uint32_t     InfoAddr = 0;
+
+    /* if sq == 1 */
+    PIEC10X_DETECT_T   detect   = NULL;
+    PIEC10X_DETECT_F_T detect_f = NULL;
+
+    /* if sq == 0 */
+    PIEC10X_DETECT_SQ0_T   detect_Sq0   = NULL;
+    PIEC10X_DETECT_SQ0_F_T detect_Sq0_f = NULL;
+
+    /* check info addrest */
+    memcpy(&InfoAddr, asdu_info->_addr, 3);
+
+    switch (Iec10x_Asdu->_reason._reason)
+    {
+
+    case IEC10X_COT_ACT:
+
+        switch (Type)
+        {
+        case IEC10X_C_SE_NA_1:
+
+            if (Sq == 1)
+            {
+                ptr = asdu_info->_element;
+                for (i = 0; i < n; i++)
+                {
+
+                    detect = (PIEC10X_DETECT_T)ptr;
+                    Value  = (float)(detect->_detect);
+                    ptr += sizeof(IEC10X_DETECT_T);
+                    IEC10X->SetConfig(Value, InfoAddr + i);
+                }
+            }
+            else if (Sq == 0)
+            {
+                ptr = Iec10x_Asdu->_info;
+                for (i = 0; i < n; i++)
+                {
+
+                    detect_Sq0 = (PIEC10X_DETECT_SQ0_T)ptr;
+                    Value      = (float)(detect_Sq0->_detect);
+                    InfoAddr   = 0;
+                    memcpy(&InfoAddr, detect_Sq0->_addr, 3);
+                    IEC10X->SetConfig(Value, InfoAddr);
+                    ptr += sizeof(IEC10X_DETECT_SQ0_T);
+                }
+            }
+            break;
+        case IEC10X_C_SE_NC_1:
+            if (Sq == 1)
+            {
+                ptr = asdu_info->_element;
+                for (i = 0; i < n; i++)
+                {
+
+                    detect_f = (PIEC10X_DETECT_F_T)ptr;
+                    Value    = detect_f->_detect;
+                    ptr += sizeof(IEC10X_DETECT_F_T);
+                    IEC10X->SetConfig(Value, InfoAddr + i);
+                }
+            }
+            else if (Sq == 0)
+            {
+                ptr = Iec10x_Asdu->_info;
+                for (i = 0; i < n; i++)
+                {
+                    detect_Sq0_f = (PIEC10X_DETECT_SQ0_F_T)ptr;
+                    Value        = (float)(detect_Sq0_f->_detect);
+                    memcpy(&InfoAddr, detect_Sq0_f->_addr, 3);
+                    IEC10X->SetConfig(Value, InfoAddr);
+                    ptr += sizeof(IEC10X_DETECT_SQ0_F_T);
+                }
+            }
+            break;
+        default:
+            LOG("-%s-, Type error !", __FUNCTION__);
+            return RET_ERROR;
+        }
+        break;
+
+    default:
+        LOG("-%s- , error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason);
+        return RET_ERROR;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t IEC104_Build_SetAck(uint8_t Prio, uint8_t Type)
+{
+
+    uint8_t  len = 0;
+    uint8_t *ptr = NULL;
+
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = Type;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 0;
+    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTFIN;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info*/
+    ptr = info->_addr;
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec104_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+uint8_t Iec104_Deal_SN(uint16_t SendSn, uint16_t RecvSn)
+{
+
+    LOG("Receive Pakage I(%d,%d), Send(%d,%d)\n", SendSn, RecvSn, Iec104_BuildSendSn, Iec104_BuildRecvSn);
+
+#if 0
+    if(SendSn > Iec104_DealSendSn+1){
+        LOG("-%s-, error,send last(%d),now(%d) \n",__FUNCTION__,Iec104_DealSendSn,SendSn);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED;
+        return RET_ERROR;
+    }else if(SendSn < Iec104_DealSendSn+1){
+        LOG("-%s-, Retransmit,send last(%d),now(%d) \n",__FUNCTION__,Iec104_DealSendSn,SendSn);
+        return RET_ERROR;
+    }
+    if(RecvSn != Iec104_BuildSendSn){
+        LOG("-%s-, error,receive last(%d),now(%d) \n",__FUNCTION__,Iec104_BuildSendSn,RecvSn);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED;
+        return RET_ERROR;
+    }
+    if(RecvSn < Iec104_DealRecvSn){
+        LOG("-%s-, error,receive2 last(%d),now(%d) \n",__FUNCTION__,Iec104_DealRecvSn,RecvSn);
+        return RET_ERROR;
+    }
+#endif
+
+    if (SendSn < Iec104_DealSendSn || RecvSn < Iec104_DealRecvSn)
+    {
+
+        LOG("-%s-, error,send last(%d),now(%d). recv last(%d),now(%d) \n", __FUNCTION__,
+            Iec104_DealSendSn, SendSn, Iec104_DealRecvSn, RecvSn);
+        return RET_ERROR;
+    }
+    Iec104_BuildRecvSn = SendSn + 1;
+
+    Iec104_DealSendSn = SendSn;
+    Iec104_DealRecvSn = RecvSn;
+
+    // Iec104_BuildRecvSn++;
+
+    /* return S ACK */
+    IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_S_ACK;
+    Iec104_TimeCycle_S      = 0;
+
+    return RET_SUCESS;
+}
+int8_t Iec104_BuildDataAck(uint8_t TI, uint16_t COT, uint32_t InfoAddr, uint16_t Info, uint8_t Prio)
+{
+
+    uint8_t  len    = 0;
+    uint8_t *ptr    = NULL;
+    uint32_t Temp32 = 0;
+
+    /* build head */
+    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
+    PIEC10X_ASDU_T asdu       = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+    PASDU_INFO_T   info       = (PASDU_INFO_T)(asdu->_info);
+
+    /*build head*/
+    Iec104Data->Head = IEC104_HEAD;
+
+    /*build control code*/
+    Iec104Data->Ctrl.I.Type   = 0;
+    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
+    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
+
+    /*build ASDU , COT ,Addr*/
+    asdu->_type           = TI;
+    asdu->_num._sq        = 0;
+    asdu->_num._num       = 1;
+    asdu->_reason._reason = COT;
+    asdu->_addr           = Iec10x_Sta_Addr;
+
+    /*build info*/
+    ptr    = info->_addr;
+    Temp32 = InfoAddr;
+    memcpy(ptr, &Temp32, 3);
+
+    ptr = info->_element;
+    if (COT == IEC10X_COT_ACT_TERMINAL || COT == IEC10X_COT_ACTCON || COT == IEC10X_COT_ACT_TERMINAL_ACK || COT == IEC10X_TI_AP_FIRM_BACKOFF)
+    {
+        ptr[0] = 0;
+        ptr[1] = 0;
+        ptr += 2;
+    }
+    else if (COT == IEC10X_COT_DATA_ACK || COT == IEC10X_COT_DATA_FIN_ACK)
+    {
+        memcpy(ptr, &Info, 2);
+        ptr += 2;
+    }
+
+    /*len*/
+    len             = ptr - Iec104_Sendbuf;
+    Iec104Data->Len = len - 2;
+
+    // DumpHEX(Iec104_Sendbuf,len);
+    /* enqueue to the transmisson queue */
+    IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL);
+
+    return RET_SUCESS;
+}
+
+int8_t Iec104_Deal_FirmUpdate(PIEC10X_ASDU_T asdu, uint8_t Len)
+{
+
+    uint16_t     cot     = asdu->_reason._reason;
+    uint16_t     FlagNum = 0, i;
+    uint8_t      DataLen = Len - IEC104_DATA_LEN - 3; /* flag num 2, check sum 1 byte*/
+    PASDU_INFO_T element = (PASDU_INFO_T)(asdu->_info);
+    uint8_t     *DataPtr = (uint8_t *)(element->_element) + 3;
+    uint8_t      TI = asdu->_type, csum = 0, CsumTemp = 0;
+    uint32_t     FirmwareType = 0;
+    int8_t       ret          = 0;
+
+    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);
+
+    FlagNum = *(uint16_t *)(info->_element);
+    memcpy(&FirmwareType, asdu->_info, 3);
+
+    if (Len == 0)
+    {
+        LOG("-%s-,data:%d,Len:%d error!\n", __FUNCTION__, FlagNum, DataLen);
+        return RET_ERROR;
+    }
+
+    /* reset the flag counter */
+    if (FlagNum == 1)
+    {
+        FirmFlagCount          = 0;
+        Iec10x_Update_SeekAddr = 0;
+    }
+
+    switch (cot)
+    {
+
+    case IEC10X_COT_DATA:
+
+        if (FlagNum == FirmFlagCount + 1)
+        {
+
+            /* check sum */
+            csum = info->_element[2];
+
+            for (i = 0; i < DataLen; i++)
+            {
+                CsumTemp += DataPtr[i];
+            }
+            if (CsumTemp == csum)
+            {
+                LOG("-%s-,data:%d,Len:%d,seek:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr);
+                for (i = 0; i < 3; i++)
+                {
+                    ret = IEC10X->SaveFirmware(DataLen, DataPtr, FirmwareType, Iec10x_Update_SeekAddr);
+                    if (ret == RET_SUCESS)
+                        break;
+                }
+                if (ret == RET_ERROR)
+                {
+                    LOG("save firmware error \n");
+                    break;
+                }
+
+                FirmFlagCount = FlagNum;
+                Iec10x_Update_SeekAddr += DataLen;
+            }
+            else
+            {
+                LOG("%s, check sum error:%d,need:%d,num:%d\n", __FUNCTION__, CsumTemp, csum, FlagNum);
+            }
+        }
+        else if (FlagNum < FirmFlagCount + 1)
+        {
+            LOG("update flag resend,need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum);
+        }
+        else
+        {
+            LOG("update flag error! need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum);
+            // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
+        }
+        break;
+
+    case IEC10X_COT_DATA_NEEDACK:
+        if (FlagNum == FirmFlagCount + 1)
+        {
+
+            /* check sum */
+            csum = info->_element[2];
+            for (i = 0; i < DataLen; i++)
+            {
+                CsumTemp += DataPtr[i];
+            }
+            if (CsumTemp == csum)
+            {
+                LOG("-%s-,data need ack:%d,Len:%d,seek:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr);
+
+                for (i = 0; i < 3; i++)
+                {
+                    ret = IEC10X->SaveFirmware(DataLen, DataPtr, FirmwareType, Iec10x_Update_SeekAddr);
+                    if (ret == RET_SUCESS)
+                        break;
+                }
+
+                if (ret == RET_ERROR)
+                {
+                    LOG("save firmware error \n");
+                    break;
+                }
+                Iec104_BuildDataAck(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum, 1);
+
+                FirmFlagCount = FlagNum;
+                Iec10x_Update_SeekAddr += DataLen;
+            }
+            else
+            {
+                LOG("%s,need ack check sum error:%d,need:%d,num...:%d\n", __FUNCTION__, CsumTemp, csum, FlagNum);
+                // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
+            }
+        }
+        else if (FlagNum < FirmFlagCount + 1)
+        {
+            LOG("update flag resend,need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum);
+            Iec104_BuildDataAck(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum, 1);
+        }
+        else
+        {
+            LOG("update flag error! need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum);
+            // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
+        }
+        break;
+
+    case IEC10X_COT_DATA_FIN:
+        if (FirmFlagCount == FlagNum)
+        {
+            LOG("-%s-,data finish:%d,Len:%d,Total Len:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr);
+            ret = IEC10X->CheckFirmware(FirmwareType, Iec10x_Update_SeekAddr);
+            if (ret == RET_SUCESS)
+            {
+                Iec104_BuildDataAck(TI, IEC10X_COT_DATA_FIN_ACK, FirmwareType, FlagNum, 1);
+                IEC10X->UpdateFirmware(FirmwareType);
+            }
+            else
+            {
+                /* check firmware error ,terminal update */
+                Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, 0, 1);
+            }
+        }
+        else
+        {
+            LOG("-%s-,data finish error:%d,Len:%d,Total Len:%d,FirmFlagCount:%d,FlagNum:%d, \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr, FirmFlagCount, FlagNum);
+            return RET_ERROR;
+        }
+        break;
+
+    case IEC10X_COT_ACT_TERMINAL:
+        LOG("-%s-, Terminal:%d,Len:%d \n", __FUNCTION__, FlagNum, DataLen);
+        Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL_ACK, FirmwareType, 0, 1);
+        break;
+    case IEC10X_COT_ACT_TERMINAL_ACK:
+        LOG("-%s-, Terminal Ack \n", __FUNCTION__);
+        break;
+    default:
+        LOG("-%s-,data:%d,Len:%d error cot: \n", __FUNCTION__, FlagNum, Len);
+        return RET_ERROR;
+    }
+    return RET_SUCESS;
+}
+
+void Iec104_Tester_Timer(void)
+{
+
+    IEC104_STATE_FLAG_TESTER    = IEC104_FLAG_IDLE;
+    Iec104_TimeCycle_TesterIdle = 0;
+}
+
+uint8_t Iec104_Deal_I(PIEC104_DATA_T Iec104Data, uint16_t len)
+{
+
+    uint8_t  Type;
+    uint16_t RecvSn, SendSn;
+    uint32_t FirmwareType = 0;
+
+    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
+
+    SendSn = Iec104Data->Ctrl.I.SendSn;
+    RecvSn = Iec104Data->Ctrl.I.RecvSn;
+
+    /* check asdu addrest */
+    if (Iec10x_Sta_Addr != asdu->_addr)
+    {
+        LOG("-%s-, error asdu addr(%x)(%x) \n", __FUNCTION__, Iec10x_Sta_Addr, asdu->_addr);
+        return RET_ERROR;
+    }
+
+    /* deal the receive and send serial number */
+    if (Iec104_Deal_SN(SendSn, RecvSn) == RET_ERROR)
+    {
+        return RET_ERROR;
+    }
+    /* Start tester timer */
+    Iec104_Tester_Timer();
+
+    Type = asdu->_type;
+    switch (Type)
+    {
+
+    case IEC10X_C_IC_NA_1:
+        LOG("++++Asdu Type Call cmd... \n");
+        IEC104_ASDU_Call(asdu);
+        IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE;
+        break;
+    case IEC10X_C_CS_NA_1:
+        LOG("++++Asdu Type Clock syc cmd... \n");
+        Iec104_Aadu_Clock(asdu);
+        break;
+
+    case IEC10X_C_SE_NA_1:
+    case IEC10X_C_SE_NC_1:
+        LOG("++++Asdu Type Set type(%d)... \n", Type);
+        IEC104_ASDU_SetAct(asdu, Type);
+        IEC104_Build_SetAck(1, Type);
+        break;
+    case IEC10X_TI_FIRM_UPDATE:
+        LOG("++++Asdu Type Firmware Update... \n");
+        Iec104_Deal_FirmUpdate(asdu, len);
+        break;
+    case IEC10X_TI_AP_FIRM_BACKOFF:
+        LOG("++++Asdu Type Firmware Backoff... \n");
+        memcpy(&FirmwareType, asdu->_info, 3);
+        Iec104_BuildDataAck(IEC10X_TI_AP_FIRM_BACKOFF, IEC10X_COT_ACTCON, FirmwareType, 0, 1);
+        IEC10X->BackoffFirmware(FirmwareType);
+        break;
+    default:
+        LOG("-%s-, error Type(%d) \n", __FUNCTION__, Type);
+        return RET_ERROR;
+    }
+    return RET_SUCESS;
+}
+
+uint8_t Iec104_Deal_S(PIEC104_DATA_T Iec104Data, uint16_t len)
+{
+
+    return RET_SUCESS;
+}
+uint8_t Iec104_Deal_U(PIEC104_DATA_T Iec104Data, uint16_t len)
+{
+
+    switch (Iec104Data->Ctrl.Func.Func)
+    {
+
+    case IEC104_U_FUNC_STARTDT:
+        LOG(">%s<, function STARTDT \n", __FUNCTION__);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_LINK_INIT;
+        Iec104_TimeCycle       = 0;
+        Iec104_TimeCount       = 0;
+        // IEC104_Build_U(IEC104_U_FUNC_STARTDT,1);
+        // IEC104_Build_InitFin();
+        break;
+    case IEC104_U_FUNC_STOPDT:
+        LOG(">%s<, function STOPDT \n", __FUNCTION__);
+        IEC10X->CloseLink();
+        IEC104_Build_U(IEC104_U_FUNC_STOPDT, 1);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED;
+        break;
+    case IEC104_U_FUNC_TESTER:
+        LOG(">%s<, function TESTER \n", __FUNCTION__);
+        IEC104_Build_U(IEC104_U_FUNC_TESTER, 1);
+        break;
+
+    /* U ACK */
+    case IEC104_U_FUNC_STARTDT_ACK:
+        LOG(">%s<, function STARTDT ACK\n", __FUNCTION__);
+        break;
+    case IEC104_U_FUNC_STOPDT_ACK:
+        LOG(">%s<, function STOPDT ACK\n", __FUNCTION__);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED;
+        break;
+    case IEC104_U_FUNC_TESTER_ACK:
+        LOG(">%s<, function TESTER ACK\n", __FUNCTION__);
+        Iec104_TesterCount = 0;
+        break;
+    default:
+        LOG(">%s<, function ERROR \n", __FUNCTION__);
+        break;
+    }
+    return RET_SUCESS;
+}
+
+void Iex104_Receive(uint8_t *buf, uint16_t len)
+{
+
+    uint8_t       *BufTemp = NULL;
+    int16_t        LenRemain, LenTmp;
+    PIEC104_DATA_T Iec104Data = NULL;
+
+    if (buf == NULL)
+    {
+        LOG("-%s-,buffer (null)", __FUNCTION__);
+        return;
+    }
+#if 0
+    if(len <= 0 || len>IEC104_MAX_BUF_LEN || len<BufTemp[0]+2){
+        LOG("-%s-,buffer len error(%d) \n",__FUNCTION__,len);
+        return;
+    }
+#endif
+
+    BufTemp   = buf;
+    LenRemain = len;
+
+    while (BufTemp < buf + len)
+    {
+
+        Iec104Data = (PIEC104_DATA_T)BufTemp;
+        Iec10x_Lock();
+        if (Iec104Data->Head == IEC104_HEAD)
+        {
+
+            LenTmp = Iec104Data->Len + 2;
+            if (LenRemain < IEC104_HEAD_LEN)
+            {
+                LOG("_%s_,len error(%d) \n", __FUNCTION__, len);
+                Iec10x_UnLock();
+                return;
+            }
+            if (Iec104Data->Ctrl.Type.Type1 == 0)
+            {
+                LOG("-%s-,Frame Type I \n", __FUNCTION__);
+                Iec104_Deal_I(Iec104Data, LenTmp);
+            }
+            else if (Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 0)
+            {
+                LOG("-%s-,Frame Type S \n", __FUNCTION__);
+                Iec104_Deal_S(Iec104Data, LenTmp);
+            }
+            else if (Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 1)
+            {
+                LOG("-%s-,Frame Type U \n", __FUNCTION__);
+                Iec104_Deal_U(Iec104Data, LenTmp);
+            }
+        }
+        else
+        {
+            LOG("-%s-,head type error(%d) \n", __FUNCTION__, BufTemp[0]);
+            Iec10x_UnLock();
+            return;
+        }
+        Iec10x_UnLock();
+        BufTemp += LenTmp;
+        LenRemain -= LenTmp;
+    }
+    return;
+}
+
+void Iec104_ResetFlag(void)
+{
+
+    IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_IDLE;
+    IEC104_STATE_FLAG_GROUP   = IEC104_FLAG_IDLE;
+    IEC104_STATE_FLAG_CLOCK   = IEC104_FLAG_IDLE;
+    IEC104_STATE_FLAG_TESTER  = IEC104_FLAG_IDLE;
+
+    Iec104_BuildSendSn = 0;
+    Iec104_BuildRecvSn = 0;
+    Iec104_DealSendSn  = -1;
+    Iec104_DealRecvSn  = 0;
+
+    Iec104_TesterCount = 0;
+}
+
+uint32_t TestCount_Temp = 0;
+uint8_t  Iec104_StateMachine(void)
+{
+
+    /*Init link*/
+    switch (IEC104_STATE_FLAG_INIT)
+    {
+
+    case IEC104_FLAG_CLOSED:
+#if defined(IEC104_STM32_FUJIAN_HX)
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_UPLOAD_ADDR;
+#else
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_START_LINK;
+        IEC10X_ClearQ();
+        Iec104_ResetFlag();
+#endif /* IEC104_STM32_FUJIAN_HX */
+        break;
+    case IEC104_FLAG_SEND_CLOSED:
+        Iec104_TimeCycle += IEC104_CYCLE_TIME_MS;
+        if (Iec104_TimeCycle > IEC104_RESEND_TIME_MS)
+        {
+            Iec104_TimeCycle = 0;
+            Iec104_TimeCount++;
+            IEC104_Build_U(IEC104_U_FUNC_STOPDT, 0);
+        }
+        if (Iec104_TimeCount >= 3)
+        {
+            Iec104_TimeCount       = 0;
+            IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE;
+            IEC10X->CloseLink();
+        }
+        break;
+    case IEC104_FLAG_RECV_CLOSED:
+        Iec104_ResetFlag();
+        IEC10X_ClearQ();
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS;
+        break;
+    case IEC104_FLAG_LINK_INIT:
+        LOG("Iec104 machine state :IEC104_FLAG_LINK_INIT \n");
+        Iec104_ResetFlag();
+        Iec10x_Sta_Addr = IEC10X->GetLinkAddr();
+        IEC104_Build_U(IEC104_U_FUNC_STARTDT, 1);
+        IEC104_Build_InitFin();
+        IEC104_BuildUpload(IEC10X_TI_AP_BASE_INFO, IEC10X_PRIO_INITLINK, AP_TYPE_BASE_INFO);
+        IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS;
+        break;
+    case IEC104_FLAG_UPLOAD_ADDR:
+        Iec104_TimeCycle += IEC104_CYCLE_TIME_MS;
+        if (Iec104_TimeCycle > IEC104_RESEND_TIME_MS)
+        {
+            Iec10x_Sta_Addr  = IEC10X->GetLinkAddr();
+            Iec104_TimeCycle = 0;
+            Iec104_TimeCount++;
+            IEC104_UploadAddr();
+        }
+        if (Iec104_TimeCount >= 3)
+        {
+            Iec104_TimeCount       = 0;
+            IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE;
+            IEC10X->CloseLink();
+        }
+        break;
+
+    case IEC104_FLAG_CONNECT_SUCESS:
+    case IEC104_FLAG_IDLE:
+    default:
+        break;
+    }
+    if (IEC104_STATE_FLAG_INIT == IEC104_FLAG_CONNECT_SUCESS)
+    {
+
+        /* Return s ack */
+        switch (IEC104_STATE_FLAG_S_ACK)
+        {
+
+        case IEC104_FLAG_S_ACK:
+            Iec104_TimeCycle_S += IEC104_CYCLE_TIME_MS;
+            if (Iec104_TimeCycle_S > IEC104_S_ACK_TIMEOUT)
+            {
+                Iec104_TimeCycle_S = 0;
+                IEC104_Build_S_Ack();
+                IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE;
+            }
+            break;
+        case IEC104_FLAG_IDLE:
+            break;
+        default:
+            break;
+        }
+        /* test spon */
+#if 0
+        if(TestCount_Temp++>(10*60*20)){
+            TestCount_Temp = 0;
+            IEC104_BuildSignal_Spon(1, 1, IEC104_INFOADDR_STATE_HXGF+2);
+            IEC104_BuildDetectF_Spont(1, 60.2, IEC104_INFOADDR_VALUE_HXTM+2);
+            IEC104_BuildDetectF_Spont(1, 61.1, IEC104_INFOADDR_VALUE_HXGF+2);
+        }
+#endif
+    }
+    /* Tester */
+    switch (IEC104_STATE_FLAG_TESTER)
+    {
+    case IEC104_FLAG_TESTER:
+        IEC104_Build_U(IEC104_U_FUNC_TESTER, 0);
+        IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;
+        Iec104_TesterCount++;
+        LOG("Tester Count(%d)... \n", Iec104_TesterCount);
+        if (Iec104_TesterCount > 3)
+        {
+            Iec104_TesterCount = 0;
+            LOG("Tester error(%d)... \n", Iec104_TesterCount);
+            IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED;
+            IEC10X->CloseLink();
+        }
+        break;
+    case IEC104_FLAG_TESTER_STOP:
+        break;
+    case IEC104_FLAG_IDLE:
+        Iec104_TimeCycle_TesterIdle += IEC104_CYCLE_TIME_MS;
+        if (Iec104_TimeCycle_TesterIdle > IEC104_TESTER_IDLE_TIMEOUT)
+        {
+            Iec104_TimeCycle_TesterIdle = 0;
+            IEC104_STATE_FLAG_TESTER    = IEC104_FLAG_TESTER;
+        }
+        break;
+    default:
+        break;
+    }
+    return RET_SUCESS;
+}

+ 204 - 0
User/app/iec104/iec104.h

@@ -0,0 +1,204 @@
+
+
+#ifndef _IEC104_H
+#define _IEC104_H
+
+#include "iec10x.h"
+#include "project_var.h"
+
+#define     IEC104_MAX_BUF_LEN          256
+
+#define     IEC104_HEAD                 0X68
+/*
+ * PRIO
+ * */
+#define             IEC104_PRIO_INITLINK            0
+#define             IEC104_PRIO_CALLALL             1
+#define             IEC104_PRIO_CALLGROUP           2
+#define             IEC104_PRIO_CLOCK               3
+#define             IEC104_PRIO_DELAY               3
+#define             IEC104_PRIO_PULSE               0
+#define             IEC104_PRIO_SPON                0
+
+/*
+ * Ctrl U Function
+ * */
+#define             IEC104_U_FUNC_STARTDT           0x07		//0B00000111
+#define             IEC104_U_FUNC_STOPDT            0x13		//0B00010011
+#define             IEC104_U_FUNC_TESTER            0x43		//0B01000011
+
+#define             IEC104_U_FUNC_STARTDT_ACK       0x0b		//0B00001011
+#define             IEC104_U_FUNC_STOPDT_ACK        0x23		//0B00100011
+#define             IEC104_U_FUNC_TESTER_ACK        0x83		//0B10000011
+
+/*
+ * ASDU Type Upload station address
+ * */
+#define             IEC104_ASDU_TYPE_M_DTU_INF_1    180
+#define             IEC104_INFO_SIGNATURE           0XEB90EB90
+
+
+/*
+ * Info Address
+ * */
+#define             IEC104_DEV_TYPE_HXGF               0X03
+#define             IEC104_DEV_TYPE_HXTM               0X01
+
+#define             IEC104_INFOADDR_VALUE_HXGF         0X004001
+#define             IEC104_INFOADDR_VALUE_HXTM         0X004201
+
+#define             IEC104_INFOADDR_STATE_HXGF         0X000001
+#define             IEC104_INFOADDR_STATE_HXTM         0X000301
+
+/* base device information */
+#define             IEC104_INFOADDR_BASE_DEVINFO       0X102001
+
+/*
+ * device type 
+ */
+//#define       ENDDEVICE_TYPE_ERR                  0
+//#define       ENDDEVICE_TYPE_HXPF                 2
+#define         ENDDEVICE_TYPE_HXTM                 1
+#define         ENDDEVICE_TYPE_HXGF                 3
+
+#define         AP_TYPE_BASE_INFO                   4    
+
+/* COT */
+#define         AP_COT_BASE_INFO                    18  
+
+
+#pragma pack(1)
+
+/*
+ *  Iec104 package
+ * */
+/* Control filed I type */
+typedef struct {
+
+    uint32_t Type:1;
+    uint32_t SendSn:15;
+    uint32_t Reserve:1;
+    uint32_t RecvSn:15;
+}IEC104_CTRL_I_T, *PIEC104_CTRL_I_T;
+
+/* Control filed S type */
+typedef struct {
+
+    uint32_t Type1:1;
+    uint32_t Type2:1;
+    uint32_t Reserve:15;
+    uint32_t RecvSn:15;
+}IEC104_CTRL_S_T, *PEC104_CTRL_S_TP;
+
+/* Control filed U type */
+typedef struct {
+
+    uint32_t Type1:1;
+    uint32_t Type2:1;
+    uint32_t Startdt:1;
+    uint32_t StartdtAck:1;
+    uint32_t Stopdt:1;
+    uint32_t StopdtAck:1;
+    uint32_t Tester:1;
+    uint32_t TesterAck:1;
+    uint32_t Reserve:24;
+}IEC104_CTRL_U_T, *PIEC104_CTRL_U_T;
+
+/* Control filed type */
+typedef struct {
+
+    uint32_t Type1:1;
+    uint32_t Type2:1;
+    uint32_t Reserve:30;
+
+}IEC104_CTRLType_T, *PIEC104_CTRLType_T;
+
+/* Control filed type */
+typedef struct {
+
+    uint32_t Func:8;
+    uint32_t Reserve:24;
+
+}IEC104_CTRLFunc_T, *PIEC104_CTRLFunc_T;
+
+typedef union{
+
+    IEC104_CTRL_I_T     I;
+    IEC104_CTRL_S_T     S;
+    IEC104_CTRL_U_T     U;
+    IEC104_CTRLType_T   Type;
+    IEC104_CTRLFunc_T   Func;
+}IEC104_CTRL_T, *PIEC104_CTRL_T;
+
+typedef struct{
+
+    uint8_t         Head;
+    uint8_t         Len;
+    IEC104_CTRL_T   Ctrl;
+    uint8_t         Asdu[1];
+}IEC104_DATA_T,*PIEC104_DATA_T;
+
+typedef struct {
+
+    float Current;
+    float Temperature;    
+}Iec10x_DevA_Info_T, *PIec10x_DevA_Info_T;
+
+#pragma pack()
+
+/*
+ * length
+ * */
+#define     IEC104_HEAD_LEN          (sizeof(IEC104_DATA_T)-1)
+#define     IEC104_ASDU_LEN          (sizeof(IEC10X_ASDU_T)-1)
+#define     IEC104_INFO_LEN          (sizeof(ASDU_INFO_T)-1)
+#define     IEC104_DATA_LEN          (IEC104_HEAD_LEN+IEC104_ASDU_LEN+IEC104_INFO_LEN)
+
+
+enum {
+    IEC104_FLAG_RECV_CLOSED,        /*0*/
+    IEC104_FLAG_SEND_CLOSED,        /*1*/
+    IEC104_FLAG_CLOSED,             /*2*/
+    IEC104_FLAG_LINK_INIT,          /*3*/
+    IEC104_FLAG_IDLE,               /*4*/
+    IEC104_FLAG_UPLOAD_ADDR,             /*5*/
+    IEC104_FLAG_START_LINK,             /*6*/
+    IEC104_FLAG_REQ_LINK,             /*7*/
+    IEC104_FLAG_RESET_REMOTE_LINK,             /*8*/
+    IEC104_FLAG_INIT_FIN,             /*9*/
+    IEC104_FLAG_CALL_ALLDATA,             /*10*/
+    IEC101_FLAG_CALL_GROURPDATA,             /*11*/
+    IEC104_FLAG_CALL_ACT_FIN,             /*12*/
+    IEC104_FLAG_CALL_SIG_TOTAL,             /*13*/
+    IEC104_FLAG_CALL_DET_TOTAL,             /*14*/
+    IEC104_FLAG_CLOCK_SYS,             /*15*/
+    IEC104_FLAG_TESTER,             /*16*/
+    IEC104_FLAG_TESTER_STOP,             /*17*/
+    IEC104_FLAG_CALL_GROUP,             /*18*/
+    IEC104_FLAG_CONNECT_SUCESS,             /*19*/
+    IEC104_FLAG_S_ACK,             /*20*/
+};
+
+/*
+*********************************************************************************************************
+*                          EXTERN  VARIABLE
+*********************************************************************************************************
+*/
+extern      uint8_t             IEC104_STATE_FLAG_INIT;
+extern      uint8_t             IEC104_STATE_FLAG_CALLALL;
+extern      uint8_t             IEC104_STATE_FLAG_GROUP;
+extern      uint8_t             IEC104_STATE_FLAG_CLOCK;
+extern      uint8_t             IEC104_STATE_FLAG_PULSE;
+
+/*
+*********************************************************************************************************
+*                          FUNCTION
+*********************************************************************************************************
+*/
+uint8_t         Iec104_StateMachine(void);
+uint8_t         IEC104_BuildSignal_Spon(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV);
+uint8_t         IEC104_BuildDetectF_Spont(uint8_t TimeFlag, float detectV, uint16_t addrV);
+void            Iex104_Receive(uint8_t *buf, uint16_t len);
+uint8_t         IEC104_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV);
+
+#endif

+ 167 - 0
User/app/iec104/iec104_init.c

@@ -0,0 +1,167 @@
+/*******************************************************************
+Copyright (C):
+File name    :    HXCP_STM32.C
+DESCRIPTION  :
+AUTHOR       :
+Version      :    1.0
+Date         :    2014/02/26
+Others       :
+History      :
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+1) Date: 2014/02/26         Author: ChenDajie
+   content:
+
+*******************************************************************/
+
+#include "PRIO_QUEUE_Iec10x.h"
+#include "dwt.h"
+#include "fly_param.h"
+#include "iec10x.h"
+#include "main.h"
+#include "project_var.h"
+// #include <errno.h>
+// #include <signal.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+#include <string.h>
+// #include <sys/socket.h>
+// #include <sys/types.h>
+// #include <sys/wait.h>
+// #include <unistd.h>
+
+/*******************************************************************************
+ * Function Name  : stm32f103_init
+ * Description    : stm32f103_init program
+ * Input          : None
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+static int
+Linux_init(void)
+{
+
+    return 0;
+}
+
+static void *Linux_Malloc(unsigned char NumByte)
+{
+
+    return malloc(NumByte);
+}
+
+static void Linux_Free(void *pblock)
+{
+
+    free(pblock);
+}
+
+static uint32_t Linux_SetTime(PCP56Time2a_T time)
+{
+
+    return RET_SUCESS;
+}
+static uint32_t Linux_GetTime(PCP56Time2a_T time)
+{
+
+    return RET_SUCESS;
+}
+
+static int8_t Linux_GetStationInfo(uint16_t *Addr, uint8_t n, uint8_t *MaxNum)
+{
+
+    *MaxNum = WTP_SUPPORT_END_NUMBER;
+    *Addr   = n;
+    return RET_SUCESS;
+}
+
+static float Linux_GetStaTemp(uint16_t Addr)
+{
+
+    return 30;
+}
+
+static uint16_t Linux_GetLinkAddr(void)
+{
+
+    return 0x0001;
+}
+
+static void Linux_CloseLink(void)
+{
+
+    // GPRSFlag = SYSTEM_FLAG_GPRS_CLOSE;
+    // IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED;
+}
+
+void delay_ms(uint16_t ms)
+{
+
+    us_delay(ms * 1000);
+}
+
+uint8_t Linuxsend(int socketfd, char *buf, int len)
+{
+
+    if (-1 == write(socketfd, buf, len))
+    {
+        LOG("-%s-,Send error \n", __FUNCTION__);
+        return RET_ERROR;
+    }
+    printf("Send Ok!\r\n");
+
+    return RET_SUCESS;
+}
+void LinuxLock(void)
+{
+    INT8U err;
+    OSMutexPend(net_mutex, 0, &err);
+    // pthread_mutex_lock(&mutex);
+}
+void LinuxUnlock()
+{
+    OSMutexPost(net_mutex);
+    // pthread_mutex_unlock(&mutex);
+}
+/*******************************************************************************
+ * Function Name  : stm32f103
+ * Description    : stm32f103
+ * Input          : None
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+static IEC10X_T Linux = {
+    "Linux",
+    Linux_init,
+    delay_ms,
+    Linux_CloseLink,
+    Linux_Malloc,
+    Linux_Free,
+    IEC10X_PrioEnQueue,
+    IEC10X_PrioDeQueue,
+    IEC10X_PrioFindQueueHead,
+    IEC10X_HighestPrio, /* Get the highest Prio Queue*/
+    IEC10X_PrioInitQueue,
+    IEC10X_Prio_ClearQueue,
+    Linuxsend,
+    Linux_SetTime,
+    Linux_GetTime,
+    Linux_GetStationInfo,
+    Linux_GetStaTemp,
+    Linux_GetLinkAddr,
+
+#ifdef IEC10XLOCK
+    LinuxLock,
+    LinuxUnlock
+#endif
+};
+/*******************************************************************************
+ * Function Name  : mstm32f103RegisterShtxxain
+ * Description    : Main program
+ * Input          : None
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+uint32_t Stm32f103RegisterIec10x(void)
+{
+    return RegisterIEC10XMoudle(&Linux);
+}

+ 202 - 0
User/app/iec104/iec10x.c

@@ -0,0 +1,202 @@
+#include "iec10x.h"
+#include "project_var.h"
+
+PIEC10X_T          IEC10X          = NULL;
+uint16_t           Iec10x_Sta_Addr = 0;
+Iec10x_PrioQueue_T Iec10x_PrioQueueArray[IEC10X_PRIO_MAX];
+
+uint16_t     IEC10X_Cp16time2a   = 0;
+uint16_t     IEC10X_Cp16time2a_V = 0;
+CP56Time2a_T IEC10X_Cp56time2a;
+
+/*******************************************************************************
+* Function Name  : IEC10X_InitQ
+* Description    : Init queue.
+* Input          : None
+* Output         : None
+* Return         : 0 failure
+                   len sucess
+*******************************************************************************/
+
+void Iec10x_Lock(void)
+{
+
+#ifdef IEC10XLOCK
+    if (IEC10X->LOCK != NULL)
+        IEC10X->LOCK();
+#endif
+}
+void Iec10x_UnLock(void)
+{
+
+#ifdef IEC10XLOCK
+    if (IEC10X->UNLOCK != NULL)
+        IEC10X->UNLOCK();
+#endif
+}
+void IEC10X_InitQ(void)
+{
+
+    uint8_t i;
+    for (i = 0; i < IEC10X_PRIO_MAX; i++)
+    {
+        IEC10X->InitQueue(&Iec10x_PrioQueueArray[i]);
+    }
+}
+void IEC10X_ClearQ(void)
+{
+    uint8_t i;
+    for (i = 0; i < IEC10X_PRIO_MAX; i++)
+    {
+        IEC10X->ClearQueue(&Iec10x_PrioQueueArray[i]);
+    }
+}
+
+uint8_t IEC10X_GetPrio(uint8_t State)
+{
+
+    /*Prio from 0~7*/
+    uint8_t Prio = 0;
+
+    return Prio;
+}
+
+void IEC10X_Enqueue(uint8_t *EnQBuf, uint16_t Length, uint8_t Prio,
+                    void (*IEC10XCallBack)(Iec10x_CallbackArg_T *Arg), Iec10x_CallbackArg_T *CallbackArg)
+{
+
+    Iec10x_PrioNode_T *new_p;
+
+    Iec10x_Lock();
+    if (Length < IEC10X_HEADER_LENGTH)
+    {
+        LOG("IEC10X_Enqueue,buffer too short \r\n");
+        goto END;
+    }
+
+    new_p = (Iec10x_PrioNode_T *)IEC10X->Malloc(sizeof(Iec10x_PrioNode_T) + Length - 1);
+    if (new_p == NULL)
+    {
+        LOG("IEC10X_Enqueue,malloc error \r\n");
+        goto END;
+    }
+
+    memcpy(new_p->value, EnQBuf, Length);
+    new_p->Length = Length;
+
+    /* Prio from 1~8, Array from 0~7*/
+    if (Prio >= IEC10X_PRIO_MAX)
+    {
+        LOG("IEC10X_Enqueue, error Prio(%d) \r\n", Prio);
+        goto END;
+    }
+
+    /* Set callback Argument */
+    new_p->CallBack = IEC10XCallBack;
+    if (CallbackArg != NULL)
+        new_p->CallBackArg = *CallbackArg;
+
+    new_p->CallBackArg.value = new_p->value;
+    LOG("IEC10X_Enqueue,Prio(%d) elementNum(%d)len(%d)(%d) \r\n", Prio, Iec10x_PrioQueueArray[Prio].ElementNum, Length, new_p->Length);
+    // DumpHEX(new_p->value, new_p->Length);
+    IEC10X->enqueue(&Iec10x_PrioQueueArray[Prio], new_p);
+END:
+    Iec10x_UnLock();
+    return;
+}
+
+Iec10x_PrioNode_T *IEC10X_Dequeue(void)
+{
+    uint8_t            Prio;
+    Iec10x_PrioNode_T *ret;
+    Prio = IEC10X->GetPrio();
+    if (Prio >= 8)
+    {
+        LOG("IEC10X_Dequeue, Error Prio(%d) \r\n", Prio);
+        return 0;
+    }
+    ret = IEC10X->dequeue(&Iec10x_PrioQueueArray[Prio]);
+    if (ret)
+    {
+        Iec10x_PrioQueueArray[Prio].ElementNum--;
+    }
+    LOG("IEC10X_Dequeue(%d) \r\n", ret->Length);
+    return ret;
+}
+Iec10x_PrioNode_T *IEC10X_FindQHead(void)
+{
+
+    uint8_t            Prio;
+    Iec10x_PrioNode_T *ret;
+    Prio = IEC10X->GetPrio();
+    if (Prio >= 8)
+    {
+        return 0;
+    }
+    ret = IEC10X->FindQHead(&Iec10x_PrioQueueArray[Prio]);
+    return ret;
+}
+
+void Iec10x_Scheduled(int socketfd)
+{
+
+    Iec10x_PrioNode_T *DeQNode;
+
+    DeQNode = IEC10X_Dequeue();
+
+    if (DeQNode)
+    {
+
+        LOG("<<-------------------IEC10X (%d)-------------------->> \r\n", DeQNode->Length);
+
+        /* call back funtion */
+        if (DeQNode->CallBack)
+            DeQNode->CallBack(&(DeQNode->CallBackArg));
+
+        DumpHEX(DeQNode->value, DeQNode->Length);
+        IEC10X->Send(socketfd, (char *)(DeQNode->value), DeQNode->Length);
+
+        Iec10x_Lock();
+        IEC10X->Free(DeQNode);
+        Iec10x_UnLock();
+    }
+}
+/*******************************************************************************
+ * Function Name  : RegisterSim900aMoudle
+ * Description    : RegisterSim900aMoudle program
+ * Input          : None
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+int32_t RegisterIEC10XMoudle(void *_IEC10X)
+{
+
+    int ret;
+    if (NULL == _IEC10X)
+    {
+        return -1;
+    }
+    else
+    {
+        IEC10X = (PIEC10X_T)_IEC10X;
+        if (NULL == IEC10X->Init)
+        {
+            return -1;
+        }
+        else
+        {
+            IEC10X_InitQ();
+            // IEC10X_InitInfo();
+            ret = IEC10X->Init();
+            if (0 == ret)
+            {
+#ifdef IEC101_STM32
+                LOG("\r\nRegister \"%s\" IEC101 Success, < HuiXing 2014-2015 > ...\r\n", IEC10X->name);
+#elif defined(IEC104_STM32)
+                LOG("\r\nRegister \"%s\" IEC104 Success, < HuiXing 2014-2015 > ...\r\n", IEC10X->name);
+#endif
+            }
+            return ret;
+        }
+    }
+}

+ 513 - 0
User/app/iec104/iec10x.h

@@ -0,0 +1,513 @@
+/*******************************************************************
+Copyright (C):
+File name    :    Iec10x.h
+DESCRIPTION  :
+AUTHOR       :
+Version      :    1.0
+Date         :    2014/07/23
+Others       :
+History      :
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+1) Date: 2014/07/23         Author: ChenDajie
+   content:
+           add iec104
+
+*******************************************************************/
+
+#ifndef _IEC10X_H
+#define _IEC10X_H
+
+#include "PRIO_QUEUE_Iec10x.h"
+#include "project_var.h"
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * CONFIGURE
+ * */
+#define IEC10XLOCK
+#define PRIO_QUEUE
+
+#ifdef IEC101_STM32
+#define IEC10X_PRIO_MAX 7
+#elif defined(IEC104_STM32)
+#define IEC10X_PRIO_MAX 7
+#endif
+#define IEC10X_HEADER_LENGTH 1
+
+/*
+ * PRIO
+ * */
+#define IEC10X_PRIO_INITLINK  0
+#define IEC10X_PRIO_CALLALL   1
+#define IEC10X_PRIO_CALLGROUP 2
+#define IEC10X_PRIO_CLOCK     3
+#define IEC10X_PRIO_DELAY     3
+#define IEC10X_PRIO_PULSE     0
+#define IEC10X_PRIO_SPON      0
+
+/*
+ *  Transmission  Priority Queue.
+ */
+typedef struct IEC10X_CallbackArg
+{
+    uint8_t *value;
+    uint32_t PicSn;
+    uint32_t FramSerialNum;
+} Iec10x_CallbackArg_T;
+
+typedef struct IEC10X_NODE
+{
+    uint16_t            Length;
+    struct IEC10X_NODE *Next;
+    void (*CallBack)(Iec10x_CallbackArg_T *Arg);
+    Iec10x_CallbackArg_T CallBackArg;
+    uint8_t              value[1];
+} Iec10x_PrioNode_T;
+
+typedef struct IEC10X_QUEUE
+{
+    struct IEC10X_NODE *Header;
+    struct IEC10X_NODE *Tail;
+    unsigned char       ElementNum;
+} Iec10x_PrioQueue_T;
+
+/*
+*********************************************************************************************************
+*                                           BLOCK SIZE AND NUMBER
+*
+* if add part, please change OS_MAX_MEM_PART in ucosii.h.
+*********************************************************************************************************
+*/
+
+/* IEC10X_PARTITION 1   size==256*8 */
+#define IEC10X_PARTITION_NUM_1  5
+#define IEC10X_PARTITION_SIZE_1 512
+#define IEC10X_PARTITION_1      (IEC10X_PARTITION_SIZE_1 - 16)
+
+/* IEC10X_PARTITION 2   size==(1300+16)*1 */
+#define IEC10X_PARTITION_NUM_2  20
+#define IEC10X_PARTITION_2      128
+#define IEC10X_PARTITION_SIZE_2 (IEC10X_PARTITION_2 + sizeof(Iec10x_PrioNode_T))
+
+/* IEC10X_PARTITION 1   size==64*20 */
+#define IEC10X_PARTITION_NUM_3  10
+#define IEC10X_PARTITION_3      32
+#define IEC10X_PARTITION_SIZE_3 (IEC10X_PARTITION_3 + sizeof(Iec10x_PrioNode_T))
+
+/*
+*********************************************************************************************************
+*                                           ASDU
+*********************************************************************************************************
+*/
+
+/*
+ * ASDU TYPE
+ * */
+#define Iec10x_M_EI_NA_1 0X46
+#define IEC10X_C_IC_NA_1 0X64 /*CALL*/
+#define IEC10X_C_CS_NA_1 103
+#define IEC10X_C_CD_NA_1 106 /*CALL*/
+
+/*Set data*/
+#define IEC10X_C_SE_NA_1 48
+#define IEC10X_C_SE_NC_1 50
+
+/*
+ * ASDU REASON
+ * */
+#define IEC10X_ASDU_REASON_INIT    0X04
+#define IEC10X_ASDU_REASON_ACT     0X06
+#define IEC10X_ASDU_REASON_ACTCON  0X07 /*CALL*/
+#define IEC10X_ASDU_REASON_ACTFIN  0X08 /*CALL FINISH*/
+#define IEC10X_ASDU_REASON_ACTTERM 0X0a /*CALL Terminal*/
+#define IEC10X_ASDU_COT_UNKNOW     45
+
+/*
+ * INFO ADDR
+ * */
+#define IEC10X_INFO_ADDR_NONE 0X00
+
+/*
+*********************************************************************************************************
+*                           REMOTE SIGNAL
+*********************************************************************************************************
+*/
+/*
+ * Asdu type (TI)
+ * */
+#define IEC10X_M_SP_NA_1 0X01
+#define IEC10X_M_DP_NA_1 0X03
+#define IEC10X_M_SP_TB_1 30
+#define IEC10X_M_DP_TB_1 31
+/*
+ * Asdu reason (COT)
+ * */
+#define IEC10X_COT_BACK     2
+#define IEC10X_COT_SPONT    3
+#define IEC10X_COT_ACT      6
+#define IEC10X_COT_ACTCON   7
+#define IEC10X_COT_REQ      5
+#define IEC10X_COT_RETREM   11
+#define IEC10X_COT_RETLOC   12
+#define IEC10X_COT_INTROGEN 20
+#define IEC10X_COT_INTRO1   21
+#define IEC10X_COT_INTRO2   22
+
+/*
+ * Asdu addr
+ * */
+#define IEC10X_INFO_ADDR_SIG_BASE        0X0001
+#define IEC10X_INFO_ADDR_SIG_TEMP_HX_OFF 0x1000
+
+/*
+*********************************************************************************************************
+*                           REMOTE DECTET
+*********************************************************************************************************
+*/
+/*
+ * Asdu type (TI)
+ * */
+#define IEC10X_M_ME_NA_1 9
+#define IEC10X_M_ME_NC_1 13
+#define IEC10X_M_ME_TD_1 34
+#define IEC10X_M_ME_TF_1 36
+
+/*
+ * Asdu reason (COT)
+ * */
+#define IEC10X_COT_PER_CYC  1
+#define IEC10X_COT_BACK     2
+#define IEC10X_COT_SPONT    3
+#define IEC10X_COT_REQ      5
+#define IEC10X_COT_INTROGEN 20
+#define IEC10X_COT_INTRO9   29
+#define IEC10X_COT_INTRO10  30
+
+/*
+ * Asdu addr
+ * */
+#define IEC10X_INFO_ADDR_DET             0X4001
+#define IEC10X_INFO_ADDR_DET_TEMP_HX_OFF 0x1000
+
+/*
+*********************************************************************************************************
+*                           CALL QOI
+*********************************************************************************************************
+*/
+
+#define IEC10X_CALL_QOI_TOTAL   20
+#define IEC10X_CALL_QOI_GROUP1  21
+#define IEC10X_CALL_QOI_GROUP2  22
+#define IEC10X_CALL_QOI_GROUP9  29
+#define IEC10X_CALL_QOI_GROUP10 30
+
+/*
+*********************************************************************************************************
+*                           INFO ADDREST
+*               TD -- temprature device
+*               PD -- pullotion device
+*********************************************************************************************************
+*/
+#define IEC10X_SET_TD_UPCYCLE      0X100001
+#define IEC10X_SET_TD_MAXIMUM      0X100002
+#define IEC10X_SET_TD_MINIMUM      0X100003
+#define IEC10X_SET_TD_DETCYCLE     0X100004
+#define IEC10X_SET_TD_TEMPRISE     0X100005
+#define IEC10X_SET_PD_DETCYCLE     0X100006
+#define IEC10X_SET_PD_PULPSE       0X100007
+#define IEC10X_SET_PD_SELFDETCYCLE 0X100008
+/*
+*********************************************************************************************************
+*                           Fujian Huixing Add
+*********************************************************************************************************
+*/
+/* TI. */
+#define IEC10X_TI_FIRM_UPDATE     128
+#define IEC10X_TI_AP_FIRM_BACKOFF 129
+#define IEC10X_TI_AP_BASE_INFO    130
+/* COT. */
+#define IEC10X_COT_ACT_TERMINAL     8
+#define IEC10X_COT_ACT_TERMINAL_ACK 9
+
+#define IEC10X_COT_DATA         14
+#define IEC10X_COT_DATA_ACK     15
+#define IEC10X_COT_DATA_FIN     16
+#define IEC10X_COT_DATA_FIN_ACK 17
+#define IEC10X_COT_DATA_NEEDACK 0X100E
+
+#pragma pack(1)
+
+/*
+ *  asdu number
+ * */
+typedef struct
+{
+
+    uint8_t _num : 7;
+    uint8_t _sq  : 1;
+
+} ASDU_NUM_T;
+/*
+ *  asdu reason
+ * */
+typedef struct
+{
+#ifdef IEC101_STM32
+    uint8_t _reason : 6;
+    uint8_t _pn     : 1;
+    uint8_t _test   : 1;
+#elif defined(IEC104_STM32)
+    uint16_t _reason : 14;
+    uint16_t _pn     : 1;
+    uint16_t _test   : 1;
+#endif
+
+} ASDU_REASON_T;
+/*
+ *  asdu
+ * */
+typedef struct
+{
+
+    uint8_t       _type;
+    ASDU_NUM_T    _num;
+    ASDU_REASON_T _reason;
+    uint16_t      _addr;
+    uint8_t       _info[1];
+} IEC10X_ASDU_T, *PIEC10X_ASDU_T;
+/*
+ *  asdu info
+ * */
+typedef struct
+{
+
+#ifdef IEC101_STM32
+    uint16_t _addr;
+#elif defined(IEC104_STM32)
+    uint8_t  _addr[3];
+#endif
+    uint8_t _element[1];
+} ASDU_INFO_T, *PASDU_INFO_T;
+
+/*
+ *  asdu info remote signal with time flag
+ * */
+typedef struct
+{
+
+    uint8_t _signal;
+    uint8_t _time;
+} SIGNAL_TIME_T, *PSIGNAL_TIME_T;
+
+/*
+ *  asdu info remote detect with time flag
+ * */
+/*int */
+typedef struct
+{
+
+    int16_t _detect;
+    uint8_t _qds;
+
+} IEC10X_DETECT_T, *PIEC10X_DETECT_T;
+/*float*/
+typedef struct
+{
+
+    float   _detect;
+    uint8_t _qds;
+
+} IEC10X_DETECT_F_T, *PIEC10X_DETECT_F_T;
+
+/*int  sq=0 */
+typedef struct
+{
+
+#ifdef IEC101_STM32
+    uint16_t _addr;
+#elif defined(IEC104_STM32)
+    uint8_t  _addr[3];
+#endif
+    int16_t _detect;
+    uint8_t _qds;
+
+} IEC10X_DETECT_SQ0_T, *PIEC10X_DETECT_SQ0_T;
+/*float sq=0*/
+typedef struct
+{
+
+#ifdef IEC101_STM32
+    uint16_t _addr;
+#elif defined(IEC104_STM32)
+    uint8_t  _addr[3];
+#endif
+    float   _detect;
+    uint8_t _qds;
+
+} IEC10X_DETECT_SQ0_F_T, *PIEC10X_DETECT_SQ0_F_T;
+
+/*
+ *  asdu info CP56Time2a
+ * */
+typedef struct
+{
+
+    uint8_t _minutes : 6;
+    uint8_t _res     : 1;
+    uint8_t _iv      : 1;
+} IEC10X_Time_Min_T, *PIEC10X_Time_Min_T;
+
+typedef struct
+{
+
+    uint8_t _hours : 5;
+    uint8_t _res   : 2;
+    uint8_t _su    : 1;
+} IEC10X_Time_Hour_T, *PIEC10X_Time_Hour_T;
+typedef struct
+{
+
+    uint8_t _dayofmonth : 5;
+    uint8_t _dayofweek  : 3;
+} IEC10X_Time_Day_T, *PIEC10X_Time_Day_T;
+typedef struct
+{
+
+    uint8_t _month : 4;
+    uint8_t _res   : 3;
+} IEC10X_Time_Month_T, *PIEC10X_Time_Month_T;
+typedef struct
+{
+
+    uint8_t _year : 7;
+    uint8_t _res  : 1;
+} IEC10X_Time_Year_T, *PIEC10X_Time_Year_T;
+typedef struct
+{
+
+    uint16_t            _milliseconds;
+    IEC10X_Time_Min_T   _min;
+    IEC10X_Time_Hour_T  _hour;
+    IEC10X_Time_Day_T   _day;
+    IEC10X_Time_Month_T _month;
+    IEC10X_Time_Year_T  _year;
+
+} CP56Time2a_T, *PCP56Time2a_T;
+
+/*
+ *  asdu info remote detect with time flag
+ * */
+typedef struct
+{
+
+    uint16_t     _detect;
+    uint8_t      _qds;
+    CP56Time2a_T _time;
+} DETECT_TIME_T, *PDETECT_TIME_T;
+
+#pragma pack()
+
+/*
+ * Iec10x init
+ */
+typedef struct _iec10x
+{
+
+    char *name;
+    int (*Init)(void);
+    void (*Delay_ms)(uint16_t);
+    void (*CloseLink)(void);
+    void *(*Malloc)(uint8_t NumByte);
+    void (*Free)(void *buffer);
+    uint8_t (*enqueue)(Iec10x_PrioQueue_T *QueueHdr, Iec10x_PrioNode_T *NewNode);
+    Iec10x_PrioNode_T *(*dequeue)(Iec10x_PrioQueue_T *QueueHdr);
+    Iec10x_PrioNode_T *(*FindQHead)(Iec10x_PrioQueue_T *QueueHdr);
+    char (*GetPrio)(void);
+    void (*InitQueue)(Iec10x_PrioQueue_T *PrioQueue);
+    void (*ClearQueue)(Iec10x_PrioQueue_T *QueueHdr);
+    uint8_t (*Send)(int socketfd, char *data, int len);
+    uint32_t (*SetTime)(PCP56Time2a_T time);
+    uint32_t (*GetTime)(PCP56Time2a_T time);
+    int8_t (*GetStationState)(uint16_t Addr, uint8_t DevType);
+    float (*GetStaValue)(uint16_t Addr, uint8_t DevType);
+    uint16_t (*GetLinkAddr)(void);
+    int8_t (*GetInfoNum)(uint8_t *InfoNum, uint8_t DevType);
+    int8_t (*SetConfig)(long Value, uint32_t addr);
+    int8_t (*SaveFirmware)(uint8_t FirmLen, uint8_t *buf, uint32_t FirmwareType, uint32_t Iec10x_Update_SeekAddr);
+    int8_t (*CheckFirmware)(uint32_t FirmwareType, uint32_t TotalLen);
+    int8_t (*UpdateFirmware)(uint32_t FirmwareType);
+    int8_t (*BackoffFirmware)(uint32_t FirmwareType);
+
+#ifdef IEC10XLOCK
+    void (*LOCK)(void);
+    void (*UNLOCK)(void);
+#endif
+
+} * PIEC10X_T, IEC10X_T;
+
+/*
+ * BIG ENDIAN
+ * */
+#ifdef BIG_ENDIAN
+#define n2hs(x) (x)
+#define h2ns(x) (x)
+
+#define n2hl(x) (x)
+#define h2nl(x) (x)
+/* LITTLE ENDIAN */
+#else
+#define n2hs(x) ((((x) >> 8) & 0xFF) | (((x)&0xFF) << 8))
+#define h2ns(x) ((((x) >> 8) & 0xFF) | (((x)&0xFF) << 8))
+
+#define n2hl(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | \
+                 (((x)&0xFF00) << 8) | (((x)&0xFF) << 24))
+#define h2nl(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | \
+                 (((x)&0xFF00) << 8) | (((x)&0xFF) << 24))
+#endif /* BIG_ENDIAN */
+
+/*
+*********************************************************************************************************
+*                                           EXTERN VARIABLE
+*********************************************************************************************************
+*/
+extern PIEC10X_T IEC10X;
+extern uint16_t  Iec10x_Sta_Addr;
+extern int32_t   Iec104_BuildSendSn;
+extern int32_t   Iec104_BuildRecvSn;
+
+extern uint16_t     IEC10X_Cp16time2a;
+extern uint16_t     IEC10X_Cp16time2a_V;
+extern CP56Time2a_T IEC10X_Cp56time2a;
+extern uint8_t      Iec10x_FirmwareUpdateFlag;
+/*
+*********************************************************************************************************
+*                                          QUEUE FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+/*
+ * Prio
+ * */
+uint8_t            IEC10X_PrioEnQueue(Iec10x_PrioQueue_T *QueueHdr, Iec10x_PrioNode_T *new_p);
+Iec10x_PrioNode_T *IEC10X_PrioDeQueue(Iec10x_PrioQueue_T *QueueHdr);
+char               IEC10X_HighestPrio(void);
+void               IEC10X_PrioInitQueue(Iec10x_PrioQueue_T *PrioQueue);
+void               IEC10X_Prio_ClearQueue(Iec10x_PrioQueue_T *QueueHdr);
+Iec10x_PrioNode_T *IEC10X_PrioFindQueueHead(Iec10x_PrioQueue_T *QueueHdr);
+/*
+ * Iec10x queue
+ * */
+void               IEC10X_InitQ(void);
+void               IEC10X_ClearQ(void);
+uint8_t            IEC10X_GetPrio(uint8_t State);
+void               IEC10X_Enqueue(uint8_t *EnQBuf, uint16_t Length, uint8_t Prio,
+                                  void (*IEC10XCallBack)(Iec10x_CallbackArg_T *Arg), Iec10x_CallbackArg_T *CallbackArg);
+void               Iec10x_Scheduled(int socketfd);
+Iec10x_PrioNode_T *IEC10X_Dequeue(void);
+int32_t            RegisterIEC10XMoudle(void *_IEC10X);
+void               IEC10X_ClearQ(void);
+
+void Iec10x_Lock(void);
+void Iec10x_UnLock(void);
+
+#endif /*_IEC10X_H*/

+ 308 - 0
User/app/memory/memory_manager.c

@@ -0,0 +1,308 @@
+#include "memory_manager.h"
+
+/* 内存块大小不能 小于  MemoryMINIMUM_BLOCK_SIZE */
+#define MemoryMINIMUM_BLOCK_SIZE ((size_t)(pMemoryStructSize << 1))
+
+/* 内存使用标记 最高位标志 当最高位置位时表示已使用 */
+/*	pBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * MemoryBITS_PER_BYTE ) - 1 );	pBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * 8 ) - 1 );		*/
+#define MemoryBITS_PER_BYTE ((size_t)8)
+
+#define BYTE_ALIGNMENT      (uint8_t)8UL
+#define BYTE_ALIGNMENT_MASK (uint8_t)(BYTE_ALIGNMENT - 1)
+
+//__align(BYTE_ALIGNMENT) static volatile uint8_t AXISRAM[ AXISRAMSIZE ] __attribute__((at(0x24000000)));
+//__align(BYTE_ALIGNMENT) static volatile uint8_t SDRAMEX[ SDRAMSIZE ] __attribute__((at(0xC0400000)));
+
+MemoryStruct SRAM0 = {
+    .pMemory = (uint8_t *)0x24000000,
+    AXISRAMSIZE,
+    0,
+    0,
+    0,
+    0,
+};
+
+MemoryStruct SRAM1 = {
+    // 可以通过AXI 访问
+    .pMemory = (uint8_t *)0x10000000,
+    SRAM1SIZE,
+    0,
+    0,
+    0,
+    0,
+};
+
+MemoryStruct SRAM2 = {
+    // 可以通过AXI->AHB 访问
+    .pMemory = (uint8_t *)0x30020000,
+    SRAM2SIZE,
+    0,
+    0,
+    0,
+    0,
+};
+
+MemoryStruct SDRAM = {
+    .pMemory = (uint8_t *)0xC0400000,
+    SDRAMSIZE,
+    0,
+    0,
+    0,
+    0,
+};
+
+/*合并内存*/
+static void pInsertBlockIntoFreeList(MemoryStruct *mem, BlockLink_t *pxBlockToInsert);
+/*-----------------------------------------------------------*/
+
+/* 在每个分配的内存的开始处放置的结构的大小块必须通过正确的字节对齐 */
+static const size_t pMemoryStructSize = (sizeof(BlockLink_t) + ((size_t)(BYTE_ALIGNMENT - 1))) & ~((size_t)BYTE_ALIGNMENT_MASK);
+
+/* 内存使用标志 BLOCK 的最高位 | pBlockAllocatedBit 表示已使用 */
+static size_t pBlockAllocatedBit = 0;
+
+/*-----------------------------------------------------------*/
+
+void *pMemoryMalloc(MemoryStruct *mem, size_t xWantedSize)
+{
+    BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
+    void        *pvReturn = NULL;
+
+    // __set_FAULTMASK(1); //  关闭所有中断();
+
+    /* 申请内存大小不能大于 pBlockAllocatedBit */
+    if ((xWantedSize & pBlockAllocatedBit) == 0)
+    {
+        if (xWantedSize > 0)
+        {
+            /* xWantedSize 实际大小 需要加 pMemoryStructSize */
+            xWantedSize += pMemoryStructSize;
+
+            /* 判断 xWantedSize 是否 字节对齐 */
+            if ((xWantedSize & BYTE_ALIGNMENT_MASK) != 0x00)
+            {
+                /* 字节对齐处理 */
+                xWantedSize += (BYTE_ALIGNMENT - (xWantedSize & BYTE_ALIGNMENT_MASK));
+            }
+        }
+
+        /* 申请大小大于零 并且 小于当前剩余量 */
+        if ((xWantedSize > 0) && (xWantedSize <= mem->Free))
+        {
+            /* 寻找足够大小的内存块 */
+            pxPreviousBlock = &mem->pStart;
+            pxBlock         = mem->pStart.pxNextFreeBlock;
+            while ((pxBlock->xBlockSize < xWantedSize) && (pxBlock->pxNextFreeBlock != NULL))
+            {
+                pxPreviousBlock = pxBlock;                  //保存当前 BLOCK
+                pxBlock         = pxBlock->pxNextFreeBlock; //指向下一个 BLOCK
+            }
+
+            /* 是否有满足条件的内存块 */
+            if (pxBlock != mem->pEnd) // 如果 pxBlock = = pEnd[mem]  则找到了最后没找到
+            {
+                /* 内存地址为  pxNextFreeBlock + pMemoryStructSize 为起始 */
+                pvReturn = (void *)(((uint8_t *)pxPreviousBlock->pxNextFreeBlock) + pMemoryStructSize);
+
+                /* 改变当前 BLOCK 的 pxNextFreeBlock 的指向地址 指向下一个 BLOCK 的地址 */
+                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
+
+                /* 如果 pxBlock 剩余内存 大于 最小的 BLOCK 大小 */
+                if ((pxBlock->xBlockSize - xWantedSize) > MemoryMINIMUM_BLOCK_SIZE)
+                {
+                    /* 创建新的 BLOCKLink 地址为 pxBlock + xWantedSize */
+                    pxNewBlockLink = (void *)(((uint8_t *)pxBlock) + xWantedSize);
+
+                    /* 创建新的 BLOCKLink 内存大小为 xBlockSize - 申请值 */
+                    pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
+
+                    /* 当前 BLOCK 的大小 */
+                    pxBlock->xBlockSize = xWantedSize;
+
+                    /* 插入新的LIST 到剩余 内存中 */
+                    pInsertBlockIntoFreeList(mem, pxNewBlockLink);
+                }
+
+                /* 记录当前内存剩余 */
+                mem->Free -= pxBlock->xBlockSize;
+
+                if (mem->Free < mem->MinFree)
+                {
+                    /* 记录历史内存最小剩余 */
+                    mem->MinFree = mem->Free;
+                }
+
+                /* 当前BLock 已使用标志置位 */
+                pxBlock->xBlockSize |= pBlockAllocatedBit;
+                pxBlock->pxNextFreeBlock = NULL;
+            }
+        }
+    }
+
+    // __set_FAULTMASK(0);
+
+    return pvReturn;
+}
+
+/*-----------------------------------------------------------*/
+
+void *pMemoryReMalloc(MemoryStruct *mem1, MemoryStruct *mem2, void *ptr, size_t size)
+{
+    size_t *offset = NULL;
+
+    offset = pMemoryMalloc(mem1, size);
+
+    if (offset == NULL)
+    {
+        return NULL;
+    }
+    else
+    {
+        memcpy(offset, ptr, size);
+
+        pMemoryFree(mem2, ptr);
+    }
+
+    return offset;
+}
+/*-----------------------------------------------------------*/
+
+void pMemoryFree(MemoryStruct *mem, void *pv)
+{
+    uint8_t     *puc = (uint8_t *)pv;
+    BlockLink_t *pxLink;
+
+    if (pv == NULL)
+        return;
+
+    /* 内存BLOCK list 地址为内存地址 - pMemoryStructSize 在申请的时候会 + pMemoryStructSize */
+    puc -= pMemoryStructSize;
+
+    /* 使用  puc 避免编译器报警告 */
+    pxLink = (void *)puc;
+
+    /* 使用  xBlockSize 是否使用 */
+    if ((pxLink->xBlockSize & pBlockAllocatedBit) != 0)
+    {
+        if (pxLink->pxNextFreeBlock == NULL)
+        {
+            /* 去掉使用标志 */
+            pxLink->xBlockSize &= ~pBlockAllocatedBit;
+
+            // __set_FAULTMASK(1); //  关闭所有中断();
+
+            /* 把这个BLOCK 添加到剩余内存中 */
+            mem->Free += pxLink->xBlockSize;
+            pInsertBlockIntoFreeList(mem, ((BlockLink_t *)pxLink));
+
+            // __set_FAULTMASK(0);
+        }
+    }
+}
+/*-----------------------------------------------------------*/
+
+size_t pMemoryGetFreeMemorySize(MemoryStruct *mem)
+{
+    return mem->Free;
+}
+/*-----------------------------------------------------------*/
+
+size_t pMemoryGetMinimumEverFreeMemorySize(MemoryStruct *mem)
+{
+    return mem->MinFree;
+}
+/*-----------------------------------------------------------*/
+
+void pMemoryInit(MemoryStruct *mem)
+{
+    BlockLink_t *pxFirstFreeBlock;
+    uint8_t     *pucAlignedHeap;
+    size_t       uxAddress;
+    size_t       xTotalHeapSize = mem->size;
+
+    memset((void *)mem->pMemory, 0, mem->size);
+
+    /* 内存地址赋值 */
+    uxAddress = (size_t)mem->pMemory;
+
+    /* 判断是否内存对齐 */
+    if ((uxAddress & BYTE_ALIGNMENT_MASK) != 0)
+    {
+        uxAddress += (BYTE_ALIGNMENT - 1);
+        uxAddress &= ~((size_t)BYTE_ALIGNMENT_MASK);
+        xTotalHeapSize -= uxAddress - (size_t)mem->pMemory;
+    }
+
+    pucAlignedHeap = (uint8_t *)uxAddress;
+
+    /* 第一个 BLOCK 初始化 */
+    mem->pStart.pxNextFreeBlock = (void *)pucAlignedHeap;
+    mem->pStart.xBlockSize      = (size_t)0;
+
+    /* 内存结尾赋值 */
+    uxAddress = ((size_t)pucAlignedHeap) + xTotalHeapSize;
+    uxAddress -= pMemoryStructSize;
+    uxAddress &= ~((size_t)BYTE_ALIGNMENT_MASK);
+    mem->pEnd                  = (void *)uxAddress;
+    mem->pEnd->xBlockSize      = 0;
+    mem->pEnd->pxNextFreeBlock = NULL;
+
+    /* 首先,有一个单独的自由块,它的大小可以用来处理整个堆空间,减去pxEnd所占用的空间 */
+    pxFirstFreeBlock                  = (void *)pucAlignedHeap;
+    pxFirstFreeBlock->xBlockSize      = uxAddress - (size_t)pxFirstFreeBlock;
+    pxFirstFreeBlock->pxNextFreeBlock = mem->pEnd;
+
+    /* 内存使用剩余量 */
+    mem->Free    = pxFirstFreeBlock->xBlockSize;
+    mem->MinFree = pxFirstFreeBlock->xBlockSize;
+
+    /* 最高位标志 当最高位置位时表示已使用 */
+    pBlockAllocatedBit = ((size_t)1) << ((sizeof(size_t) * MemoryBITS_PER_BYTE) - 1);
+}
+/*-----------------------------------------------------------*/
+
+static void pInsertBlockIntoFreeList(MemoryStruct *mem, BlockLink_t *pxBlockToInsert)
+{
+    BlockLink_t *pxIterator;
+    uint8_t     *puc;
+
+    /* 寻找插入内存地址 找到当前 插入的 BLOCK 位置 pxIterator 下一个内存地址 >= pxBlockToInsert */
+    for (pxIterator = &mem->pStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock)
+    {
+    }
+
+    /* 判断前一个 BLOCK(pxIterator)  是否 指向的是当前 BLOCK(pxBlockToInsert) 内存块*/
+    puc = (uint8_t *)pxIterator;
+    if ((puc + pxIterator->xBlockSize) == (uint8_t *)pxBlockToInsert)
+    {
+        pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; //合并两个 BLOCK
+        pxBlockToInsert = pxIterator;
+    }
+
+    /* 插入的块,以及它之前插入的块创建一个连续的内存块?*/
+    puc = (uint8_t *)pxBlockToInsert;
+    if ((puc + pxBlockToInsert->xBlockSize) == (uint8_t *)pxIterator->pxNextFreeBlock)
+    {
+        if (pxIterator->pxNextFreeBlock != mem->pEnd)
+        {
+            /* 合并两个内存块 */
+            pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
+            pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
+        }
+        else
+        {
+            pxBlockToInsert->pxNextFreeBlock = mem->pEnd;
+        }
+    }
+    else
+    {
+        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
+    }
+
+    /* 如果插入的块插入一个gab,那么就与block合并在此之前和之后,它的pxNextFreeBlock指针将会有已经设置好了,
+    不应该在这里设置因为这将使它指向本身。 */
+    if (pxIterator != pxBlockToInsert)
+    {
+        pxIterator->pxNextFreeBlock = pxBlockToInsert;
+    }
+}

+ 48 - 0
User/app/memory/memory_manager.h

@@ -0,0 +1,48 @@
+#ifndef _MEMORY_H
+#define _MEMORY_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define AXISRAMSIZE 512 * 1024
+#define SRAM1SIZE   128 * 1024
+#define SRAM2SIZE   128 * 1024
+#define SDRAMSIZE   28 * 1024 * 1024
+
+/* 定义链表结构。这是用来连接自由块的他们的记忆地址 */
+typedef struct A_BLOCK_LINK
+{
+    struct A_BLOCK_LINK *pxNextFreeBlock; /* 列表中的下一个自由块 */
+    size_t               xBlockSize;      /* 自由块的大小 */
+} BlockLink_t;
+
+typedef struct
+{
+    volatile uint8_t *pMemory; /* 创建内存地址 */
+    volatile size_t   size;    /* 创建内存大小 */
+    BlockLink_t       pStart;  /* 创建内存开始 链表标记 */
+    BlockLink_t      *pEnd;    /* 创建内存结束 链表标记 */
+    volatile size_t   Free;    /* 内存当前最小剩余 */
+    volatile size_t   MinFree; /* 内存历史最小剩余 */
+} MemoryStruct;
+
+extern MemoryStruct SRAM0;
+extern MemoryStruct SRAM1;
+extern MemoryStruct SRAM2;
+extern MemoryStruct SDRAM;
+
+/*内存初始化*/
+extern void pMemoryInit(MemoryStruct *mem);
+/*内存申请*/
+extern void *pMemoryMalloc(MemoryStruct *mem, size_t xWantedSize);
+/*内存重申请*/
+extern void *pMemoryReMalloc(MemoryStruct *mem1, MemoryStruct *mem2, void *ptr, size_t size);
+/*内存释放*/
+extern void pMemoryFree(MemoryStruct *mem, void *pv);
+/*内存当前剩余*/
+extern size_t pMemoryGetFreeMemorySize(MemoryStruct *mem);
+/*内存历史最小剩余*/
+extern size_t pMemoryGetMinimumEverFreeMemorySize(MemoryStruct *mem);
+
+#endif

+ 1 - 7
User/app/modbus/modbus.c

@@ -326,12 +326,7 @@ void modbus_slave_task(void)
     {
         OSTimeDly(200);
         iwdg_feed(UART3_DOG);
-        msg         = (UartFrame_TypeDef *)OSMboxPend(uart3_mbox, 50, &err);
-        test_buf[0] = 0x01;
-        test_buf[1] = 0xBB;
-        test_buf[2] = 0xAA;
-        uart3_dma_send(test_buf, 3);
-        printf(test_buf);
+        msg = (UartFrame_TypeDef *)OSMboxPend(uart3_mbox, 50, &err);
         if ((err == OS_ERR_NONE) && (msg->len >= 2))
         {
             if ((msg->buf[0] == 0x00) && (msg->buf[1] == 0xAA) && (msg->buf[2] == 0xBB))
@@ -340,7 +335,6 @@ void modbus_slave_task(void)
                 test_buf[1] = 0xBB;
                 test_buf[2] = 0xAA;
                 uart3_dma_send(test_buf, 3);
-                printf("dsdasdasdds");
             }
         }
     }

+ 31 - 1
User/app/net/net.c

@@ -1,6 +1,8 @@
 #include "net.h"
+#include "iec104.h"
+#include "iec10x.h"
 
-static err_t bms_net_process(int fd, void *data, int len)
+static err_t bms_test_process(int fd, void *data, int len)
 {
     INT8U response[2] = {0xBB, 0xAA};
     if ((len == 2) && (((INT8U *)data)[0] == 0xAA) && (((INT8U *)data)[1] == 0xBB))
@@ -10,14 +12,32 @@ static err_t bms_net_process(int fd, void *data, int len)
     return 1;
 }
 
+static err_t bms_net_process(int fd, void *data, int len)
+{
+
+    Iec10x_Scheduled(fd);
+    Iec104_StateMachine();
+    // INT8U response[2] = {0xBB, 0xAA};
+    // if ((len == 2) && (((INT8U *)data)[0] == 0xAA) && (((INT8U *)data)[1] == 0xBB))
+    // {
+    //     send(fd, (void *)response, sizeof(response), 0);
+    // }
+    return 1;
+}
+
 void net_task(void)
 {
+    int                StaCount = 0;
     INT8U              buf[50];
     INT32S             ret    = 0;
     INT32S             sockfd = -1, newfd = -1;
     INT32U             len = 0;
     struct sockaddr_in svr_addr, clt_addr;
 
+    INT16U Iec104_RecvLen;
+    int    err;
+    int    staid = StaCount++;
+
     svr_addr.sin_family      = AF_INET;
     svr_addr.sin_port        = htons(TCP_PORT);
     svr_addr.sin_addr.s_addr = htons(INADDR_ANY);
@@ -59,6 +79,16 @@ void net_task(void)
                 break;
             }
             bms_net_process(newfd, buf, ret);
+            Iec104_RecvLen = read(newfd, buf, 50);
+            if (Iec104_RecvLen <= 0 || Iec104_RecvLen > 1500)
+            {
+                printf("the other side has been closed (%d).\n", Iec104_RecvLen);
+                continue;
+            }
+            LOG("#####################received \n");
+
+            DumpHEX(buf, Iec104_RecvLen);
+            Iex104_Receive(buf, Iec104_RecvLen);
         }
 
         lwip_close(sockfd);

+ 92 - 133
User/config/lwip/lwip_dm9k.c

@@ -1,15 +1,66 @@
 #include "lwip_dm9k.h"
+#include "dm9k.h"
 #include "ethernetif_dm9k.h"
 #include "lwip/tcpip.h"
+#include "lwip_init.h"
+#include "malloc.h"
+#include "memory_manager.h"
 
-//*******************************************************************************
-struct netif dm9k_netif; // 定义一个网络接口
-/*函数声明*/
-#ifdef USE_DHCP
-static void lwip_dhcp_task(void const *pdata);
-#endif
+struct netif dm9k_netif = {0}; // 定义一个网络接口
 
+#define DM9K_TASK_PRIO     10
+#define DM9K_TASK_STK_SIZE 512
+CPU_STK     dm9k_task_stk[DM9K_TASK_STK_SIZE];
 static void ethernet_link_status_updated(struct netif *netif);
+// lwip 默认IP设置
+void lwip_dm9k_default_ip_set(__lwip_dev *lwipx)
+{
+
+    //默认远端IP为:192.168.1.100
+    lwipx->remoteip[0] = 192;
+    lwipx->remoteip[1] = 168;
+    lwipx->remoteip[2] = 1;
+    lwipx->remoteip[3] = 10;
+
+    // MAC地址设置(高三字节固定为:2.0.0,低三字节用STM32唯一ID)
+    lwipx->mac[0] = 2; //高三字节(IEEE称之为组织唯一ID,OUI)地址固定为:2.0.0
+    lwipx->mac[1] = 0;
+    lwipx->mac[2] = 0;
+    lwipx->mac[3] = 0x90; //低三字节用STM32的唯一ID
+    lwipx->mac[4] = 0x00;
+    lwipx->mac[5] = 0xae;
+
+    //默认本地IP为:192.168.1.30
+    lwipx->ip[0] = 192;
+    lwipx->ip[1] = 168;
+    lwipx->ip[2] = 1;
+    lwipx->ip[3] = 40;
+
+    //默认子网掩码:255.255.255.0
+    lwipx->netmask[0] = 255;
+    lwipx->netmask[1] = 255;
+    lwipx->netmask[2] = 255;
+    lwipx->netmask[3] = 0;
+
+    //默认网关:192.168.1.1
+    lwipx->gateway[0] = 192;
+    lwipx->gateway[1] = 168;
+    lwipx->gateway[2] = 1;
+    lwipx->gateway[3] = 1;
+
+    lwipx->dhcpstatus = 0; //没有DHCP
+}
+
+void ethernet_dm9k_link_thread(void const *argument)
+{
+    struct netif *netif = (struct netif *)(argument);
+
+    for (;;)
+    {
+        ethernet_link_check_state(netif);
+        OSTimeDly(2000);
+    }
+}
 
 // LWIP初始化(LWIP启动的时候使用)
 void lwip_dm9k_init(void)
@@ -18,131 +69,43 @@ void lwip_dm9k_init(void)
     ip4_addr_t netmask;
     ip4_addr_t gw;
 
+    lwip_dm9k_default_ip_set(&dm9kdev); //设置默认IP等信息
+    dm9k_init();
+
 #ifdef USE_DHCP //使用动态IP
     ip_addr_set_zero_ip4(&ipaddr);
     ip_addr_set_zero_ip4(&netmask);
     ip_addr_set_zero_ip4(&gw);
 #else //使用静态IP
-    IP4_ADDR(&ipaddr, DM9K_IP_ADDR0, DM9K_IP_ADDR1, DM9K_IP_ADDR2, DM9K_IP_ADDR3);
-    IP4_ADDR(&netmask, DM9K_NETMASK_ADDR0, DM9K_NETMASK_ADDR1, DM9K_NETMASK_ADDR2, DM9K_NETMASK_ADDR3);
-    IP4_ADDR(&gw, DM9K_GW_ADDR0, DM9K_GW_ADDR1, DM9K_GW_ADDR2, DM9K_GW_ADDR3);
-    printf("\r\n");
-    printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n", DM9K_MAC_ADDR0, DM9K_MAC_ADDR1, DM9K_MAC_ADDR2, DM9K_MAC_ADDR3, DM9K_MAC_ADDR4, DM9K_MAC_ADDR5);
-    printf("静态IP地址........................%d.%d.%d.%d\r\n", DM9K_IP_ADDR0, DM9K_IP_ADDR1, DM9K_IP_ADDR2, DM9K_IP_ADDR3);
-    printf("子网掩码..........................%d.%d.%d.%d\r\n", DM9K_NETMASK_ADDR0, DM9K_NETMASK_ADDR1, DM9K_NETMASK_ADDR2, DM9K_NETMASK_ADDR3);
-    printf("默认网关..........................%d.%d.%d.%d\r\n", DM9K_GW_ADDR0, DM9K_GW_ADDR1, DM9K_GW_ADDR2, DM9K_GW_ADDR3);
+    IP4_ADDR(&ipaddr, dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
+    IP4_ADDR(&netmask, dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
+    IP4_ADDR(&gw, dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);
 #endif
 
     netif_add(&dm9k_netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_dm9k_init, &tcpip_input); //向网卡列表中添加一个网口
     netif_set_default(&dm9k_netif);                                                            //设置netif为默认网口
 
-    ethernet_link_status_updated(&dm9k_netif);
-
+    /* Set the link callback function, this function is called on change of link status*/
 #if LWIP_NETIF_LINK_CALLBACK
     netif_set_link_callback(&dm9k_netif, ethernet_link_status_updated);
 #endif
-    //操作OK.
-}
 
-//如果使能了DHCP
-#ifdef USE_DHCP
-
-// DHCP处理任务
-static osSemaphoreId DHCPSemaphore = NULL; /* Semaphore to signal incoming packets */
-static void          lwip_dhcp_task(void const *argument)
-{
-    struct netif *netif = (struct netif *)argument;
-    struct dhcp  *dhcp;
-    ip_addr_t     ipaddr;
-    ip_addr_t     netmask;
-    ip_addr_t     gw;
-
-    for (;;)
-    {
-        if (osSemaphoreWait(DHCPSemaphore, osWaitForever) == osOK)
-        {
-            if (dm9kdev.dhcpstatus == DHCP_START)
-            {
-                ip_addr_set_zero_ip4(&netif->ip_addr);
-                ip_addr_set_zero_ip4(&netif->netmask);
-                ip_addr_set_zero_ip4(&netif->gw);
-
-                dm9kdev.dhcpstatus = DHCP_WAIT_ADDRESS;
-                dhcp_start(netif); //开启DHCP
-
-                printf("dm9k 开启DHCP服务,请稍等...........\r\n");
-            }
-            else if (dm9kdev.dhcpstatus == DHCP_LINK_DOWN)
-            {
-                dm9kdev.dhcpstatus = DHCP_OFF;
-                //				dhcp_stop(netif);
-                //				dhcp_try_stop(netif);
-
-                printf("dm9k 链接断开\r\n");
-            }
-
-            while (dm9kdev.dhcpstatus == DHCP_WAIT_ADDRESS)
-            {
-                printf("dm9k 正在获取地址...\r\n");
-                if (dhcp_supplied_address(netif)) //当正确读取到IP地址的时候
-                {
-                    dm9kdev.dhcpstatus = DHCP_ADDRESS_ASSIGNED;
-
-                    printf("dm9k 网卡en的MAC地址为:.......%d.%d.%d.%d.%d.%d\r\n", DM9K_MAC_ADDR0, DM9K_MAC_ADDR1, DM9K_MAC_ADDR2, DM9K_MAC_ADDR3, DM9K_MAC_ADDR4, DM9K_MAC_ADDR5);
-                    //解析出通过DHCP获取到的IP地址
-                    dm9kdev.ip[3] = (uint8_t)(netif->ip_addr.addr >> 24);
-                    dm9kdev.ip[2] = (uint8_t)(netif->ip_addr.addr >> 16);
-                    dm9kdev.ip[1] = (uint8_t)(netif->ip_addr.addr >> 8);
-                    dm9kdev.ip[0] = (uint8_t)(netif->ip_addr.addr);
-                    printf("dm9k DHCP获取到IP地址.........%d.%d.%d.%d\r\n", DM9K_IP_ADDR0, DM9K_IP_ADDR1, DM9K_IP_ADDR2, DM9K_IP_ADDR3);
-                    //解析通过DHCP获取到的子网掩码地址
-                    dm9kdev.netmask[3] = (uint8_t)(netif->netmask.addr >> 24);
-                    dm9kdev.netmask[2] = (uint8_t)(netif->netmask.addr >> 16);
-                    dm9kdev.netmask[1] = (uint8_t)(netif->netmask.addr >> 8);
-                    dm9kdev.netmask[0] = (uint8_t)(netif->netmask.addr);
-                    printf("dm9k DHCP获取到子网掩码.......%d.%d.%d.%d\r\n", DM9K_NETMASK_ADDR0, DM9K_NETMASK_ADDR1, DM9K_NETMASK_ADDR2, DM9K_NETMASK_ADDR3);
-                    //解析出通过DHCP获取到的默认网关
-                    dm9kdev.gateway[3] = (uint8_t)(netif->gw.addr >> 24);
-                    dm9kdev.gateway[2] = (uint8_t)(netif->gw.addr >> 16);
-                    dm9kdev.gateway[1] = (uint8_t)(netif->gw.addr >> 8);
-                    dm9kdev.gateway[0] = (uint8_t)(netif->gw.addr);
-                    printf("dm9k DHCP获取到的网关..........%d.%d.%d.%d\r\n", DM9K_GW_ADDR0, DM9K_GW_ADDR1, DM9K_GW_ADDR2, DM9K_GW_ADDR3);
-                }
-                else
-                {
-                    dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
-                    if (dhcp->tries > LWIP_MAX_DHCP_TRIES) //通过DHCP服务获取IP地址失败,且超过最大尝试次数
-                    {
-                        dm9kdev.dhcpstatus = DHCP_TIMEOUT;
-
-                        //使用静态IP地址
-                        netif_set_down(netif);              //先禁用网卡
-                        lwip_dm9k_default_ip_set(&dm9kdev); //设置默认IP等信息
-                        IP4_ADDR(&ipaddr, dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
-                        IP4_ADDR(&netmask, dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
-                        IP4_ADDR(&gw, dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);
-                        //						netif_set_addr(netif, &ipaddr, &netmask, &gw);
-
-                        netif_set_gw(netif, &gw);           //重新设置网关地址
-                        netif_set_netmask(netif, &netmask); //重新设置子网掩码
-                        netif_set_ipaddr(netif, &ipaddr);   //重新设置IP地址
-
-                        printf("dm9k DHCP服务超时,使用静态IP地址!\r\n");
-                        printf("dm9k 网卡en的MAC地址为:........%d.%d.%d.%d.%d.%d\r\n", dm9kdev.mac[0], dm9kdev.mac[1], dm9kdev.mac[2], dm9kdev.mac[3], dm9kdev.mac[4], dm9kdev.mac[5]);
-                        printf("dm9k 静态IP地址................%d.%d.%d.%d\r\n", dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
-                        printf("dm9k 子网掩码..................%d.%d.%d.%d\r\n", dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
-                        printf("dm9k 默认网关..................%d.%d.%d.%d\r\n", dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);
-
-                        netif_set_up(netif); //启用网卡
-                    }
-                }
-
-                OSTimeDly(500);
-            }
-        }
-    }
+    OSTaskCreateExt((void (*)(void *))ethernet_dm9k_link_thread,
+                    (void const *)&dm9k_netif,
+                    (OS_STK *)&dm9k_task_stk[DM9K_TASK_STK_SIZE - 1],
+                    (INT8U)DM9K_TASK_PRIO,
+                    (INT16U)DM9K_TASK_PRIO,
+                    (OS_STK *)&dm9k_task_stk[0],
+                    (INT32U)DM9K_TASK_STK_SIZE,
+                    (void *)0,
+                    (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);
+
+    // if (DM9K_LINK_STATUS == 1)
+    // {
+    //     dm9k_netif.flags |= NETIF_FLAG_LINK_UP;
+    //     netif_set_up(&dm9k_netif);
+    // }
 }
-#endif
 
 /**
  * @brief  This function notify user about link status changement.
@@ -151,42 +114,38 @@ static void          lwip_dhcp_task(void const *argument)
  */
 static void ethernet_link_status_updated(struct netif *netif)
 {
-#ifdef USE_DHCP
+#if LWIP_DHCP
     if (DHCPSemaphore == NULL)
     {
         osSemaphoreDef(ETH_SEM);
         DHCPSemaphore = osSemaphoreCreate(osSemaphore(ETH_SEM), 1);
     }
 #else
-    ip4_addr_t ipaddr;
-    ip4_addr_t netmask;
-    ip4_addr_t gw;
-#endif
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+#endif /* USE_DHCP */
 
     if (netif_is_link_up(netif))
     {
-#ifdef USE_DHCP
+#if LWIP_DHCP
         /* Update DHCP state machine */
         dm9kdev.dhcpstatus = DHCP_START;
         osSemaphoreRelease(DHCPSemaphore);
 #else
-        IP4_ADDR(&ipaddr, DM9K_IP_ADDR0, DM9K_IP_ADDR1, DM9K_IP_ADDR2, DM9K_IP_ADDR3);
-        IP4_ADDR(&netmask, DM9K_NETMASK_ADDR0, DM9K_NETMASK_ADDR1, DM9K_NETMASK_ADDR2, DM9K_NETMASK_ADDR3);
-        IP4_ADDR(&gw, DM9K_GW_ADDR0, DM9K_GW_ADDR1, DM9K_GW_ADDR2, DM9K_GW_ADDR3);
-        printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n", DM9K_MAC_ADDR0, DM9K_MAC_ADDR1, DM9K_MAC_ADDR2, DM9K_MAC_ADDR3, DM9K_MAC_ADDR4, DM9K_MAC_ADDR5);
-        printf("静态IP地址........................%d.%d.%d.%d\r\n", DM9K_IP_ADDR0, DM9K_IP_ADDR1, DM9K_IP_ADDR2, DM9K_IP_ADDR3);
-        printf("子网掩码..........................%d.%d.%d.%d\r\n", DM9K_NETMASK_ADDR0, DM9K_NETMASK_ADDR1, DM9K_NETMASK_ADDR2, DM9K_NETMASK_ADDR3);
-        printf("默认网关..........................%d.%d.%d.%d\r\n", DM9K_GW_ADDR0, DM9K_GW_ADDR1, DM9K_GW_ADDR2, DM9K_GW_ADDR3);
-        netif_set_addr(netif, &ipaddr, &netmask, &gw);
+        IP4_ADDR(&ipaddr, dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
+        IP4_ADDR(&netmask, dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
+        IP4_ADDR(&gw, dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);
 
-#endif
+        dm9kdev.dhcpstatus = DHCP_ADDRESS_ASSIGNED; //标记网络开启成功。
+#endif /* USE_DHCP */
     }
     else
     {
-#ifdef USE_DHCP
+#if LWIP_DHCP
         /* Update DHCP state machine */
         osSemaphoreRelease(DHCPSemaphore);
 #endif /* USE_DHCP */
-        // dm9kdev.dhcpstatus = DHCP_LINK_DOWN;
+        dm9kdev.dhcpstatus = DHCP_LINK_DOWN;
     }
 }

+ 1 - 33
User/config/lwip/lwip_dm9k.h

@@ -1,39 +1,7 @@
 #ifndef _LWIP_DM9K_H
 #define _LWIP_DM9K_H
 
-//////////////////////////////////////////////////////////////////////////////////
-
-/* 定义网卡的 MAC 地址 */
-#define DM9K_MAC_ADDR0 2
-#define DM9K_MAC_ADDR1 0
-#define DM9K_MAC_ADDR2 0
-#define DM9K_MAC_ADDR3 0
-#define DM9K_MAC_ADDR4 0
-#define DM9K_MAC_ADDR5 0
-
-/* static IP address: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
-#define DM9K_IP_ADDR0 192
-#define DM9K_IP_ADDR1 168
-#define DM9K_IP_ADDR2 1
-#define DM9K_IP_ADDR3 150
-
-/* remote IP address: IP_S_ADDR0.IP_S_ADDR1.IP_S_ADDR2.IP_S_ADDR3 */
-#define DM9K_IP_S_ADDR0 192
-#define DM9K_IP_S_ADDR1 168
-#define DM9K_IP_S_ADDR2 1
-#define DM9K_IP_S_ADDR3 10
-
-/* net mask */
-#define DM9K_NETMASK_ADDR0 255
-#define DM9K_NETMASK_ADDR1 255
-#define DM9K_NETMASK_ADDR2 255
-#define DM9K_NETMASK_ADDR3 0
-
-/* gateway address */
-#define DM9K_GW_ADDR0 192
-#define DM9K_GW_ADDR1 168
-#define DM9K_GW_ADDR2 1
-#define DM9K_GW_ADDR3 1
+#include "fly_config.h"
 
 void lwip_dm9k_init(void);
 

+ 55 - 22
User/config/lwip/lwip_eth.c

@@ -5,19 +5,12 @@
 #include "lwip/memp.h"
 #include "lwip/netif.h"
 #include "lwip/tcpip.h"
-#include "main.h"
+#include "lwip_init.h"
+#include "stm32f4x7_phy.h"
 #include <stdio.h>
 
 #define MAX_DHCP_TRIES 4
 
-typedef enum
-{
-    DHCP_START = 0,
-    DHCP_WAIT_ADDRESS,
-    DHCP_ADDRESS_ASSIGNED,
-    DHCP_TIMEOUT
-} dhcp_state_enum;
-
 #ifdef USE_DHCP
 dhcp_state_enum dhcp_state = DHCP_START;
 ip4_addr_t      ip_address = {0};
@@ -25,6 +18,45 @@ ip4_addr_t      ip_address = {0};
 
 struct netif gnetif;
 
+// lwip 默认IP设置
+void lwip_eth_default_ip_set(__lwip_dev *lwipx)
+{
+
+    //默认远端IP为:192.168.1.100
+    lwipx->remoteip[0] = 192;
+    lwipx->remoteip[1] = 168;
+    lwipx->remoteip[2] = 1;
+    lwipx->remoteip[3] = 10;
+
+    // MAC地址设置(高三字节固定为:2.0.0,低三字节用STM32唯一ID)
+    lwipx->mac[0] = 2; //高三字节(IEEE称之为组织唯一ID,OUI)地址固定为:2.0.0
+    lwipx->mac[1] = 0;
+    lwipx->mac[2] = 0;
+    lwipx->mac[3] = 0; //低三字节用STM32的唯一ID
+    lwipx->mac[4] = 0;
+    lwipx->mac[5] = 0;
+
+    //默认本地IP为:192.168.1.30
+    lwipx->ip[0] = 192;
+    lwipx->ip[1] = 168;
+    lwipx->ip[2] = 1;
+    lwipx->ip[3] = 40;
+
+    //默认子网掩码:255.255.255.0
+    lwipx->netmask[0] = 255;
+    lwipx->netmask[1] = 255;
+    lwipx->netmask[2] = 255;
+    lwipx->netmask[3] = 0;
+
+    //默认网关:192.168.1.1
+    lwipx->gateway[0] = 192;
+    lwipx->gateway[1] = 168;
+    lwipx->gateway[2] = 1;
+    lwipx->gateway[3] = 1;
+
+    lwipx->dhcpstatus = 0; //没有DHCP
+}
+
 /*!
     \brief      initializes the LwIP stack
     \param[in]  none
@@ -37,15 +69,17 @@ void lwip_eth_setup(void)
     ip4_addr_t netmask;
     ip4_addr_t gw;
 
+    lwip_eth_default_ip_set(&ethdev); //设置默认IP等信息
+    eth_init();
     /* IP address setting */
 #ifdef USE_DHCP
     ipaddr.addr  = 0;
     netmask.addr = 0;
     gw.addr      = 0;
 #else
-    IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
-    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
-    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+    IP4_ADDR(&ipaddr, ethdev.ip[0], ethdev.ip[1], ethdev.ip[2], ethdev.ip[3]);
+    IP4_ADDR(&netmask, ethdev.netmask[0], ethdev.netmask[1], ethdev.netmask[2], ethdev.netmask[3]);
+    IP4_ADDR(&gw, ethdev.gateway[0], ethdev.gateway[1], ethdev.gateway[2], ethdev.gateway[3]);
 
 #endif /* USE_DHCP */
 
@@ -81,7 +115,6 @@ void lwip_eth_setup(void)
     {
         netif_set_down(&gnetif);
     }
-    // netif_set_link_callback(&gnetif, ETH_link_callback);
 }
 
 #ifdef USE_DHCP
@@ -98,27 +131,27 @@ void dhcp_task(void *pvParameters)
     ip4_addr_t   gw;
     struct dhcp *dhcp_client;
 
-    dhcp_client = netif_dhcp_data(&xnetif);
+    dhcp_client = netif_dhcp_data(&gnetif);
 
     for (;;)
     {
         switch (dhcp_state)
         {
         case DHCP_START:
-            dhcp_start(&xnetif);
+            dhcp_start(&gnetif);
             ip_address.addr = 0;
             dhcp_state      = DHCP_WAIT_ADDRESS;
             break;
 
         case DHCP_WAIT_ADDRESS:
             /* read the new IP address */
-            ip_address.addr = xnetif.ip_addr.u_addr.ip4.addr;
+            ip_address.addr = gnetif.ip_addr.u_addr.ip4.addr;
 
             if (ip_address.addr != 0)
             {
                 dhcp_state = DHCP_ADDRESS_ASSIGNED;
                 /* stop DHCP */
-                dhcp_stop(&xnetif);
+                dhcp_stop(&gnetif);
 
                 printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address),
                        ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
@@ -131,13 +164,13 @@ void dhcp_task(void *pvParameters)
                 {
                     dhcp_state = DHCP_TIMEOUT;
                     /* stop DHCP */
-                    dhcp_stop(&xnetif);
+                    dhcp_stop(&gnetif);
 
                     /* static address used */
-                    IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
-                    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
-                    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
-                    netif_set_addr(&xnetif, &ipaddr, &netmask, &gw);
+                    IP4_ADDR(&ipaddr, ethdev.ip[0], ethdev.ip[1], ethdev.ip[2], ethdev.ip[3]);
+                    IP4_ADDR(&netmask, ethdev.netmask[0], ethdev.netmask[1], ethdev.netmask[2], ethdev.netmask[3]);
+                    IP4_ADDR(&gw, ethdev.gateway[0], ethdev.gateway[1], ethdev.gateway[2], ethdev.gateway[3]);
+                    netif_set_addr(&gnetif, &ipaddr, &netmask, &gw);
                     OSTaskSuspend(OS_PRIO_SELF);
                 }
             }

+ 3 - 33
User/config/lwip/lwip_eth.h

@@ -1,43 +1,12 @@
 #ifndef LWIP_ETH_H
 #define LWIP_ETH_H
 
-#include "main.h"
+// #include "fly_config.h"
 
 //#define USE_DHCP       1 /* enable DHCP, if disabled static address is used */
+// extern __lwip_dev ethdev; // lwip控制结构体
 
 #define USE_ETH_INTERRUPT
-//#define TIMEOUT_CHECK_USE_LWIP
-/* MAC address: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
-#define MAC_ADDR0 2
-#define MAC_ADDR1 0
-#define MAC_ADDR2 0
-#define MAC_ADDR3 0
-#define MAC_ADDR4 0
-#define MAC_ADDR5 0
-
-/* static IP address: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
-#define IP_ADDR0 192
-#define IP_ADDR1 168
-#define IP_ADDR2 1
-#define IP_ADDR3 40
-
-/* remote IP address: IP_S_ADDR0.IP_S_ADDR1.IP_S_ADDR2.IP_S_ADDR3 */
-#define IP_S_ADDR0 192
-#define IP_S_ADDR1 168
-#define IP_S_ADDR2 1
-#define IP_S_ADDR3 10
-
-/* net mask */
-#define NETMASK_ADDR0 255
-#define NETMASK_ADDR1 255
-#define NETMASK_ADDR2 255
-#define NETMASK_ADDR3 0
-
-/* gateway address */
-#define GW_ADDR0 192
-#define GW_ADDR1 168
-#define GW_ADDR2 1
-#define GW_ADDR3 1
 
 /* MII and RMII mode selection */
 #define RMII_MODE // user have to provide the 50 MHz clock by soldering a 50 MHz oscillator
@@ -51,6 +20,7 @@
 #ifdef USE_DHCP
 /* dhcp_task */
 void dhcp_task(void *pvParameters);
+#include "dhcp.h"
 #endif /* USE_DHCP */
 
 void lwip_eth_setup(void);

+ 3 - 0
User/config/lwip/lwip_init.c

@@ -2,6 +2,9 @@
 #include "lwip_dm9k.h"
 #include "lwip_eth.h"
 
+__lwip_dev ethdev  = {0}; // lwip控制结构体
+__lwip_dev dm9kdev = {0}; // lwip控制结构体
+
 // LWIP初始化(LWIP启动的时候使用)
 void lwip_setup(void)
 {

+ 30 - 12
User/config/lwip/lwip_init.h

@@ -12,20 +12,38 @@
 #include "lwip/prot/dhcp.h"
 #endif
 
-#include "dm9k.h"
-#include "ethernetif_dm9k.h"
-#include "ethernetif_eth.h"
-#include "stm32f4x7_phy.h"
-
 #define LWIP_MAX_DHCP_TRIES 4 // DHCP服务器最大重试次数
 
-#define DHCP_OFF              (uint8_t)0
-#define DHCP_START            (uint8_t)1
-#define DHCP_WAIT_ADDRESS     (uint8_t)2
-#define DHCP_ADDRESS_ASSIGNED (uint8_t)3
-#define DHCP_TIMEOUT          (uint8_t)4
-#define DHCP_LINK_DOWN        (uint8_t)5
-#define DHCP_LINK_FAIL        (uint8_t)0xff
+// #define DHCP_OFF              (uint8_t)0
+// #define DHCP_START            (uint8_t)1
+// #define DHCP_WAIT_ADDRESS     (uint8_t)2
+// #define DHCP_ADDRESS_ASSIGNED (uint8_t)3
+// #define DHCP_TIMEOUT          (uint8_t)4
+// #define DHCP_LINK_DOWN        (uint8_t)5
+// #define DHCP_LINK_FAIL        (uint8_t)0xff
+
+typedef enum
+{
+    DHCP_START = 0,
+    DHCP_WAIT_ADDRESS,
+    DHCP_ADDRESS_ASSIGNED,
+    DHCP_TIMEOUT,
+    DHCP_LINK_DOWN,
+    DHCP_LINK_FAIL
+} dhcp_state_enum;
+
+typedef struct
+{
+    uint8_t mac[6];      // MAC地址
+    uint8_t remoteip[4]; //远端主机IP地址
+    uint8_t ip[4];       //本机IP地址
+    uint8_t netmask[4];  //子网掩码
+    uint8_t gateway[4];  //默认网关的IP地址
+    uint8_t dhcpstatus;  // dhcp状态
+} __lwip_dev;
+
+extern __lwip_dev ethdev;  // lwip控制结构体
+extern __lwip_dev dm9kdev; // lwip控制结构体
 
 void lwip_setup(void);
 

+ 8 - 8
User/config/lwip/lwipopts.h

@@ -50,9 +50,11 @@
 
 #define MEMP_NUM_NETBUF 8 /* the number of struct netbufs */
 
-/* Pbuf options */
-#define PBUF_POOL_SIZE    20  /* the number of buffers in the pbuf pool */
-#define PBUF_POOL_BUFSIZE 512 /* the size of each pbuf in the pbuf pool */
+/* ---------- pbuf选项 ---------- */
+#define MEMP_NUM_PBUF            15   /* MEMP_NUM_PBUF:memp结构的pbuf数量,如果应用从ROM或者静态存储区发送大量数据时,这个值应该设置大一点 */
+#define PBUF_POOL_SIZE           15   /* PBUF_POOL_SIZE:pbuf内存池个数 */
+#define PBUF_POOL_BUFSIZE        1528 /* PBUF_POOL_BUFSIZE:每个pbuf内存池大小 */
+#define LWIP_SUPPORT_CUSTOM_PBUF 1
 
 /* TCP options */
 #define LWIP_TCP 1
@@ -85,7 +87,7 @@
 #define LWIP_ICMP 1
 
 /* DHCP options */
-#define LWIP_DHCP 1 /* define to 1 if you want DHCP configuration of interfaces, \
+#define LWIP_DHCP 0 /* define to 1 if you want DHCP configuration of interfaces, \
                        DHCP is not implemented in lwIP 0.5.1, however, so        \
                        turning this on does currently not work. */
 
@@ -101,8 +103,8 @@
 #define LWIP_PROVIDE_ERRNO 1
 
 /* checksum options */
-//#define CHECKSUM_BY_HARDWARE                             /* computing and verifying the IP, UDP, TCP and ICMP
-//                                                            checksums by hardware */
+#define CHECKSUM_BY_HARDWARE   /* computing and verifying the IP, UDP, TCP and ICMP \
+                                 checksums by hardware */
 
 /* netconn options */
 #define LWIP_NETCONN 1 /* set to 1 to enable netconn API (require to use api_lib.c) */
@@ -118,8 +120,6 @@
 /* Lwip debug options */
 #define LWIP_DEBUG 0
 
-#define CHECKSUM_BY_HARDWARE
-
 #ifdef CHECKSUM_BY_HARDWARE
 /* CHECKSUM_GEN_IP==0: generate checksums by hardware for outgoing IP packets.*/
 #define CHECKSUM_GEN_IP 0

+ 158 - 45
User/config/lwip/port/ethernetif_dm9k.c

@@ -3,48 +3,73 @@
 #include "dm9k.h"
 #include "lwip/tcpip.h"
 #include "lwip/timeouts.h"
+#include "lwip_dm9k.h"
+#include "memory_manager.h"
 #include "netif/etharp.h"
 #include "netif/ethernet.h"
+// #include "snmp.h"
+#include "lwip_init.h"
 #include "string.h"
 
-#define DM9K_RX_TASK_PRIO     (4)
-#define DM9K_RX_TASK_STK_SIZE (2048)
+#define DM9K_RX_TASK_PRIO     4
+#define DM9K_RX_TASK_STK_SIZE 2048
 CPU_STK dm9k_rx_task_stk[DM9K_RX_TASK_STK_SIZE];
 
 /* Define those to better describe your network interface. */
-#define IFNAME0 's'
-#define IFNAME1 't'
+#define IFNAME0 'D'
+#define IFNAME1 '2'
 
-#define DM9K_RX_DESC_CNT 3
-#define DM9K_RX_Lenth    1536UL * 2
+#define DM9K_RX_DESC_CNT 4
+#define DM9K_RX_Lenth    1536UL
 
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
 static uint8_t            *Rx_Buff[DM9K_RX_DESC_CNT]     = {0}; /* Ethernet Rx Buffer */
-static uint8_t             current_pbuf_idx              = 0;   /* Zero-copy RX PBUF pool */
+uint8_t                    current_pbuf_idx              = 0;   /* Zero-copy RX PBUF pool */
 static struct pbuf_custom *custom_pbuf[DM9K_RX_DESC_CNT] = {0};
 /* Private function prototypes -----------------------------------------------*/
 static void pbuf_free_custom(struct pbuf *p);
 static void ethernetif_input(void *pvParameters);
-static void ethernet_link_check_state(struct netif *netif);
+// static void ethernet_link_check_state(struct netif *netif);
 
 static OS_EVENT     *g_dm9k_rx_sem = NULL;
+static OS_EVENT     *dm9k_mutex    = NULL;
 static struct netif *low_netif     = NULL;
+/*
+*********************************************************************************************************
+*	函 数 名: VariableMemInit
+*	功能说明: 申请串口相关的变量内存
+*	形    参: 无
+*	返 回 值: 无
+*********************************************************************************************************
+*/
+static void VariableMemInit(void)
+{
+    uint16_t idx = 0;
 
+    for (idx = 0; idx < DM9K_RX_DESC_CNT; idx++)
+    {
+        if (Rx_Buff[idx] == 0)
+            Rx_Buff[idx] = pMemoryMalloc(&SRAM0, DM9K_RX_Lenth); // 因为不释放,避免重复申请
+        if (custom_pbuf[idx] == 0)
+            custom_pbuf[idx] = pMemoryMalloc(&SRAM0, sizeof(struct pbuf_custom)); // 因为不释放,避免重复申请
+    }
+}
 static void low_level_init(struct netif *netif)
 {
-    // VariableMemInit();
-
+    INT32U idx = 0;
+    VariableMemInit();
+    INT8U err;
     /* set MAC hardware address length */
     netif->hwaddr_len = ETHARP_HWADDR_LEN;
 
     /* set MAC hardware address */ /* 网卡的 MAC 修改2 */
-    netif->hwaddr[0] = DM9K_MAC_ADDR0;
-    netif->hwaddr[1] = DM9K_MAC_ADDR1;
-    netif->hwaddr[2] = DM9K_MAC_ADDR2;
-    netif->hwaddr[3] = DM9K_MAC_ADDR3;
-    netif->hwaddr[4] = DM9K_MAC_ADDR4;
-    netif->hwaddr[5] = DM9K_MAC_ADDR5;
+    netif->hwaddr[0] = dm9kdev.mac[0];
+    netif->hwaddr[1] = dm9kdev.mac[1];
+    netif->hwaddr[2] = dm9kdev.mac[2];
+    netif->hwaddr[3] = dm9kdev.mac[3];
+    netif->hwaddr[4] = dm9kdev.mac[4];
+    netif->hwaddr[5] = dm9kdev.mac[5];
 
     /* maximum transfer unit */
     netif->mtu = 1500;
@@ -53,6 +78,18 @@ static void low_level_init(struct netif *netif)
     /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
     netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
 
+    low_netif = netif;
+
+    for (idx = 0; idx < DM9K_RX_DESC_CNT; idx++)
+    {
+        custom_pbuf[idx]->custom_free_function = pbuf_free_custom;
+    }
+
+    if (NULL == dm9k_mutex)
+    {
+        dm9k_mutex = OSMutexCreate(1, &err);
+    }
+
     /* create binary semaphore used for informing ethernetif of frame reception */
     if (NULL == g_dm9k_rx_sem)
     {
@@ -68,8 +105,7 @@ static void low_level_init(struct netif *netif)
                     (INT32U)DM9K_RX_TASK_STK_SIZE,
                     (void *)0,
                     (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);
-
-    ethernet_link_check_state(netif);
+    // ethernet_link_check_state(netif);
 }
 
 /**
@@ -89,10 +125,17 @@ static void low_level_init(struct netif *netif)
  */
 static err_t low_level_output(struct netif *netif, struct pbuf *p)
 {
+
+    INT8U        err;
     err_t        errval = ERR_OK;
     uint32_t     i = 0, framelen = 0, calc_len = 0;
     struct pbuf *q;
 
+    SYS_ARCH_DECL_PROTECT(sr);
+
+    OSMutexPend(dm9k_mutex, 1000, &err);
+    SYS_ARCH_PROTECT(sr);
+
     dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 dm9kA 中断 */
 
     NET_REG_ADDR = DM9K_REG_MWCMD;
@@ -117,6 +160,9 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
         ;                                      /* 等待发送完成	 */
     dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 dm9kA 中断 */
 
+    SYS_ARCH_UNPROTECT(sr);
+
+    OSMutexPost(dm9k_mutex);
     return errval;
 }
 
@@ -125,10 +171,14 @@ static struct pbuf *low_level_input(struct netif *netif)
     struct pbuf *p        = NULL;
     uint32_t     framelen = 0;
 
+    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 DM9000A 中断 */
     framelen = etherdev_read(Rx_Buff[current_pbuf_idx]);
+    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 DM9000A 中断 */
     if (framelen)
     {
-        // p = pbuf_alloced_custom(PBUF_RAW, framelen, PBUF_REF, custom_pbuf[current_pbuf_idx], Rx_Buff[current_pbuf_idx], Max_Ethernet_Lenth);
+
+        // p = pbuf_alloc(PBUF_RAW, framelen, PBUF_POOL);
+        p = pbuf_alloced_custom(PBUF_RAW, framelen, PBUF_REF, custom_pbuf[current_pbuf_idx], Rx_Buff[current_pbuf_idx], Max_Ethernet_Lenth);
         if (current_pbuf_idx < (DM9K_RX_DESC_CNT - 1))
         {
             current_pbuf_idx++;
@@ -138,10 +188,10 @@ static struct pbuf *low_level_input(struct netif *netif)
             current_pbuf_idx = 0;
         }
     }
-
     return p;
 }
 
+#if 1
 void ethernetif_input(void *pvParameters)
 {
     struct pbuf *p;
@@ -152,7 +202,7 @@ void ethernetif_input(void *pvParameters)
     for (;;)
     {
 
-        OSSemPend(g_dm9k_rx_sem, 0, &err);
+        OSSemPend(g_dm9k_rx_sem, 100, &err);
 
 TRY_GET_NEXT_FRAME:
         SYS_ARCH_PROTECT(sr);
@@ -172,14 +222,50 @@ TRY_GET_NEXT_FRAME:
         }
     }
 }
+#else
+void ethernetif_input(void *argument)
+{
+    struct pbuf *p;
+    // struct netif *netif = (struct netif *)argument;
+    INT8U err;
+    for (;;)
+    {
+        OSSemPend(g_dm9k_rx_sem, 0, &err);
+        // if (err == OS)
+        // {
+        if (err == ERR_OK)
+        {
+            do
+            {
+                LOCK_TCPIP_CORE();
+
+                p = low_level_input(low_netif);
+                if (p != NULL)
+                {
+                    err = low_netif->input(p, low_netif);
+                    if (err != ERR_OK)
+                    {
+                        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+                        pbuf_free(p);
+                    }
+                }
+
+                UNLOCK_TCPIP_CORE();
+
+            } while (p != NULL);
+        }
 
+        // }
+    }
+}
+#endif
 err_t ethernetif_dm9k_init(struct netif *netif)
 {
     LWIP_ASSERT("netif != NULL", (netif != NULL));
 
 #if LWIP_NETIF_HOSTNAME
     /* Initialize interface hostname */
-    netif->hostname = "lwip";
+    netif->hostname = "DM9000";
 #endif /* LWIP_NETIF_HOSTNAME */
 
     /*
@@ -187,7 +273,7 @@ err_t ethernetif_dm9k_init(struct netif *netif)
      * The last argument should be replaced with your link speed, in units
      * of bits per second.
      */
-
+    // MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
     netif->name[0] = IFNAME0;
     netif->name[1] = IFNAME1;
 
@@ -216,15 +302,24 @@ static void pbuf_free_custom(struct pbuf *p)
         memset(p, 0, sizeof(struct pbuf));
     }
 }
-
-void EXTI15_10_IRQHandler(void)
+void dm9k_interrupt(void)
 {
+    uint8_t  save_reg;
+    uint16_t isr_status;
 
-    if (EXTI_GetITStatus(EXTI_Line14) != RESET)
-    {
-        BSP_GPIO15_EXTI_Callback();
-        EXTI_ClearITPendingBit(EXTI_Line14); /* 清除中断标志位 */
+    save_reg = NET_REG_ADDR; /* 暂存所使用的位置 */
+
+    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 DM9KA 中断 */
+    isr_status = dm9k_ReadReg(DM9K_REG_ISR);   /* 取得中断产生值 */
+    // isr_status = isr_status & DM9K_RX_INTR;
+    if (isr_status & DM9K_RX_INTR)
+    { /* 检查是否为接收中断 */
+        OSSemPost(g_dm9k_rx_sem);
+        // dm9k_receive_packet();							/* 执行接收处理程序 */
     }
+
+    dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 DM9KA 中断 */
+    NET_REG_ADDR = save_reg;                   /* 回复所使用的位置 */
 }
 
 /**
@@ -241,6 +336,7 @@ void BSP_GPIO15_EXTI_Callback(void)
 
     isr_status = dm9k_ReadReg(DM9K_REG_ISR); /* 取得中断产生值 */
     dm9k_WriteReg(DM9K_REG_ISR, isr_status); /* 清除中断产生值 */
+    // isr_status = isr_status & DM9K_RX_INTR;
 
     if (isr_status & DM9K_RX_INTR) /* 检查是否为接收中断 */
     {
@@ -250,11 +346,39 @@ void BSP_GPIO15_EXTI_Callback(void)
     NET_REG_ADDR = save_reg; /* 回复所使用的位置 */
 }
 
-/**
- * @brief  Check the ETH link state and update netif accordingly.
- * @param  argument: netif
- * @retval None
- */
+//中断处理函数,注意不是中断服函数,需要在中断服务函数中调用
+void DMA9K_ISRHandler(void)
+{
+    u16 int_status;
+    u16 last_io;
+    last_io    = NET_REG_ADDR;
+    int_status = dm9k_ReadReg(DM9K_REG_ISR);
+    dm9k_WriteReg(DM9K_REG_ISR, int_status); //清除中断标志位
+
+    if (int_status & DM9K_RX_INTR) //接收中断
+    {
+        OSSemPost(g_dm9k_rx_sem);
+        //接收完成中断,用户自己添加代码
+    }
+    if (int_status & DM9K_TX_INTR) //发送中断
+    {
+        // OSSemPost(g_dm9k_tx_sem);
+        //发送完成中断,用户自己添加代码
+    }
+    NET_REG_ADDR = last_io;
+}
+
+void EXTI15_10_IRQHandler(void)
+{
+    OSIntEnter();
+    EXTI_ClearITPendingBit(EXTI_Line15); /* 清除中断标志位 */
+    if (EXTI_GetITStatus(EXTI_Line15) != RESET)
+    {
+        BSP_GPIO15_EXTI_Callback();
+    }
+    OSIntExit();
+}
+
 void ethernet_link_check_state(struct netif *netif)
 {
     uint8_t linkchanged = 0;
@@ -272,14 +396,3 @@ void ethernet_link_check_state(struct netif *netif)
         netif_set_link_up(netif);
     }
 }
-
-void ethernet_dm9k_link_thread(void const *argument)
-{
-    struct netif *netif = (struct netif *)argument;
-
-    for (;;)
-    {
-        ethernet_link_check_state(netif);
-        OSTimeDly(100);
-    }
-}

+ 1 - 1
User/config/lwip/port/ethernetif_dm9k.h

@@ -5,6 +5,6 @@
 #include "lwip/netif.h"
 
 err_t ethernetif_dm9k_init(struct netif *netif);
-void  ethernet_dm9k_link_thread(void const *argument);
+void  ethernet_link_check_state(struct netif *netif);
 void  BSP_GPIO15_EXTI_Callback(void);
 #endif

+ 8 - 7
User/config/lwip/port/ethernetif_eth.c

@@ -44,6 +44,7 @@
 #include "lwip/opt.h"
 #include "lwip/pbuf.h"
 #include "lwip/timeouts.h"
+#include "lwip_init.h"
 #include "main.h"
 #include "netif/etharp.h"
 #include "stm32f4x7_eth.h"
@@ -92,13 +93,13 @@ static void low_level_init(struct netif *netif)
     /* set MAC hardware address length */
     netif->hwaddr_len = ETHARP_HWADDR_LEN;
 
-    /* set MAC hardware address */
-    netif->hwaddr[0] = MAC_ADDR0;
-    netif->hwaddr[1] = MAC_ADDR1;
-    netif->hwaddr[2] = MAC_ADDR2;
-    netif->hwaddr[3] = MAC_ADDR3;
-    netif->hwaddr[4] = MAC_ADDR4;
-    netif->hwaddr[5] = MAC_ADDR5;
+    /* set MAC hardware address */ /* 网卡的 MAC 修改2 */
+    netif->hwaddr[0] = ethdev.mac[0];
+    netif->hwaddr[1] = ethdev.mac[1];
+    netif->hwaddr[2] = ethdev.mac[2];
+    netif->hwaddr[3] = ethdev.mac[3];
+    netif->hwaddr[4] = ethdev.mac[4];
+    netif->hwaddr[5] = ethdev.mac[5];
 
     /* initialize MAC address in ethernet MAC */
     ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);

+ 0 - 1
User/config/lwip/port/ethernetif_eth.h

@@ -5,6 +5,5 @@
 #include "lwip/netif.h"
 
 err_t ethernetif_eth_init(struct netif *netif);
-// err_t ethernetif_input(struct netif *netif);
 
 #endif

+ 19 - 1
User/main.c

@@ -9,6 +9,24 @@
 
 #include "main.h"
 
+void DumpHEX(uint8_t *buffer, uint32_t len)
+{
+
+    uint32_t i;
+    printf("[DumpHEX]Length:%d ", len);
+    for (i = 0; i < len; i++)
+    {
+        if (i % 16 == 0)
+            printf("\r\n");
+        else if (i % 8 == 0)
+            printf("    ");
+        else
+            printf(":");
+        printf("%02x", buffer[i]);
+    }
+    printf("\r\n");
+}
+
 int main(void)
 {
 #if 0
@@ -51,7 +69,7 @@ int main(void)
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
     OSInit();
     bsp_init();
-
+    Stm32f103RegisterIec10x();
     /* init task */
     /* 创建一个启动任务(也就是主任务)。启动任务会创建所有的应用程序任务 */
     OSTaskCreateExt(init_task,                                   /* 启动任务函数指针 */

+ 2 - 0
User/main.h

@@ -14,4 +14,6 @@
 void bsp_init(void);
 void init_task(void *pvParameters);
 void misc_task(void);
+
+uint32_t Stm32f103RegisterIec10x(void);
 #endif

+ 31 - 0
User/project_var.h

@@ -1,5 +1,6 @@
 #ifndef __PROJECT_VAR_H
 #define __PROJECT_VAR_H
+#include "includes.h"
 
 typedef unsigned long long INT64U;
 typedef signed long long   INT64S;
@@ -14,4 +15,34 @@ typedef signed long long   INT64S;
 #define SW_VERSION1    0
 #define SW_VERSION2    2
 
+#define WTP_SUPPORT_END_NUMBER 9
+
+#define RET_SUCESS 0
+#define RET_ERROR  1
+
+//#define IEC101_STM32
+#define IEC104_STM32
+//#define IEC104_STM32_FUJIAN_HX
+
+//#define SIM900_MODE_SERVER
+#define SIM900_MODE_CLIENT
+
+#define SERIAL_DEBUG
+
+#ifdef SERIAL_DEBUG
+#define log(...) printf(__VA_ARGS__)
+#define LOG(...) printf(__VA_ARGS__)
+#define LogInit()
+#define PRINT_FUNLINE printf("%s %d\r\n", __FUNCTION__, __LINE__)
+#else
+#define log(...)
+#define LOG(...)
+#define DumpHEX(buffer, len)
+#define PRINT_FUNLINE
+#endif
+
+#ifdef SERIAL_DEBUG
+void DumpHEX(INT8U *buffer, INT32U len);
+#endif
+
 #endif

+ 4 - 0
platformio.ini

@@ -26,8 +26,10 @@ build_flags =
   -IUser/bsp/timer
   -IUser/bsp/uart 
   -IUser/app
+  -IUser/app/iec104
   -IUser/app/queue
   -IUser/app/led
+  -IUser/app/memory
   -IUser/app/modbus
   -IUser/app/net
   -IUser/config/lwip
@@ -57,10 +59,12 @@ build_flags =
   -Wno-unused-variable
   -Wno-pointer-sign
   -Wno-unused-but-set-variable
+  -O0
 
 build_unflags = 
   -DSTM32F407xx
   -DSTM32F4
+  -Os
 
 src_filter = +<User/> 
             +<Project/GCC/>