gaochunhui 1 rok pred
commit
424382cc68
100 zmenil súbory, kde vykonal 39796 pridanie a 0 odobranie
  1. 654 0
      App/masterslave.c
  2. 277 0
      App/masterslave.h
  3. 858 0
      App/ota_update.c
  4. 244 0
      App/ota_update.h
  5. 653 0
      App/public.c
  6. 138 0
      App/public.h
  7. 205 0
      App/taskOpt.c
  8. 33 0
      App/taskOpt.h
  9. 0 0
      App/upto485.c
  10. 0 0
      App/upto485.h
  11. 1256 0
      App/xspDataOpt.c
  12. 196 0
      App/xspDataOpt.h
  13. 369 0
      App/xspOptFlash.c
  14. 36 0
      App/xspOptFlash.h
  15. 1638 0
      CMSIS/core_cm3.h
  16. 637 0
      CMSIS/core_cmFunc.h
  17. 687 0
      CMSIS/core_cmInstr.h
  18. 380 0
      CMSIS/gd32f10x.h
  19. 1059 0
      CMSIS/system_gd32f10x.c
  20. 60 0
      CMSIS/system_gd32f10x.h
  21. BIN
      HEAD.zip
  22. 158 0
      Hardware/I2C.c
  23. 60 0
      Hardware/I2C.h
  24. 267 0
      Hardware/Timer.c
  25. 31 0
      Hardware/Timer.h
  26. 237 0
      Hardware/Uart.c
  27. 32 0
      Hardware/Uart.h
  28. 497 0
      Hardware/boardinit.c
  29. 153 0
      Hardware/boardinit.h
  30. 156 0
      Hardware/epprom.c
  31. 20 0
      Hardware/epprom.h
  32. 84 0
      Hardware/fifo.c
  33. 27 0
      Hardware/fifo.h
  34. 205 0
      Hardware/flash.c
  35. 25 0
      Hardware/flash.h
  36. 96 0
      Hardware/key.c
  37. 27 0
      Hardware/key.h
  38. 67 0
      Hardware/rtc.c
  39. 8 0
      Hardware/rtc.h
  40. 53 0
      Hardware/timeout.c
  41. 19 0
      Hardware/timeout.h
  42. 367 0
      Library/Include/gd32f10x_adc.h
  43. 229 0
      Library/Include/gd32f10x_bkp.h
  44. 759 0
      Library/Include/gd32f10x_can.h
  45. 80 0
      Library/Include/gd32f10x_crc.h
  46. 249 0
      Library/Include/gd32f10x_dac.h
  47. 152 0
      Library/Include/gd32f10x_dbg.h
  48. 289 0
      Library/Include/gd32f10x_dma.h
  49. 1497 0
      Library/Include/gd32f10x_enet.h
  50. 431 0
      Library/Include/gd32f10x_exmc.h
  51. 258 0
      Library/Include/gd32f10x_exti.h
  52. 370 0
      Library/Include/gd32f10x_fmc.h
  53. 107 0
      Library/Include/gd32f10x_fwdgt.h
  54. 498 0
      Library/Include/gd32f10x_gpio.h
  55. 347 0
      Library/Include/gd32f10x_i2c.h
  56. 94 0
      Library/Include/gd32f10x_misc.h
  57. 128 0
      Library/Include/gd32f10x_pmu.h
  58. 923 0
      Library/Include/gd32f10x_rcu.h
  59. 151 0
      Library/Include/gd32f10x_rtc.h
  60. 433 0
      Library/Include/gd32f10x_sdio.h
  61. 327 0
      Library/Include/gd32f10x_spi.h
  62. 728 0
      Library/Include/gd32f10x_timer.h
  63. 377 0
      Library/Include/gd32f10x_usart.h
  64. 89 0
      Library/Include/gd32f10x_wwdgt.h
  65. 932 0
      Library/Source/gd32f10x_adc.c
  66. 295 0
      Library/Source/gd32f10x_bkp.c
  67. 1054 0
      Library/Source/gd32f10x_can.c
  68. 130 0
      Library/Source/gd32f10x_crc.c
  69. 558 0
      Library/Source/gd32f10x_dac.c
  70. 152 0
      Library/Source/gd32f10x_dbg.c
  71. 737 0
      Library/Source/gd32f10x_dma.c
  72. 3084 0
      Library/Source/gd32f10x_enet.c
  73. 645 0
      Library/Source/gd32f10x_exmc.c
  74. 251 0
      Library/Source/gd32f10x_exti.c
  75. 964 0
      Library/Source/gd32f10x_fmc.c
  76. 154 0
      Library/Source/gd32f10x_fwdgt.c
  77. 538 0
      Library/Source/gd32f10x_gpio.c
  78. 714 0
      Library/Source/gd32f10x_i2c.c
  79. 187 0
      Library/Source/gd32f10x_misc.c
  80. 282 0
      Library/Source/gd32f10x_pmu.c
  81. 1195 0
      Library/Source/gd32f10x_rcu.c
  82. 276 0
      Library/Source/gd32f10x_rtc.c
  83. 807 0
      Library/Source/gd32f10x_sdio.c
  84. 717 0
      Library/Source/gd32f10x_spi.c
  85. 2002 0
      Library/Source/gd32f10x_timer.c
  86. 766 0
      Library/Source/gd32f10x_usart.c
  87. 133 0
      Library/Source/gd32f10x_wwdgt.c
  88. 642 0
      Project/XspBoardPro.uvprojx
  89. 390 0
      Startup/ARM/startup_gd32f10x_cl.s
  90. 371 0
      Startup/ARM/startup_gd32f10x_hd.s
  91. 328 0
      Startup/ARM/startup_gd32f10x_md.s
  92. 371 0
      Startup/ARM/startup_gd32f10x_xd.s
  93. 155 0
      User/gd32f10x_it.c
  94. 111 0
      User/gd32f10x_it.h
  95. 64 0
      User/gd32f10x_libopt.h
  96. 83 0
      User/main.c
  97. 44 0
      User/main.h
  98. 39 0
      User/readme.txt
  99. 87 0
      User/systick.c
  100. 53 0
      User/systick.h

+ 654 - 0
App/masterslave.c

@@ -0,0 +1,654 @@
+#include "masterslave.h"
+#include "ota_update.h"
+#include "taskOpt.h"
+
+uint32_t _msgid = 0;
+
+void slave_send_data_to_uart(uint8_t type1, uint16_t type2,uint8_t *data,uint8_t len)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = type1;
+    msg->msgType2 = type2;
+
+    memcpy(msg->comInfo.info,data,len);
+    sendlen =  COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.info[len] = crc &0xff;
+    msg->comInfo.info[len+1] = (crc>>8) &0xff;
+
+    data_dump("send to 485:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+
+
+
+static void slave_get_status_0x1002(uint8_t *buf,uint8_t *len,uint16_t devtypeM,uint32_t devSnM,uint8_t bself)
+{
+    status0x2002 *msg = (status0x2002*)buf;
+
+
+    if(bself == SLAVE_OFFLINE){
+        msg->devTypeM = g_devMsg.devType;
+        msg->devSnM   = g_devMsg.devSn;
+        msg->devTypeS = devtypeM;
+        msg->devSnS   = devSnM;
+        msg->identity = IDENTITY_SLAVE;
+
+        msg->identity = g_iDentity;
+        if(IDENTITY_MASTER == g_iDentity){
+            memcpy(msg->cfgFileNo,g_table1027.confFileNum,8);
+            msg->bHave4G  = g_devMsg.bHave4G;
+        }
+        else{
+            memset(msg->cfgFileNo,0,8);
+            msg->bHave4G  = 0;
+        }
+        msg->status = 0;
+    }
+    else {
+        msg->devTypeM = devtypeM;
+        msg->devSnM   = devSnM;
+        msg->devTypeS = g_devMsg.devType;
+        msg->devSnS   = g_devMsg.devSn;
+        memcpy(msg->cfgFileNo,g_table1027.confFileNum,8);
+        msg->identity = g_iDentity;
+        msg->bHave4G  = g_devMsg.bHave4G;
+        msg->status = 1;
+        msg->lastResetType = g_devResetMsg.resetflag;
+        msg->resetNum = g_devResetMsg.resetNum;
+        msg->runTime  = Get_SysTick()/1000;
+        msg->voltage = 0x00;
+        msg->temperature = 0x00;
+        msg->rssi4G  =  0 + 1000;
+        msg->snr4G   = 0x00;
+        msg->tempStamp = g_taskRunDa.timetamp;
+        msg->reserve = 0x00;
+    }
+
+    *len = sizeof(status0x2002);
+
+    return;
+}
+static void slave_get_status_0x1001(uint8_t *buf,uint8_t *len,uint16_t devtypeM,uint32_t devSnM)
+{
+    status0x2001 *msg = (status0x2001*)buf;
+
+    msg->devTypeM = devtypeM;
+    msg->devSnM   = devSnM;
+
+    msg->devTypeS = g_devMsg.devType;
+    msg->devSnS   = g_devMsg.devSn;
+
+    msg->upCode   = 0;
+    msg->bootVer  = g_devAppVer.bootVer;
+    msg->ptVer    = g_devAppVer.ptVer;
+    msg->appVer   = g_devAppVer.app1Ver;
+    memcpy(msg->uuid,g_devfirmMsg.uuid,12);
+    memset(msg->imei,0,15);
+    memset(msg->iccid,0,20);
+    msg->reserve = 0x00;
+
+
+    *len = sizeof(status0x2001);
+
+    return;
+}
+void slave_get_update_0x1001(uint8_t *outdata, uint8_t *len,uint16_t taskId)
+{
+    update0x2001 *msg = (update0x2001*)outdata;
+
+    msg->devType = g_devMsg.devType;
+    msg->devSn = g_devMsg.devSn;
+    msg->appVer = 0x1001234;
+    msg->taskId = taskId;
+    msg->reserve = 0x00;
+
+    *len = sizeof(update0x2001);
+    return;
+}
+
+
+void slave_send_status_comm(uint16_t cmd,uint8_t *data,uint8_t len)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = 0x02;
+    msg->msgType2 = cmd;
+
+    memcpy(msg->comInfo.info,data,len);
+    sendlen =  COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.info[len] = crc &0xff;
+    msg->comInfo.info[len+1] = (crc>>8) &0xff;
+
+    data_dump("send:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+
+void slave_send_data_0x2061(uint16_t devType, uint32_t devSn,uint8_t *data, uint8_t len,uint8_t bnew)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = 0x03;
+    msg->msgType2 = 0x2061;
+
+    msg->comInfo.da2061.devTypeM = devType;
+    msg->comInfo.da2061.devSnM  = devSn;
+    msg->comInfo.da2061.devTypeS = g_devMsg.devType;
+    msg->comInfo.da2061.devSnS = g_devMsg.devSn;
+    msg->comInfo.da2061.bnewflag = bnew;
+    msg->comInfo.da2061.palen = len;
+
+    memcpy(msg->comInfo.da2061.info,data,len);
+    sendlen = DATA_2061_LEN + COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.da2061.info[len] = crc &0xff;
+    msg->comInfo.da2061.info[len+1] = (crc>>8) &0xff;
+
+    data_dump("send:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+
+void slave_send_log_0x2062(uint16_t devType, uint32_t devSn,uint8_t *data, uint8_t len)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = 0x10;
+    msg->msgType2 = 0x2062;
+
+    msg->comInfo.lg2062.devTypeM = devType;
+    msg->comInfo.lg2062.devSnM  = devSn;
+    msg->comInfo.lg2062.devTypeS = g_devMsg.devType;
+    msg->comInfo.lg2062.devSnS = g_devMsg.devSn;
+    msg->comInfo.lg2062.palen = len;
+
+    memcpy(msg->comInfo.lg2062.info,data,len);
+    sendlen = LOG_2062_LEN + COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.lg2062.info[len] = crc &0xff;
+    msg->comInfo.lg2062.info[len+1] = (crc>>8) &0xff;
+
+   // data_dump_00("send:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+
+void slave_send_log_0x2063(uint16_t devType, uint32_t devSn,uint8_t logtype,uint8_t *data, uint8_t len)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = 0x10;
+    msg->msgType2 = 0x2063;
+
+    msg->comInfo.lg2063.devTypeM = devType;
+    msg->comInfo.lg2063.devSnM  = devSn;
+    msg->comInfo.lg2063.devTypeS = g_devMsg.devType;
+    msg->comInfo.lg2063.devSnS = g_devMsg.devSn;
+    msg->comInfo.lg2063.logtype = logtype;
+    msg->comInfo.lg2063.reserve = 0x00;
+    msg->comInfo.lg2063.palen = len;
+
+    memcpy(msg->comInfo.lg2063.info,data,len);
+    sendlen = LOG_2063_LEN + COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.lg2063.info[len] = crc &0xff;
+    msg->comInfo.lg2063.info[len+1] = (crc>>8) &0xff;
+
+   // data_dump_00("send:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+void slave_send_data_0x2030(uint16_t devType, uint32_t devSn,uint8_t *data,uint8_t *cfigNo, uint8_t len)
+{
+    MasterSlave *msg = NULL;
+    uint16_t crc ;
+    uint8_t sendlen;
+
+    msg = (MasterSlave*)usart485TX_Buffer;
+    memset(usart485TX_Buffer,0,sizeof(usart485TX_Buffer));
+
+    msg->start = 0xFEFE;
+    msg->msgId = _msgid++;
+    msg->proVer = 2;
+    msg->msgType1 = 0x01;
+    msg->msgType2 = 0x2030;
+
+    msg->comInfo.sysMsg.devTypeM = devType;
+    msg->comInfo.sysMsg.devSnM  = devSn;
+    msg->comInfo.sysMsg.devTypeS = g_devMsg.devType;
+    msg->comInfo.sysMsg.devSnS = g_devMsg.devSn;
+    memcpy(msg->comInfo.sysMsg.sDa.s0x2030.configfileNo,cfigNo,8);// = bnew;
+    msg->comInfo.sysMsg.sDa.s0x2030.reserve = 0;
+
+    memcpy(msg->comInfo.info+SYSTEM_2030_LEN,data,len); // 24为2030的头
+    sendlen = SYSTEM_2030_LEN + COMM_HEAD_LEN + len;
+    msg->palen  = sendlen + 2 - COMM_HEAD_LEN;
+
+
+    crc = _crc16_get(usart485TX_Buffer,sendlen);
+    msg->comInfo.info[len+SYSTEM_2030_LEN] = crc &0xff;
+    msg->comInfo.info[len+1+SYSTEM_2030_LEN] = (crc>>8) &0xff;
+
+    data_dump("send:",usart485TX_Buffer,sendlen+2);
+    usart_tx_dma_send(USART1,usart485TX_Buffer,sendlen+2);
+}
+/*------------------------------------------- 主解析从的指令 并存储到4G 的发送fifo中---------------*/
+
+
+
+/*-----------------------------------------------------------------------------
+ *  从设备读取flash 中的交易记录 放入到485的发送fifo中
+ *  flag : 1:主设备读取的,2:服务器读取的
+ * ----------------------------------------------------------------------------*/
+void slave_read_flash_data_to485(uint16_t devType, uint32_t devSn)
+{
+    uint8_t ret;
+    XspDataInfo xspda;
+
+    ret = read_flash(xspda.data,1);
+    if(ret==1){ // 有新的交易记录
+        printf("发送数据到服务器:recordId=%d,amount=%d,oil=%d,tamout=%lld,toil=%lld\r\n",\
+               xspda.reDa.recordId,xspda.reDa.amount,xspda.reDa.oil,\
+               xspda.reDa.tamount,xspda.reDa.toil);
+        // 组成数据
+        if((0xFFFFFFFF == xspda.reDa.recordId) && (xspda.reDa.price==0xFFFFFFFF)) {// 错误数据不上传
+            slave_send_data_0x2061(devType, devSn,xspda.data,0,0);
+        }
+        else
+            slave_send_data_0x2061(devType,devSn,xspda.data,64,1);
+    }
+    else { // 无新的交易记录
+        slave_send_data_0x2061(devType, devSn,xspda.data,0,0);
+    }
+}
+uint8_t master_check_dev_table(uint16_t devType, uint32_t devSn)
+{
+    volatile uint8_t i = 0;
+    uint8_t flag;
+    flag = 0;
+    g_runNode.slaveNum = (g_runNode.slaveNum>NODE_MAX_SIZE ? NODE_MAX_SIZE:g_runNode.slaveNum);
+    for(i=0;i<g_runNode.slaveNum;i++){
+        if((devType== g_runNode.nodMsg[i].devType) \
+           && (devSn == g_runNode.nodMsg[i].devSn)) {
+            flag = 1;
+            break;
+        }
+    }
+    if(flag == 1){
+        g_runNode.nodMsg[i].readCount = 0;
+        g_runNode.nodMsg[i].status = 1;
+        return i;
+    }
+    else
+        return 0xFF;
+}
+
+void slave_system_cmd_0x1026(uint8_t *data)
+{
+    systemCmd *msg = (systemCmd*)(data);
+    if((msg->sDa.s0x1026.appointDevModel == g_devMsg.devType)) {
+        if((0xFFFFFFFF == msg->devSnS) ||(msg->devSnS == g_devMsg.devSn) ){ //
+
+//            exti_interrupt_flag_clear(g_extimsg.extiLine); /* 清除中断 */
+//            exti_interrupt_disable(g_extimsg.extiLine);
+            epprom_init_com_config();
+            epprom_write_com_config((uint8_t*)(&msg->sDa.s0x1026.priceInuseCout),sizeof(system0x1026)-6);
+            epprom_read_com_config();
+            exti_gpio_init();
+//            exti_interrupt_enable(g_extimsg.extiLine);
+            power_up_read_comm_min_time();
+        }
+    }
+}
+
+
+void anlaysis_0x1027(uint8_t *data,uint8_t framNo,uint16_t time)
+{
+    static uint8_t groupId;
+    uint8_t flag = 0,i=0;
+    sysCmd1027 *msg = (sysCmd1027*)data;
+
+    if(0xFF == framNo){ // 单帧
+        groupId = 0;
+        memcpy((uint8_t*)&g_table1027,data,sizeof(sysCmd1027));
+        g_table1027.groupNum = msg->groupNum;
+        flag = 1;
+    }
+    else if((framNo&0x80) == 0x80){ // 多帧的第一帧
+        groupId = 0;
+        memcpy((uint8_t*)&g_temtable1027,data,sizeof(sysCmd1027));
+        groupId = msg->groupNum;
+
+    }
+    else if((framNo%0x0F) != 0x01) { // 多帧的中间帧
+        memcpy(g_temtable1027.table[groupId],msg->table,sizeof(sysCmd1027)-11);
+        groupId += msg->groupNum;
+    }
+    else if((framNo&0x01) == 0x01) { // 多帧的最后一帧
+        memcpy(g_temtable1027.table[groupId],msg->table,sizeof(sysCmd1027)-11);
+        groupId += msg->groupNum;
+        g_temtable1027.groupNum = groupId;
+        flag = 1;
+        memcpy(&g_table1027,&g_temtable1027,sizeof(sysCmd1027));// 将临时表中的数据放入到用到的表中
+    }
+
+    if( (1 == flag) ){
+        if((0==time)){
+            epprom_write_pin_config((uint8_t*)&g_table1027,(uint16_t)sizeof(sysCmd1027)); // 写入EEPROm中
+            g_taskRunDa.bcfgfiletime = 0;
+        }
+        else {
+            timeout_setValue(&g_taskRunDa.cfigFileTime,time*1000);
+            timeout_start(&g_taskRunDa.cfigFileTime);
+            g_taskRunDa.bcfgfiletime = 1;
+        }
+        for(i=0;i<g_table1027.groupNum;i++){
+            if(i%10 == 0) printf("\r\n");
+            printf("{%d,%2d},",g_table1027.table[i][0],g_table1027.table[i][1]);
+
+        }
+    }
+}
+void slave_system_cmd_0x1027(uint8_t *data)
+{
+    systemCmd *msg = (systemCmd*)data;
+
+    if(msg->sDa.s0x1027.da1027.appointDevModel != g_devMsg.devType) return; // 不是本设备的设备类型
+
+    if((0xFFFFFFFF != msg->devSnS) && (msg->devSnS != g_devMsg.devSn)) return;
+
+    if((0xFF ==msg->sDa.s0x1027.framNo) ||(0x80 == (msg->sDa.s0x1027.framNo&0x80)) ){
+        if(0 == msg->sDa.s0x1027.expireTime) epprom_init_pin_config();
+    }
+    anlaysis_0x1027((uint8_t*)&msg->sDa.s0x1027.da1027,msg->sDa.s0x1027.framNo,msg->sDa.s0x1027.expireTime);
+}
+
+void slave_system_cmd_0x1028(uint8_t *data)
+{
+    systemCmd *msg = (systemCmd*)data;
+    uint8_t flag = 0; // 1: 主 2: 从 3: 主从
+    if(0xFFFF == msg->devTypeS) flag = 3;
+    else if(0xFFFFFFFF == msg->devSnS) flag = 3;
+    else if(msg->devSnS == g_devMsg.devSn) flag = 1;
+    else flag = 2;
+    if((3==flag) ||(1==flag)){
+
+        g_up7segData.bOpen = 1;
+        if(0xFFFFFFFF == msg->sDa.s0x1028.time) {
+            timeout_setValue(&g_up7segData.upTime,4000);
+            g_up7segData.bofflineTest = 1;
+        }
+        else{
+            timeout_setValue(&g_up7segData.upTime,msg->sDa.s0x1028.time*1000);
+            g_up7segData.bofflineTest = 0;
+        }
+        timeout_start(&g_up7segData.upTime);
+    }
+}
+
+void slave_system_cmd_0x1029(uint8_t *data)
+{
+    systemCmd *msg = (systemCmd*)data;
+    uint8_t flag = 0; // 1: 主 2: 从 3: 主从
+    if(0xFFFF == msg->devTypeS) flag = 3;
+    else if(0xFFFFFFFF == msg->devSnS) flag = 3;
+    else if(msg->devSnS == g_devMsg.devSn) flag = 1;
+    else flag = 2;
+    g_up7segData.bofflineTest = 0;
+    if((3==flag) ||(1==flag)){
+        g_up7segData.bOpen = 0;
+        timeout_stop(&g_up7segData.upTime);
+        if(msg->sDa.s0x1029.status == 1){ // 1保存
+            epprom_write_pin_config((uint8_t*)&g_table1027,(uint16_t)sizeof(sysCmd1027));
+        }
+        else if(msg->sDa.s0x1029.status == 2){ //2放弃不存储,要读取回原来的数据
+            epprom_read_pin_config();
+        }
+    }
+
+}
+
+/*----------------------------------------------------------------------------------
+ *   解析系统类 0x01
+ * ---------------------------------------------------------------------------------*/
+void analysis_cmd_system(uint16_t cmd, uint8_t *data,uint8_t len)
+{
+    MasterSlave * pmsg = (MasterSlave*)data;
+    commInfo_t *msg = &(pmsg->comInfo);
+
+    if(0x1000 == (cmd&0x1000)) {
+        if(0x1015 == cmd ){
+            printf("收到时间同步指令\r\n");
+            set_time(msg->sysMsg.sDa.s0x1015.timer);
+            g_taskRunDa.timetamp = msg->sysMsg.sDa.s0x1015.timer;
+            return;
+        }
+        if(0==check_dev_type_sn01(msg->sysMsg.devTypeS,msg->sysMsg.devSnS)) return;
+        data_dump("收到数据",data,len);
+        switch(cmd){
+        case 0x1021: // 系统重启
+            if(0x02 == msg->sysMsg.sDa.s0x1021.object)NVIC_SystemReset();
+            break;
+        case 0x1015: // 时间同步
+            printf("收到时间同步指令\r\n");
+            set_time(msg->sysMsg.sDa.s0x1015.timer);
+            break;
+        case 0x1026: // com配置文件
+            slave_system_cmd_0x1026((uint8_t *)msg);
+            break;
+        case 0x1027: // 探针脚配置表
+            slave_system_cmd_0x1027((uint8_t*)msg);
+            break;
+        case 0x1028: // 开启8段码上报
+            slave_system_cmd_0x1028((uint8_t*)msg);
+            break;
+        case 0x1029: // 关闭8段码上报
+            slave_system_cmd_0x1029((uint8_t*)msg);
+            break;
+        case 0x1030:
+            slave_send_data_0x2030(msg->sysMsg.devTypeM,msg->sysMsg.devSnM,&g_7egDa[1],&g_table1027.confFileNum[0],28);
+            break;
+        }
+    }
+}
+/*----------------------------------------------------------------------------------
+ *   解析状态类 0x02
+ * ---------------------------------------------------------------------------------*/
+void analysis_cmd_status(uint16_t cmd, uint8_t *data,uint8_t len)
+{
+    uint8_t sendbuff[128], sendlen;
+    MasterSlave *msg = (MasterSlave*)data;
+
+    if(0x1000 == (cmd&0x1000)) { // 从设备处理
+        if(0==check_dev_type_sn(msg->comInfo.statusMsg.devTypeS,msg->comInfo.statusMsg.devSnS)) return;
+        data_dump("收到数据",data,len);
+        memset(sendbuff,0,128);
+        switch(cmd){
+        case 0x1002: // 实时状态
+            slave_get_status_0x1002(sendbuff,&sendlen,msg->comInfo.statusMsg.devTypeM,msg->comInfo.statusMsg.devSnM,SELF_STATUS);
+            slave_send_status_comm(0x2002,sendbuff,sendlen);
+            break;
+        case 0x1001: // 固件信息
+            slave_get_status_0x1001(sendbuff,&sendlen,msg->comInfo.statusMsg.devTypeM,msg->comInfo.statusMsg.devSnM);
+            slave_send_status_comm(0x2001,sendbuff,sendlen);
+            break;
+        }
+    }
+}
+
+/*----------------------------------------------------------------------------------
+ *   解析数据类 0x03
+ * ---------------------------------------------------------------------------------*/
+void analysis_cmd_data(uint16_t cmd,uint8_t *data,uint8_t len)
+{
+    MasterSlave *msg = (MasterSlave*)data;
+//    uint16_t sIndex = 0xFF;
+    uint8_t ret;
+    switch (cmd) {
+    case 0x1061:
+        if(0==check_dev_type_sn(msg->comInfo.da1061.devTypeS,msg->comInfo.da1061.devSnS)) break;
+        data_dump("收到数据",data,len);
+        if(0 == msg->comInfo.da1061.recordId) {
+            if(g_xspErrDa.bsend ==2 ){
+                slave_send_log_0x2062(msg->comInfo.da1061.devTypeM,msg->comInfo.da1061.devSnM,g_xspErrDa.segDa,16);
+                g_xspErrDa.bsend = 1;
+                //printf("~~~~~~~~~~~~~~~~~~~~~~~~发送错误数据\r\n");
+            }
+            else slave_read_flash_data_to485(msg->comInfo.da1061.devTypeM,msg->comInfo.da1061.devSnM);
+        }
+        else if(0xFFFFFFFF == msg->comInfo.da1061.recordId){ // 主设备按键读取
+//            save_display_data_to_flash();
+//            slave_read_flash_data_to485(msg->comInfo.da1061.devTypeM,msg->comInfo.da1061.devSnM);
+        }
+        else { // 服务器读取
+            ret = xsp_check_point_record(msg->comInfo.da1061.recordId,g_xspReDa.data);
+            if(1 == ret ){ // 说明已经找到的记录
+                slave_send_data_0x2061(msg->comInfo.da1061.devTypeM,msg->comInfo.da1061.devSnM,g_xspReDa.data,64,2);
+            }
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+/*----------------------------------------------------------------------------------
+ *   解析升级类 0x04
+ * ---------------------------------------------------------------------------------*/
+void analysis_cmd_update(uint16_t cmd,uint8_t *data,uint8_t len)
+{
+    uint8_t sendbuff[128], sendlen;
+    MasterSlave *msg = (MasterSlave*)data;
+
+    if(0x2000 == (cmd&0x2000)){
+        if((g_devMsg.workMode==WORK_UPDATE && g_updateDa.iDentity==IDENTITY_SLAVE)||0x01 ==g_updateDa.bResetUpdate) return;//被升级时,不处理
+        data_dump("收到数据",data,len);
+        switch(cmd){
+
+        case 0x2007: //  收到从设备上报的升级状态
+            set_start_ota_timer(&g_otaTimer.upstatusTmr,10*1000);
+            master_update_status_rcv(msg->comInfo.info,msg->palen-2);
+            printf("收到从设备上报的升级状态\r\n");
+            break;
+        case 0x2005: // 收到从设备的重传指令
+            ota_update_master_retransmit(msg->comInfo.info);
+            break;
+        }
+    }
+    else if(0x1000 == (cmd&0x1000)) { // 从设备处理
+
+        memset(sendbuff,0,128);
+        switch(cmd){
+        case 0x1001: // 获取设备版本
+            if(0==check_dev_type_sn(msg->comInfo.upMsg.up0x1001.devType,msg->comInfo.upMsg.up0x1001.devSn)) return;
+            data_dump("收到数据",data,len);
+            slave_get_update_0x1001(sendbuff,&sendlen,msg->comInfo.upMsg.up0x1001.taskId);
+            slave_send_data_to_uart(0x04,0x2001,sendbuff,sendlen);
+            break;
+        case 0x1003: case 0x1004: case 0x1005: case 0x1007: // 需要在升级时处理
+            if(0==check_dev_type_sn(msg->comInfo.upMsg.up0x1001.devType,msg->comInfo.upMsg.up0x1001.devSn)) return;
+            ota_timer_stop(&g_otaTimer.randomTmr);
+            if(0x1005 == cmd) g_updateDa.bRetransmit = 0;
+            //data_dump("收到升级指令",data,len);
+            ota_update_slave_task(cmd,msg->comInfo.info,msg->palen-2);
+            break;
+        case 0x1006: // 离线升级
+            ota_update_slave_offline(msg->comInfo.info,msg->palen-2);
+            break;
+
+
+        }
+    }
+}
+/*----------------------------------------------------------------------------------
+ *   解析日志类 0x10
+ * ---------------------------------------------------------------------------------*/
+void analysis_cmd_log(uint16_t cmd,uint8_t *data,uint8_t len)
+{
+    MasterSlave *msg = (MasterSlave*)data;
+//    uint16_t sIndex = 0xFF;
+
+    switch(cmd){
+    case 0x1062:
+        if(msg->comInfo.lg1062.devTypeS != DEV_TYPE) break;
+        if((msg->comInfo.lg1062.devSnS != 0xFFFFFFFF)&& (msg->comInfo.lg1062.devSnS!= g_devMsg.devSn)) break;
+        if(msg->comInfo.lg1062.time != 0) {
+            g_logMsg.logType = msg->comInfo.lg1062.logType;
+            g_logMsg.blogOpen = 1;
+            timeout_setValue(&g_logMsg.timer,msg->comInfo.lg1062.time*1000);
+            timeout_start(&g_logMsg.timer);
+        }
+        else{
+            g_logMsg.logType = 0;
+            g_logMsg.blogOpen = 0;
+            timeout_stop(&g_logMsg.timer);
+        }
+        printf("收到 10---1062, delay = %d, type=%d\r\n",msg->comInfo.lg1062.time,msg->comInfo.lg1062.logType);
+        break;
+    case 0x1063:
+        if(msg->comInfo.lg1063.devTypeS != DEV_TYPE) break;
+        if((msg->comInfo.lg1063.devSnS != 0xFFFFFFFF)&& (msg->comInfo.lg1063.devSnS!= g_devMsg.devSn)) break;
+        slave_send_log_0x2063(msg->comInfo.lg1063.devTypeM,msg->comInfo.lg1063.devSnM,msg->comInfo.lg1063.logType,g_testCollDa.sendCollNum,192);
+        break;
+//    case 0x2062: // 错误数据
+//        sIndex = master_check_dev_table(msg->comInfo.lg2062.devTypeS,msg->comInfo.lg2062.devSnS);
+//        if(sIndex == 0xFF) return;
+//        fifo_write(&g_4Gtxfifo,data,len);// 直接透传
+//        timeout_stop(&g_uart485.time);
+//        break;
+    }
+}

+ 277 - 0
App/masterslave.h

@@ -0,0 +1,277 @@
+#ifndef _DN_485_H_
+#define _DN_485_H_
+
+#include "../Hardware/boardinit.h"
+#include "public.h"
+#include "xspDataOpt.h"
+/*-------------------------------------系统指令 --------------------*/
+#define SYSTEM_1001_LEN 13
+#define SYSTEM_2030_LEN 24
+#define SYSTEM_1030_LEN 16
+typedef struct _system_0x1021_{ // 系统类指令 重启
+    uint8_t  object; // 重启对象
+    uint8_t  info[2]; // 用于存储crc 校验码
+}__attribute__((packed))system0x1021;
+typedef struct _system_0x1015_{ // 系统类指令  时间同步
+    uint32_t timer;   // 时间戳
+    uint32_t reserve; // 预留
+}__attribute__((packed))system0x1015;
+
+typedef struct _sys_cmd_1026_{
+    uint8_t priceInuseCout; // 对于单价屏是否探针板接线
+    uint8_t confFileNum[8]; //配置文件编号
+    uint16_t appointDevModel; // 配置文件适配设备类型
+    uint8_t portStatus;    // 端口是否启用
+    uint8_t portNum[4];    // 每个端口连接针脚的个数
+    uint8_t comGroup;      // com端的级数
+    uint8_t param[4][4];   //  一共4组,每组4个参数
+}__attribute__((packed))sysCmd1026;
+
+typedef struct _system_0x1026_{ // 系统类指令 com端文件配置
+    uint32_t reserve;      // 预留 不需要存储EPPROM -4
+    uint16_t expireTime;   // 过期时间  不需要存储EPPROM -2
+    uint8_t priceInuseCout; // 对于单价屏是否探针板接线
+    uint8_t confFileNum[8]; //配置文件编号
+    uint16_t appointDevModel; // 配置文件适配设备类型
+    uint8_t portStatus;    // 端口是否启用
+    uint8_t portNum[4];    // 每个端口连接针脚的个数
+    uint8_t comGroup;      // com端的级数
+    uint8_t param[4][4];   //  一共4组,每组4个参数
+}__attribute__((packed))system0x1026;
+
+typedef struct _sys_cmd_1027_{
+    uint8_t confFileNum[8]; //配置文件编号
+    uint16_t appointDevModel; // 配置文件适配设备类型
+    uint8_t groupNum;         // 组数
+    uint8_t table[300][2];    // 表的说明
+}__attribute__((packed))sysCmd1027;
+extern sysCmd1027 g_table1027;
+extern sysCmd1027 g_temtable1027; // ???±±í
+
+typedef struct _sys_0x1027_{
+    uint32_t reserve;      // 预留
+    uint16_t expireTime;   // 过期时间
+    uint8_t  framNo;       // 帧号
+    sysCmd1027 da1027;
+}__attribute__((packed))system0x1027;
+
+
+
+typedef struct _sys_0x1028_{
+    uint32_t time;         // 开启时常
+}__attribute__((packed))system0x1028;
+
+typedef struct _sys_0x1029_{
+    uint8_t status;        // 保存状态 1:保存 2:放弃
+}__attribute__((packed))system0x1029;
+typedef struct _sys_0x1030_{
+    uint32_t reserve;
+    uint8_t info[2];//用于校验位
+}__attribute__((packed))system0x1030;
+
+typedef struct _sys_0x2030_{
+    uint8_t configfileNo[8];        //配置文件编号
+    uint32_t reserve;               //预留
+}__attribute__((packed))system0x2030;
+
+typedef union _system_cmd_table_{
+    system0x1021 s0x1021;
+    system0x1015 s0x1015;
+    system0x1026 s0x1026; // com端配置文件
+    system0x1027 s0x1027; // 探针脚配置文件
+    system0x1028 s0x1028; // 开启8段码上报
+    system0x1029 s0x1029; // 关闭8段码上报
+    system0x1030 s0x1030; // 读取8段数据
+    system0x2030 s0x2030;  // 上报8段码数据
+}__attribute__((packed))systemCmdTable;
+
+typedef struct _system_cmd_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    systemCmdTable sDa;
+}__attribute__((packed))systemCmd;
+
+
+/*-------------------------------------状态指令 --------------------*/
+enum {
+    SELF_STATUS = 0x02,
+    SLAVE_OFFLINE = 0x03,
+};
+
+typedef struct _status_0x2002_{
+    uint16_t devTypeM;      //主设备类型
+    uint32_t devSnM;        //主设备SN
+    uint16_t devTypeS;      //从设备类型
+    uint32_t devSnS;        //从设备SN
+    uint8_t  cfgFileNo[8];  //配置文件编号
+    uint8_t identity;       //主从身份 1:从 2:主
+    uint8_t  bHave4G;       //是否有4G模块 0:无 1:有
+    uint8_t status;         //在线状态 0:离线 1:在线
+    uint8_t lastResetType;  // 最后一次复位类型
+    uint32_t resetNum;      // 复位次数
+    uint32_t runTime;       // 运行时常
+    uint32_t voltage;       // 电压
+    uint32_t temperature;   // 温度
+    uint16_t rssi4G;        // 4G强度
+    uint16_t snr4G;         // 4G信噪比
+    uint32_t tempStamp;     // 时间戳
+    uint32_t reserve;
+}__attribute__((packed))status0x2002;
+
+typedef struct _status_0x2001_{
+    uint16_t devTypeM;  // 主设备类型
+    uint32_t devSnM;    // 主设备SN
+    uint16_t devTypeS;  // 从设备类型
+    uint32_t devSnS;    // 从设备SN
+    uint8_t upCode;     // 升级状态码
+    uint32_t bootVer;   // bootloader版本
+    uint32_t ptVer;     // pt版本
+    uint32_t appVer;    // app版本
+    uint8_t uuid[12];   // UUID
+    uint8_t imei[15];   // imei
+    uint8_t iccid[20];  // iccid
+    uint32_t reserve;   // 预留
+}__attribute__((packed))status0x2001;
+
+#define STATUS_COMM_LEN 12
+typedef struct _status_comm_msg_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint8_t info[2];
+}__attribute__((packed))statCom;
+
+/*-------------------------------------数据指令 --------------------*/
+#define DATA_1061_LEN 20
+typedef struct _data_0x1061_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint32_t recordId;
+    uint32_t reserve;
+    uint8_t info[2];
+}__attribute__((packed))data0x1061;
+
+#define DATA_2061_LEN 18
+typedef struct _data_0x2061_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint32_t reserve;
+    uint8_t bnewflag; // 新交易标识
+    uint8_t palen;    // 参数长度
+    uint8_t info[160];
+}__attribute__((packed))data0x2061;
+
+#define LOG_2062_LEN 17
+typedef struct _log_0x2062_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint32_t reserve;
+    uint8_t palen;    // 参数长度
+    uint8_t info[160];
+}__attribute__((packed))log0x2062;
+
+#define LOG_1062_LEN 21
+typedef struct _log_0x1062_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint8_t  logType;      // 日志类型
+    uint32_t time;         // 开启日志的时间
+    uint32_t reserve;      // 预留
+}__attribute__((packed))log0x1062;
+
+#define LOG_2063_LEN 18
+typedef struct _log_0x2063_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint8_t logtype; // 1:错误七段码上 2:log 日志 3:信号错误率
+    uint32_t reserve;
+    uint8_t palen;    // 参数长度
+    uint8_t info[256];
+}__attribute__((packed))log0x2063;
+
+#define LOG_1063_LEN 22
+typedef struct _log_0x1063_{
+    uint16_t devTypeM;
+    uint32_t devSnM;
+    uint16_t devTypeS;
+    uint32_t devSnS;
+    uint8_t  logType;      // 日志类型 1: 去重七段码上报 2:lg日志 3: 信号采集率调试
+    uint32_t time;         // 开启日志的时间(秒) 0: 关闭 非0:开始时长
+    uint8_t interval;     // 间隔上报 秒
+    uint32_t reserve;      // 预留
+}__attribute__((packed))log0x1063;
+
+
+/*----------------------------------升级指令-------------------------*/
+typedef struct _update_0x1001_{
+    uint16_t devType;
+    uint32_t devSn;
+    uint16_t taskId; // 任务号
+    uint32_t reserve; // 预留
+}__attribute__((packed))update0x1001;
+
+typedef struct _update_0x2001_{
+    uint16_t devType;
+    uint32_t devSn;
+    uint32_t appVer;
+    uint16_t taskId;
+    uint32_t reserve;
+}__attribute__((packed))update0x2001;
+
+typedef union _update_info_{
+    update0x1001 up0x1001;
+    update0x2001 up0x2001;
+}__attribute__((packed))updateCmd;
+
+/*------------------------------------------------------------------*/
+typedef union _comm_info_{
+    //system0x1021 sys1021;
+    systemCmd sysMsg;
+    statCom statusMsg;
+    updateCmd upMsg;
+    data0x1061 da1061;
+    data0x2061 da2061;
+    log0x1062  lg1062;
+    log0x2062  lg2062;
+    log0x1063  lg1063;
+    log0x2063  lg2063;
+    uint8_t info[256];
+}__attribute__((packed))commInfo_t;
+
+#define COMM_HEAD_LEN 12
+typedef struct _HEAD_DATA_{
+    uint16_t start;
+    uint8_t proVer;
+    uint32_t msgId;
+    uint8_t msgType1;
+    uint16_t msgType2;
+    uint16_t palen;
+    commInfo_t comInfo;
+}__attribute__((packed))MasterSlave;
+
+
+extern void slave_send_data_to_uart(uint8_t type1, uint16_t type2,uint8_t *data,uint8_t len);
+
+extern void slave_send_log_0x2063(uint16_t devType, uint32_t devSn,uint8_t logtype,uint8_t *data, uint8_t len);
+
+extern void slave_send_data_0x2030(uint16_t devType, uint32_t devSn,uint8_t *data,uint8_t *cfigNo, uint8_t len);
+
+extern void analysis_cmd_system(uint16_t cmd, uint8_t *data,uint8_t len);
+extern void analysis_cmd_status(uint16_t cmd, uint8_t *data,uint8_t len);
+extern void analysis_cmd_data(uint16_t cmd,uint8_t *data,uint8_t len);
+extern void analysis_cmd_update(uint16_t cmd,uint8_t *data,uint8_t len);
+extern void analysis_cmd_log(uint16_t cmd,uint8_t *data,uint8_t len);
+#endif

+ 858 - 0
App/ota_update.c

@@ -0,0 +1,858 @@
+/*----------------------------------------------------------------------------------
+ *  备份寄存器的说明
+ *  BKP_DR0: 写入的RTC标志
+ *  BKP_DR1: 写入升级标志码
+ *  BKP_DR2: 写入升级状态码
+ *  BKP_DR3: 写入升级任务号
+ *  BKP_DR4: 升级的来源: 0x22:来源于服务器下发的 0x44:来源于网关的离线升级
+ *  BKP_DR5: 上电后升级从设备
+ *  BKP_DR6: 升级的固件类型
+ * ---------------------------------------------------------------------------------*/
+#include "ota_update.h"
+#include "masterslave.h"
+
+static uint8_t _buff[256];
+
+UpdateDa g_updateDa;
+OtaUpdateTime g_otaTimer;
+static otaUpdatMsg ota_devMsg;
+static uint16_t updata_state,updata_state_save;
+
+//static void send_update_code_to_serve(uint16_t devtype, uint32_t devsn,uint16_t taskId,uint8_t upcode,uint8_t firmType)
+//{
+//    uint8_t  bufflen;
+
+//    memset(_buff,0,256);
+//    up_update_cmd_0x2002(_buff,&bufflen,devtype,devsn,taskId,firmType,upcode);
+//    add_data_to_4G_txfifo(_buff,bufflen,0x04,0x2002);
+//}
+
+/*--------------------------------------------------------------------------
+ *  上电读取升级的状态
+ * --------------------------------------------------------------------------*/
+void ota_power_up_read_update_status(void)
+{
+    uint16_t data;
+
+    data = bkp_data_read(BKP_DATA_1); // 读取入标志码
+    if(data != 0){
+        if(updata_state_cmp(data)){
+            if((data&0x00ff) == 0x82){ // 升级成功
+                data = set_updata_state(UPDATE_SUCCESS);
+                bkp_data_write(BKP_DATA_2, data);
+                printf("\r\n send to net update sucess\r\n");
+            }
+            else if((data&0x00ff) == 0x83) { // 回退成功
+                data = set_updata_state(UPDATE_RETURN_SUCESS);
+                bkp_data_write(BKP_DATA_2, data);
+                 printf("\r\n send to net return sucess\r\n");
+            }
+            printf("\r\n update status1 = %x\r\n",data);
+            data = bkp_data_read(BKP_DATA_2);
+            bkp_data_write(BKP_DATA_1, 0);
+            g_updateDa.updateCode = data&0xFF;
+			
+            data = bkp_data_read(BKP_DATA_3);//升级任务号
+            g_updateDa.taskNo = data;
+			
+            data = bkp_data_read(BKP_DATA_4);
+            //if(data == UP_PROG_FROM_NET) g_updateDa.bResetUpdate = 1;
+            //else g_updateDa.bResetUpdate = 2;
+            if(data == UP_PROG_FROM_GAT)
+            {
+                set_start_ota_timer(&g_otaTimer.randomTmr,(rand()%150+200));
+            }
+            g_updateDa.Update_Source = data;
+            g_updateDa.bResetUpdate = 1;
+            printf("g_updateDa.bResetUpdate = %d\r\n",g_updateDa.bResetUpdate);
+            bkp_data_write(BKP_DATA_4, 0);
+			
+            data = bkp_data_read(BKP_DATA_6);//固件类型
+            g_updateDa.bfirmware_type = data;
+
+            data = bkp_data_read(BKP_DATA_5);
+            printf("bkp5=%04x\n",data);
+            if(data == UPDATE_SLAVE)//需要升级从设备
+            {
+                if(ota_offline_init(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE))//升级包正确
+                {
+                    ota_master_init_update_msg_offline(g_devMsg.devType,0xffffffff,g_devMsg.devType,0xffffffff,g_updateDa.bfirmware_type);
+//					g_updateDa.bOffline_s = 1;//可以离线升级
+                    g_updateDa.bUpdate_slave = data;
+                    g_updateDa.bOffline_addr = OTA_UPDATE_APP3_FLASH_START_ADDR;
+                    g_devMsg.workMode = WORK_UPDATE;
+                    g_devMsg.ledgreen = 2;
+                    printf("升级从设备\n");
+                }
+            }
+            bkp_data_write(BKP_DATA_5, 0);
+        }
+    }
+    else{
+        g_updateDa.bResetUpdate = 0;
+        printf("\r\n no update program, data = %x\r\n",data);
+    }
+}
+void set_start_ota_timer(otaTimeSet *timer, uint32_t delay)
+{
+    timeout_stop(&(timer->timer));
+    timeout_setValue(&(timer->timer),delay);
+    timeout_start(&(timer->timer));
+    timer->status = OTA_TIMER_START;
+}
+void ota_timer_stop(otaTimeSet *timer)
+{
+    timeout_stop(&timer->timer);
+    timer->status = OTA_TIMER_END;
+}
+
+/*----------------------------------------------------------------------
+ *  1: 超时 0: 未超时
+ * ---------------------------------------------------------------------*/
+uint8_t ota_timer_is_timeout(otaTimeSet * timer)
+{
+    if(timer->status == OTA_TIMER_NULL) return 0; // 定时器还未启动时
+    if((OTA_TIMER_START == timer->status) && timeout_isOut(&(timer->timer))){
+        timer->status = OTA_TIMER_END;
+        return 1;
+    }
+    else
+        return 0;
+}
+
+void ota_master_update_slave_continue(otaUpdatMsg *msg,uint32_t addr)
+{
+    updateCmd0x1004 *pmsg = NULL;
+   // uint8_t i;
+    pmsg = (updateCmd0x1004*)_buff;
+    memset(_buff,0,256);
+    pmsg->rcvDevType = msg->rcvDevType;
+    pmsg->rcvDevSn   = msg->rcvDevSn;
+    pmsg->desDevType = msg->rcvDevType;
+    pmsg->desDevSn   = msg->rcvDevSn;
+    pmsg->totalPage  = msg->totalPage;
+    pmsg->subPkgId   = msg->subPkgId;
+    pmsg->subPkgLen  = msg->subPkgLen;
+
+    while(ota_devMsg.subPkgId <= ota_devMsg.totalPage){
+		start_delay_ms(msg->sendInterval);
+        printf("lora_gw_ota_continues %d\r\n", msg->subPkgId);
+        pmsg->subPkgId = msg->subPkgId++;
+        Flash_BufferRead(addr + (pmsg->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE,
+            ((uint8_t *)pmsg) + OTA_CONTINUES_INFO_LEN, OTA_MASTER_SEND_PKG_SIZE);
+//        if(pmsg->subPkgId%30)
+            slave_send_data_to_uart(0x04,0x1004,(uint8_t*)pmsg,sizeof(updateCmd0x1004)+OTA_MASTER_SEND_PKG_SIZE);
+//        for(i=0;i< sizeof(updateCmd0x1004)+OTA_MASTER_SEND_PKG_SIZE-OTA_CONTINUES_INFO_LEN;i++){
+//            printf("%02x ",_buff[i]);
+//        }
+//        printf("\r\n");
+//		printf("发送间隔:%u\n",msg->sendInterval);
+//        start_delay_ms(msg->sendInterval);
+        while(!g_iDelayfinish);
+    }
+    printf("continue finish, start repeat\r\n");
+
+}
+/*-------------------------------------------------------------------------------
+ *  从设备初化
+ * ------------------------------------------------------------------------------*/
+void ota_slave_init_update_msg(updateCmd0x1003 *msg)
+{
+    memset(&ota_devMsg,0,sizeof(otaUpdatMsg));
+
+    ota_devMsg.rcvDevType   = msg->rcvDevType;    // 接收设备类型
+    ota_devMsg.rcvDevSn     = msg->rcvDevSn;      // 接收设备SN
+    ota_devMsg.desDevType   = msg->desDevType;    // 升级目标设备类型
+    ota_devMsg.desDevSn     = msg->desDevSn;      // 升级目标设备SN
+    ota_devMsg.firmType     = msg->firmType;      // 固件类型
+    ota_devMsg.totalByte    = msg->totalByte;     // 升级总总长度
+    ota_devMsg.eachMaxByte  = msg->eachMaxByte;   // 单包最大字节类
+    ota_devMsg.losePage     = msg->losePage;      // 最大丢包面分比 最小为10%,最大为60%
+    ota_devMsg.sendInterval = msg->sendInterval;  // 连续阶段发 送包的时间间隔(单位:ms)
+    ota_devMsg.totalPage    = msg->totalByte/OTA_MASTER_SEND_PKG_SIZE; //总包数
+    if(msg->totalByte%OTA_MASTER_SEND_PKG_SIZE) ota_devMsg.totalPage += 1;
+	ota_devMsg.loseTotalPage = (ota_devMsg.totalPage*ota_devMsg.losePage)/100;//计算最大丢包数
+	ota_devMsg.loseTotalPage = (ota_devMsg.loseTotalPage>250)?250:ota_devMsg.loseTotalPage;//最大丢包数不能超过250个
+	printf("losetotalpage=%d\n",ota_devMsg.loseTotalPage);
+    ota_devMsg.subPkgId     = 1;      // 升级包编号
+    ota_devMsg.subPkgLen    = 0;     // 本升级包的长度
+    ota_devMsg.lastRightPkgNum = 1;
+    ota_devMsg.lossPkgIndex = 0;
+}
+
+/*--------------------------------------------------------------------------
+ *  主设备升级从设备
+ * -------------------------------------------------------------------------*/
+void ota_master_update_salve(otaUpdatMsg*msg,uint32_t addr)
+{
+    uint8_t i;
+    updateCmd0x1003 pMsg;
+    pMsg.rcvDevType = msg->rcvDevType;
+    pMsg.rcvDevSn   = msg->rcvDevSn;
+    pMsg.desDevType = msg->desDevType;
+    pMsg.desDevSn   = msg->desDevSn;
+    pMsg.firmType   = msg->firmType;
+    pMsg.updateVer  = msg->version;
+    pMsg.totalByte  = msg->totalByte;
+    pMsg.eachMaxByte= OTA_MASTER_SEND_PKG_SIZE;
+    pMsg.losePage   = msg->losePage;
+    pMsg.sendInterval = msg->sendInterval;
+    for(i=0;i<3;i++){ // 下发启动升级指令
+        slave_send_data_to_uart(0x04,0x1003,(uint8_t*)&pMsg,sizeof(updateCmd0x1003));
+        start_delay_ms(2000);
+        while(!g_iDelayfinish);
+    }
+
+    set_start_ota_timer(&g_otaTimer.totalTmr,OTA_TIM_TOTALTMR); // 升级的总时间
+    printf("启动升级总定时时间\r\n");
+    ota_master_update_slave_continue(msg,addr);// 处理连续升级指令
+    set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT); //启动重传定时器
+    printf("启动升级重传时间\r\n");
+}
+
+//重传随机延时
+void ota_repeat_rand_timer(uint8_t status)
+{
+	static uint32_t randDa;
+	
+//	srand(randDa+g_devMsg.devSn);
+	if(status == 0)
+		randDa = rand()%150 + 200;
+	else
+		randDa = rand()%150 + 500;
+	printf("重传随机时间 = %d\r\n",randDa);
+	set_start_ota_timer(&g_otaTimer.repeatRandomTmr,randDa);
+}
+
+void ota_check_update_timer(void)
+{
+	int i;
+	uint32_t randDa;
+    //if(g_updateDa.Work_State == OTA_UPDATE_CONTINUE_END){
+        ota_update_slave_continue_end(g_updateDa.Work_State);
+    //}
+
+    if(ota_timer_is_timeout(&g_otaTimer.totalTmr)){ // 总定时器超时
+        g_updateDa.Work_State = OTA_UPDATE_NULL;
+        //g_devMsg.workMode = WORK_NORMAL;
+        reset_work_mode();
+
+        printf("启动升级总定时时间--超时\r\n");
+    }
+    if(ota_timer_is_timeout(&g_otaTimer.onlookerTmr)){ // 旁观都定时器超时
+        if(g_updateDa.iDentity == IDENTITY_SLAVE)
+        {
+            if(g_updateDa.ResetUpdate_s)
+            {
+                g_updateDa.ResetUpdate_s = 0;
+                g_updateDa.bResetUpdate = 1;
+
+                randDa = rand()%150+200;
+                set_start_ota_timer(&g_otaTimer.randomTmr,randDa);
+                printf("上报升级状态\n");
+            }
+        }
+
+        //g_devMsg.workMode = WORK_NORMAL;
+        reset_work_mode();
+        ota_timer_stop(&g_otaTimer.continueTmr);
+        ota_timer_stop(&g_otaTimer.repeatTmr);
+        ota_timer_stop(&g_otaTimer.totalTmr);
+        printf("旁观者时间到\r\n");
+    }
+    if(ota_timer_is_timeout(&g_otaTimer.continueTmr)) {
+        printf("连续发包超时\n");
+        if(IDENTITY_MASTER != g_updateDa.iDentity)//被升级设备
+        {
+            for(i=ota_devMsg.lastRightPkgNum;i<ota_devMsg.totalPage;i++){
+                ota_devMsg.losePkgNum++;
+                ota_devMsg.lossPkgId[ota_devMsg.lossPkgIndex++] = i;
+                if(ota_devMsg.losePkgNum == ota_devMsg.loseTotalPage) {// 丢10条
+                    set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+                    updata_state_save = set_updata_state(PACKET_LOSS_MORE);// 丢包太多
+                    bkp_data_write(BKP_DATA_2,updata_state_save);
+                    return;
+                }
+            }
+            if(ota_devMsg.losePkgNum)//有丢包,开始重传
+            {
+                g_updateDa.Work_State = OTA_UPDATE_REPEAT;
+                set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT);
+                ota_repeat_rand_timer(0);//重传随机延时
+            }
+        }
+    }
+    if(ota_timer_is_timeout(&g_otaTimer.repeatTmr)){
+        printf("启动升级重传时间--超时\r\n");
+        if(IDENTITY_MASTER != g_updateDa.iDentity)//被升级设备
+        {
+            updata_state = RETRANSMIT_TIMEOUT;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+            g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+            ota_timer_stop(&g_otaTimer.repeatRandomTmr);
+            ota_timer_stop(&g_otaTimer.repeatTmr);
+        }
+        else//下发升级的设备
+        {
+            ota_timer_stop(&g_otaTimer.repeatRandomTmr);
+            ota_timer_stop(&g_otaTimer.repeatTmr);
+            set_start_ota_timer(&g_otaTimer.upstatusTmr,10*1000);
+        }
+    }
+    if(ota_timer_is_timeout(&g_otaTimer.upstatusTmr)){ // 读取状态时间
+        ota_timer_stop(&g_otaTimer.totalTmr);
+        ota_timer_stop(&g_otaTimer.repeatTmr);
+        //g_devMsg.workMode = WORK_NORMAL;
+        reset_work_mode();
+        g_updateDa.Work_State = OTA_UPDATE_NULL;
+        memset(&g_updateDa,0,sizeof(UpdateDa));//
+        printf("状态已经上报,升级结束\r\n");
+    }
+}
+
+/*---------------------------------------------------------------------------
+ *  从设备运行的升级任务
+ * ---------------------------------------------------------------------------*/
+void ota_update_slave_task(uint16_t cmd,uint8_t *data,uint8_t len)
+{
+    uint16_t totalPkg,i;
+    uint32_t otaContinueTmr;
+    updateCmd0x1003 *msg1003 = NULL;
+    updateCmd0x1004 *msg1004 = NULL;
+    updateCmd0x1005 *msg1005 = NULL;
+    if(OTA_UPDATE_ONLOOKER == g_updateDa.Work_State) { //旁观者身份
+        set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+        printf("cur mode outlooker_01 \r\n");
+    }
+    else {
+        switch(cmd){
+        case 0x1003:
+            msg1003 = (updateCmd0x1003*)data;
+            g_devMsg.workMode = WORK_UPDATE;
+            g_devMsg.ledgreen = 2;
+            if(0 == check_dev_type_sn(msg1003->desDevType,msg1003->desDevSn)){
+                g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+                set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);// 打开旁观者定时器
+                printf("cur mode outlooker \r\n");
+                break;
+            }
+            if(OTA_UPDATE_NULL == g_updateDa.Work_State){
+                Flash_RangeErase(OTA_UPDATE_APP3_FLASH_START_ADDR, OTA_UPDATE_APP3_FLASH_SIZE); //擦除app3
+            }
+            g_updateDa.iDentity = IDENTITY_SLAVE;//标记为被升级状态
+            g_updateDa.ResetUpdate_s = 1;//需要上报升级状态
+            g_updateDa.Update_Source = UP_PROG_FROM_GAT;
+            bkp_data_write(BKP_DATA_4, UP_PROG_FROM_GAT); // 升级的来源 0x44 来源来网关下发的
+            g_updateDa.bfirmware_type = msg1003->firmType;
+            bkp_data_write(BKP_DATA_6,g_updateDa.bfirmware_type);//记录固件类型
+			
+            set_start_ota_timer(&g_otaTimer.totalTmr,OTA_TIM_TOTALTMR); // 打开总定时器
+            //收到升级指令
+            updata_state = START_UPDATA;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+            g_updateDa.Work_State = OTA_UPDATE_BEGIN;
+            totalPkg = (msg1003->totalByte%msg1003->eachMaxByte) ? msg1003->totalByte/msg1003->eachMaxByte+1 : msg1003->totalByte/msg1003->eachMaxByte;
+            otaContinueTmr = totalPkg*msg1003->sendInterval + OTA_TIM_CONTINUE;
+            if(otaContinueTmr > 8*60*1000){
+                g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+                set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+                return;
+            }
+            ota_slave_init_update_msg(msg1003);
+            set_start_ota_timer(&g_otaTimer.continueTmr,otaContinueTmr); // 启用续传定时器
+            printf("ota_totle_byte:%d, ota_totle_pkg:%d\n",msg1003->totalByte,totalPkg);
+            printf("send interval:%d, continuous time:%d\n",msg1003->sendInterval,otaContinueTmr);
+            break;
+        case 0x1004:
+            msg1004 = (updateCmd0x1004*)data;
+            if((OTA_UPDATE_BEGIN == g_updateDa.Work_State) || (OTA_UPDATE_CONTINUE == g_updateDa.Work_State)){
+                if(0 == check_dev_type_sn(msg1004->desDevType,msg1004->desDevSn)){
+                    g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+                    set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);// 打开旁观者定时器
+                    ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器
+                    break;
+                }
+                if(msg1004->subPkgLen > ota_devMsg.eachMaxByte) break; // 接收错误
+                if(OTA_UPDATE_BEGIN == g_updateDa.Work_State) g_updateDa.Work_State = OTA_UPDATE_CONTINUE;
+                if((msg1004->totalPage == ota_devMsg.totalPage) && (msg1004->subPkgId <= ota_devMsg.totalPage)){
+                    printf("update continue type=0x%x,sn=0x%x,{%d/%d/%d}\r\n",msg1004->rcvDevType,msg1004->rcvDevSn,
+                           msg1004->totalPage,msg1004->subPkgId,ota_devMsg.losePkgNum);
+                    Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (msg1004->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE,
+                        (uint32_t *)((data+OTA_CONTINUES_INFO_LEN)), msg1004->subPkgLen);
+                    //data_dump("收到1004",(uint8_t*)data+OTA_CONTINUES_INFO_LEN,msg1004->subPkgLen);
+                    for(i=ota_devMsg.lastRightPkgNum;i<msg1004->subPkgId;i++){
+                        ota_devMsg.losePkgNum++;
+                        ota_devMsg.lossPkgId[ota_devMsg.lossPkgIndex++] = i;
+                        if(ota_devMsg.losePkgNum == ota_devMsg.loseTotalPage) {// 丢10条
+                            set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+                            updata_state_save = set_updata_state(PACKET_LOSS_MORE);// 丢包太多
+                            bkp_data_write(BKP_DATA_2,updata_state_save);
+                            return;
+                        }
+                    }
+                    ota_devMsg.lastRightPkgNum = msg1004->subPkgId +1;
+                    if(msg1004->subPkgId == msg1004->totalPage){ // 最后一包
+                        if(0 == ota_devMsg.losePkgNum){ // 没有丢包
+                            printf("传输完成,没有丢包\r\n");
+                            ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器
+                            g_updateDa.Work_State = OTA_UPDATE_CONTINUE_END; // 接收完成
+                            printf("check program right\r\n");
+
+                        }
+                        else { // 有丢包
+                            printf("传输完成,有丢包,启动重传指令\r\n");
+                            g_updateDa.Work_State = OTA_UPDATE_REPEAT;
+                            set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT);
+                            ota_repeat_rand_timer(0);//重传随机延时
+                        }
+                        ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器
+                    }
+                    else { // 不是最后一包
+
+                    }
+                }
+            }
+            else {
+                g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+                set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+                ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器
+            }
+            break;
+        case 0x1005:
+            msg1005 = (updateCmd0x1005*)data;
+            if(g_updateDa.Work_State == OTA_UPDATE_REPEAT) {
+//                ota_timer_stop(&g_otaTimer.repeatTmr);
+                if(msg1005->totalPage == ota_devMsg.totalPage){
+                    if(msg1005->subPkgLen > OTA_MASTER_SEND_PKG_SIZE) return;
+                    //判定该包是否为本设备丢的那些包之中的子包
+                    for(i = 0;i < ota_devMsg.lossPkgIndex;i++) {
+                        if(ota_devMsg.lossPkgId[i] == msg1005->subPkgId) {
+                            ota_devMsg.losePkgNum--;
+                            ota_devMsg.lossPkgId[i] = 0;
+
+                            //接受本包并写入flash的对应位置
+                            Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (msg1005->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE,
+                            (uint32_t *)(data+OTA_CONTINUES_INFO_LEN ), msg1005->subPkgLen);
+
+                            printf("rcv retransmit pkgid:%d\n",msg1005->subPkgId);
+                            break;
+                        }
+                    }
+                    if(ota_devMsg.losePkgNum == 0) //丢包已收完
+                    {
+                        //ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT;
+                        //g_updateDa.Work_State = DEV_WORK_STATE_OTA_UPGRADE_RCV_END;
+                        g_updateDa.Work_State = OTA_UPDATE_REPEAT_END;
+                        ota_timer_stop(&g_otaTimer.repeatRandomTmr);
+                    }
+                    printf("ota_info.lossPkgCounter = %d, lossPkgId:%d\r\n", ota_devMsg.losePkgNum,msg1005->subPkgId);
+                    //指示灯显示
+                    //remain_pkg = ota_info.lossPkgCounter; //gch
+                }
+//                set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT);
+                  g_updateDa.retransmit_s = 0;
+            }
+            else {
+                g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+                set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);
+                ota_timer_stop(&g_otaTimer.continueTmr);// 关闭连续定时器
+            }
+            break;
+        }
+
+
+    }
+
+}
+void ota_update_slave_retransmit(uint16_t index)
+{
+    updateCmd0x2005 *msg = (updateCmd0x2005*)_buff;
+
+    memset(_buff,0,256);
+
+    msg->slaveDevType = g_devMsg.devType;
+    msg->slaveDevSn   = g_devMsg.devSn;
+    msg->repDevType   = g_devMsg.devType;
+    msg->repDevSn     = g_devMsg.devSn;
+    msg->repPkgId     = index;
+
+    slave_send_data_to_uart(0x04,0x2005,(uint8_t*)msg,sizeof(updateCmd0x2005));
+
+
+}
+/*----------------------------------------------------------------------------
+ *  主设备收到重传指令
+ * ---------------------------------------------------------------------------*/
+void ota_update_master_retransmit(uint8_t *data)
+{
+    updateCmd0x2005 *msg = (updateCmd0x2005*)data;
+    updateCmd0x1005 *pmsg = (updateCmd0x1005*)_buff;
+
+    ota_timer_stop(&g_otaTimer.repeatTmr);
+    memset(_buff,0,256);
+    pmsg->rcvDevSn   = ota_devMsg.rcvDevSn;       //msg->slaveDevSn;    ota_devMsg.rcvDevSn;   
+    pmsg->rcvDevType = ota_devMsg.rcvDevType;     //msg->slaveDevType;  ota_devMsg.rcvDevType;
+    pmsg->desDevSn   = ota_devMsg.desDevSn;       //msg->repDevSn;      ota_devMsg.desDevSn;  
+    pmsg->desDevType = ota_devMsg.desDevType;     //msg->repDevType;    ota_devMsg.desDevType;
+    pmsg->subPkgId   = msg->repPkgId;
+    pmsg->subPkgLen  = OTA_MASTER_SEND_PKG_SIZE;
+    pmsg->totalPage  = ota_devMsg.totalPage;
+
+    Flash_BufferRead(OTA_UPDATE_APP3_FLASH_START_ADDR + (pmsg->subPkgId - 1)*OTA_MASTER_SEND_PKG_SIZE,
+        ((uint8_t *)pmsg) + OTA_CONTINUES_INFO_LEN, OTA_MASTER_SEND_PKG_SIZE);
+    slave_send_data_to_uart(0x04,0x1005,(uint8_t*)pmsg,sizeof(updateCmd0x1005)+OTA_MASTER_SEND_PKG_SIZE);
+
+    set_start_ota_timer(&g_otaTimer.repeatTmr,OTA_TIM_REPEAT);
+}
+
+void ota_update_slave_continue_end(uint8_t workMode)
+{
+    uint32_t crcVl,fixChar,fileVer,filelen,i;
+    uint32_t getcrc;
+
+    switch(workMode){
+    case OTA_UPDATE_CONTINUE_END: case OTA_UPDATE_REPEAT_END:
+        crcVl = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-4); //CRC校验
+        fixChar = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-8); // 固定字符 WBJW
+        fileVer = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-12); // 固件信息
+        filelen =  *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_devMsg.totalByte-20); // 文件总长度
+
+        printf("read_fixchar:%08x, fixchar:%08x\n",fixChar,0x57424A57);
+        if(fixChar != 0x57424A57) //固定字符错误
+        {
+            g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+            set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);  //打开旁观者定时器
+            updata_state = FIXED_CHARACTER_ERROR;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+            printf("fixChar error\r\n");// 升级文件固定字符校验错误
+            return;
+        }
+        printf("read_filever:%08x, device_type:%08x\n",fileVer,0x01013000);
+        if((fileVer&0xfffff000) != (APP_VERSION&0xFFFFF000)) //固件信息错误
+        {
+            g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+            set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);   //打开旁观者定时器
+            updata_state = DEVICE_TYPE_ERROR;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+            printf("fileVer error\r\n");// 升级文件固件信息校验错误
+            return;
+        }
+
+        printf("read_filelen:%08x, total_bytes:%08x\n",filelen,(ota_devMsg.totalByte-20));
+        if(ota_devMsg.totalByte != (filelen+20))//长度错误
+        {
+            g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+            set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);   //打开旁观者定时器
+            updata_state = UPDATA_PACKAGE_LENGTH_ERROR;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+            printf("filelen error\r\n");// 升级文件长度校验错误
+            return;
+        }
+        app_check_crc(OTA_UPDATE_APP3_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE,&getcrc);
+        printf("read_crc:%x, get_crc:%x\n",crcVl,getcrc);
+        if(getcrc!=crcVl) { //校验错误
+            printf("update file crc error\r\n");// 升级文件crc校验错误
+            g_updateDa.Work_State = OTA_UPDATE_ONLOOKER;
+            set_start_ota_timer(&g_otaTimer.onlookerTmr,OTA_TIM_ONLOOKER);   //打开旁观者定时器
+            updata_state = UPDATA_CRC_ERROR;
+            updata_state_save = set_updata_state(updata_state);
+            bkp_data_write(BKP_DATA_2, updata_state_save);
+
+            return;
+        }
+
+        printf("收包正确\n");
+        updata_state = UPDATA_DATA_SUCCESS;
+        updata_state_save = set_updata_state(updata_state);
+        bkp_data_write(BKP_DATA_2, updata_state_save);
+
+        updata_state = set_updata_state(UPDATE_FLAG);//置升级标志
+        bkp_data_write(BKP_DATA_1, updata_state);
+
+        //g_firmwareMsg.gatewayMsg.verMsg.gate_appVr3 = fileVer;//存储APP3版本
+        //fram_write_gateway_version();
+        NVIC_SystemReset();
+        break;
+    case OTA_UPDATE_REPEAT:
+//        if(!timeout_isOut(&g_otaTimer.randomTmr.timer)) break;
+		if(!timeout_isOut(&g_otaTimer.repeatRandomTmr.timer)) break;
+//        if(1 == g_updateDa.bRetransmit) break;
+		dma_channel_disable(DMA1, DMA_CH2);
+        if(USART3_RX_SIZE - dma_transfer_number_get(DMA1,DMA_CH2))
+        {
+			dma_channel_enable(DMA1, DMA_CH2);/* enable USART1_RX DMA_Channel */
+			ota_repeat_rand_timer(1);//重传随机延时
+			break;
+		}
+		dma_channel_enable(DMA1, DMA_CH2);/* enable USART1_RX DMA_Channel */
+        for(i = 0;i < ota_devMsg.lossPkgIndex;i++) {
+            if(ota_devMsg.lossPkgId[i])
+            {
+                ota_update_slave_retransmit(ota_devMsg.lossPkgId[i]);
+                printf("send retransmit pkgid:%d\n",ota_devMsg.lossPkgId[i]);
+                g_updateDa.bRetransmit = 1;
+				g_updateDa.retransmit_s = 1;
+                break;
+            }
+        }
+		ota_repeat_rand_timer(0);//重传随机延时
+        break;
+    }
+}
+void ota_update_send_update_status(uint16_t desDevType,uint32_t desDevSn)
+{
+    updateCmd0x2007 *msg = (updateCmd0x2007*)_buff;
+
+    memset(_buff,0,256);
+
+    msg->slaveDevType   = g_devMsg.devType;
+    msg->slaveDevSn     = g_devMsg.devSn;
+    msg->desDevType     = desDevType;
+    msg->desDevSn       = desDevSn;
+    msg->ptVer          = g_devAppVer.ptVer;
+    msg->appVer         = APP_VERSION;
+    msg->updateCode     = g_updateDa.updateCode;
+    msg->reserve        = 0x00;
+    slave_send_data_to_uart(0x04,0x2007,(uint8_t*)_buff,sizeof(updateCmd0x2007));
+}
+
+void ota_update_deal_upstatus(void)
+{
+    static uint8_t flag = 0;
+    if((0x01 ==g_updateDa.bResetUpdate) ) { // 连接网络且有升级
+        
+            if(timeout_isOut(&(g_otaTimer.randomTmr.timer))){ //超时,可以发送
+                printf("发送升级标志 %d\r\n",g_updateDa.updateCode);
+                ota_update_send_update_status(g_devMsg.devType,g_devMsg.devSn);
+                flag++;
+                if(flag >=3 ){
+                    bkp_data_write(BKP_DATA_2,0);//清除标志备份寄存器
+                    g_updateDa.bResetUpdate = 0x00;
+                    memset(&g_updateDa,0,sizeof(UpdateDa));
+                    flag = 0;
+                }
+                set_start_ota_timer(&g_otaTimer.randomTmr,(rand()%150+200));
+            }
+        
+    }
+	
+	
+}
+
+///////////////////////离线升级////////////////////////////
+//读取app程序包的大小并校验
+uint32_t Read_APP_datalen_check(uint32_t addr, uint32_t len)
+{
+    uint32_t datalen = 0;
+	uint32_t crcVl,fixChar,fileVer,filelen,getcrc,t_addr;
+	uint32_t bin_data[6] = {0};
+	uint8_t flag = 0;
+    uint8_t check_flag = 0;
+
+	printf("addr=%08x\n",addr);
+	datalen = Flash_DatalenRead(addr,len);
+	if((datalen > (96*1024)) || (datalen < (20)))
+	{
+		printf("升级包长度超过128K: %d\n",datalen);
+		datalen = 0;
+		return datalen;
+	}
+	
+	filelen =  *(uint32_t*)(addr+datalen-20); // 文件总长度
+	printf("datalen=%08x,%u; filelen=%08x,%u\n",datalen,datalen,filelen,filelen);
+	
+	printf("addr=%08x\n",addr);
+	crcVl = *(uint32_t*)(addr + datalen-4); //CRC校验
+	fixChar = *(uint32_t*)(addr + datalen-8); // 固定字符 WBJW
+	fileVer = *(uint32_t*)(addr + datalen-12); // 固件信息
+	filelen =  *(uint32_t*)(addr + datalen-20); // 文件总长度
+	t_addr = *(uint32_t*)(addr + datalen-16); // 文件写入的地址
+	
+	printf("crcVl=%08x,fixChar=%08x,fileVer=%08x,filelen=%08x,t_addr=%08x\n",crcVl,fixChar,fileVer,filelen,t_addr);
+	
+	//判断后20字节是否正确
+	if((fixChar == 0x57424A57) && (t_addr == 0x08018000))//升级包中包含了后20字节
+	{
+		printf("升级包包含了后20字节\n");
+		if(datalen != (filelen+20))
+		{
+			printf("升级包长度校验错误\n");
+			check_flag = 1;
+		}
+//			else if(fileVer != device_fixed_info.Soft_ver_app)
+//			{
+//				printf("固件信息错误\n");
+//				printf("filever=%08x,app=%08x\n",fileVer,device_fixed_info.Soft_ver_app);
+//                check_flag = 1;
+//			}
+		else
+		{
+			app_check_crc(addr,datalen,&getcrc);
+			printf("read_crc:%08x, get_crc:%08x\n",crcVl,getcrc);
+			if(crcVl != getcrc)
+			{
+				printf("crc 错误\n");
+				check_flag = 1;
+			}
+		}
+	}
+	else
+	{
+		check_flag = 1;
+	}
+
+	if(check_flag)//后20字节错误
+	{
+		if(addr==OTA_UPDATE_APP1_FLASH_START_ADDR)//app1需要计算后20个字节
+		{
+			bin_data[0] = datalen;  //原始bin文件字节长度
+			bin_data[1] = OTA_UPDATE_APP1_FLASH_START_ADDR; //存储地址
+                        bin_data[2] = APP_VERSION; //固件版本
+			bin_data[3] = 0x57424A57; //固定标记,"WBJW"
+			
+			fileVer = bin_data[2];
+
+			flag = Flash_BufferWrite(addr+datalen,bin_data,16);
+			printf("first flag = %d\n",flag);
+			
+			datalen += 20;
+			printf("datalen1=%08x\n",datalen);
+			//app_check_crc(addr,datalen,&getcrc);
+			 rcu_periph_clock_enable(RCU_CRC);           //打开crc时钟
+    crc_data_register_reset();                   //复位crc数据寄存器
+    getcrc = crc_block_data_calculate((uint32_t*)addr,(datalen -4)/4);//计算crc数值
+    rcu_periph_clock_disable(RCU_CRC);            //关闭crc时钟
+
+			bin_data[0] = getcrc;
+			printf("crc=%08x\n",bin_data[0]);
+			flag = Flash_BufferWrite(addr+datalen-4,bin_data,4); //crc校验
+			printf("second flag = %d\n",flag);
+		}
+		else
+		{
+			datalen = 0;
+		}
+		
+	}
+	
+    if(datalen)
+    {
+        memset(&ota_devMsg,0,sizeof(otaUpdatMsg));
+        ota_devMsg.version      = fileVer;     // 升级的软件版本号
+        ota_devMsg.totalByte    = datalen;    // 升级的总大小
+    }
+	return datalen;
+}
+
+void ota_master_init_update_msg_offline(uint16_t rcvdevtype,uint32_t rcvdevsn,uint16_t desdevtype,uint32_t desdevsn,uint8_t firmtype)
+{
+    // memset(&ota_devMsg,0,sizeof(otaUpdatMsg));
+    ota_devMsg.rcvDevType   = rcvdevtype;  // 接收设备类型
+    ota_devMsg.rcvDevSn     = rcvdevsn;    // 接收设备SN
+    ota_devMsg.desDevType   = desdevtype;  // 升级目标设备类型
+    ota_devMsg.desDevSn     = desdevsn;    // 升级目标设备SN
+	ota_devMsg.firmType     = firmtype;    // 升级固件类型
+    // ota_devMsg.version      = version;     // 升级的软件版本号
+    // ota_devMsg.totalByte    = totallen;    // 升级的总大小
+    ota_devMsg.losePage     = 20;
+    ota_devMsg.sendInterval = 300;
+    ota_devMsg.totalPage    = ota_devMsg.totalByte/OTA_MASTER_SEND_PKG_SIZE;
+    if(ota_devMsg.totalByte%OTA_MASTER_SEND_PKG_SIZE) ota_devMsg.totalPage += 1;
+    ota_devMsg.subPkgLen    = OTA_MASTER_SEND_PKG_SIZE;
+    ota_devMsg.subPkgId = 1;
+    ota_devMsg.lastRightPkgNum = 1;
+    ota_devMsg.lossPkgIndex = 0;
+}
+
+
+//离线升级初始化
+uint8_t ota_offline_init(uint32_t addr,uint32_t len)
+{
+    uint32_t total_bytes = 0;
+    total_bytes = Read_APP_datalen_check(addr,len);
+    if(total_bytes==0) //升级包长度错误,升级结束
+    {
+        printf("升级包长度错误 ");
+        return 0;
+    }
+    return 1;
+}
+
+//离线升级过程
+void ota_offline_proc(void)
+{
+    g_updateDa.iDentity = IDENTITY_MASTER;//标记为下发升级设备
+    g_devMsg.workMode = WORK_UPDATE;
+    g_devMsg.ledgreen = 2;
+    ota_master_update_salve(&ota_devMsg,g_updateDa.bOffline_addr);
+}
+
+//离线升级处理函数
+void ota_offline_handle(void)
+{
+    //离线升级
+    if(g_updateDa.bOffline_s)
+    {
+        g_updateDa.bOffline_s = 0;
+        printf("开始离线升级\n");
+        ota_offline_proc();
+    }
+}
+
+//从设备收到离线升级指令
+void ota_update_slave_offline(uint8_t *data,uint8_t len)
+{
+    updateCmd0x1006* msg1006 = (updateCmd0x1006*)data;
+    if(g_devMsg.workMode == WORK_UPDATE) return;
+
+    if((msg1006->masterDevType==g_devMsg.devType) && (msg1006->masterDevSn==g_devMsg.devSn))
+    {
+        if(msg1006->firmType != 0x03) return; //不是升级app
+        if(ota_offline_init(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP1_FLASH_SIZE))//升级包正确
+        {
+            ota_master_init_update_msg_offline(msg1006->slaveDevType,msg1006->slaveDevSn,msg1006->desDevType,msg1006->desDevSn,msg1006->firmType);
+            g_updateDa.bOffline_s = 1;//可以离线升级
+            g_updateDa.bOffline_addr = OTA_UPDATE_APP1_FLASH_START_ADDR;
+            g_devMsg.workMode = WORK_UPDATE;
+            g_devMsg.ledgreen = 2;
+            printf("升级从设备\n");
+        }
+    }
+}
+/*-------------------------------------------------------------------------------
+ *  按键启动离线升级
+ * -----------------------------------------------------------------------------*/
+void ota_start_offline_update(void)
+{
+    if(g_devMsg.workMode != WORK_UPDATE)//非升级模式
+    {
+        if(ota_offline_init(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP1_FLASH_SIZE))//升级包正确
+        {
+            ota_master_init_update_msg_offline(DEV_TYPE,0xffffffff,DEV_TYPE,0xffffffff,0x03);//升级app
+            g_updateDa.bOffline_s = 1;//可以离线升级
+            g_updateDa.bOffline_addr = OTA_UPDATE_APP1_FLASH_START_ADDR;
+            printf("升级从设备\n");
+        }
+        g_devMsg.workMode = WORK_UPDATE;
+        g_devMsg.ledgreen = 2;
+    }
+}
+
+/*-------------------------------------------------------------------------------
+ *  升级成功后,主设备 接收升级的状态
+ * --------------------------------------------------------------------------------*/
+void master_update_status_rcv(uint8_t *data, uint32_t len)
+{
+	updateCmd0x2007 *msg = (updateCmd0x2007*)data;
+	
+	printf("^^^^^^^rcv type = %04x  sn = %08x app = %08x, status = %d\r\n",msg->desDevType, msg->desDevSn,msg->appVer,msg->updateCode);
+//        if((IDENTITY_MASTER == g_updateDa.iDentity) || (IDENTITY_MASTER == g_iDentity))
+//	{
+//		send_update_code_to_serve(msg->desDevType,msg->desDevSn,g_updateDa.taskNo,msg->updateCode,0x03);
+//	}
+}

+ 244 - 0
App/ota_update.h

@@ -0,0 +1,244 @@
+#ifndef _OTA_UPDATE_H_
+#define _OTA_UPDATE_H_
+
+#include "../User/gd32f10x_it.h"
+#include "../Hardware/boardinit.h"
+
+enum { // 升级结果类型
+    UPDATE_RECEIVE_UPDATEFLAG = 0x11, // 收到服务器的升级指令
+    UPDATE_SAMEVERSION, // 和当前版本相同
+    UPDATE_FAILE_NOCOLLECT, // 此采集器不在本网关下
+    UPDATE_HTTP_ERROR,  //HTTP返回错误码
+    UPDATE_DOWNLOADFILE_FAILED, //文件下载失败,即文件大小小于2个字节
+    UPDATE_DOWNLOADFILE_SUCCESS, // 文件下载成功
+    UPDATE_CRCERROR, // 文件包中的CRC与实际不符
+    UPDATE_URL_FILE_TYPE_ERROR, // URL中的文件信息与文件包中的信息不一致
+    UPDATE_DEVICETYPEERROR, // 升级设备类型不匹配
+    UPdATE_FILE_LEN_ERROR,  // 升级文件长度超过128个字节
+    UPDATE_SUCCESS, // 升级成功
+    UPDATE_RETURN_SUCESS, // 回退
+};
+
+//升级状态
+#define START_UPDATA                  0x21  //已收到正确的升级指令
+#define PACKET_LOSS_MORE              0x22  //丢包超标,升级结束
+#define RETRANSMIT_TIMEOUT            0x23  //重传阶段超时,升级失败
+#define UPDATA_CRC_ERROR              0x24  //升级包CRC校验失败
+#define DEVICE_TYPE_ERROR             0x25  //目标设备类型不匹配
+#define UPDATA_PACKAGE_LENGTH_ERROR   0x26  //长度不符
+#define FIXED_CHARACTER_ERROR         0x27  //固定字符错误
+#define UPDATA_DATA_SUCCESS           0x28  //升级包接收正确
+#define UPDATA_TOTAL_TIMEOUT          0x29  //升级总时间超时
+#define UPDATA_SUCCESS                0x2A  //升级成功
+#define UPDATA_BACK                   0x2B  //回退
+
+
+#define UPDATE_SLAVE 0x5AA5
+enum {
+    UP_PROG_FROM_NET = 0x22, // 来源来网络
+	UP_PROG_FROM_GAT = 0x44, //来源来网关
+};
+
+#define OTA_UPDATE_BOOTROM_FLASH_START_ADDR  (0x08000000)                                                          //
+
+#define OTA_UPDATE_PT_FLASH_SIZE        (0x8000)                                                             //
+#define OTA_UPDATE_PT_FLASH_START_ADDR  (0x08008000)                                                          //
+#define OTA_UPDATE_PT_FLASH_END_ADDR    (OTA_UPDATE_PT_FLASH_START_ADDR+OTA_UPDATE_PT_FLASH_SIZE-1)
+
+
+#define OTA_UPDATE_APP1_FLASH_SIZE        (0x18000)                                                             //
+#define OTA_UPDATE_APP1_FLASH_START_ADDR  (0x08018000)                                                          //
+#define OTA_UPDATE_APP1_FLASH_END_ADDR    (OTA_UPDATE_APP1_FLASH_START_ADDR+OTA_UPDATE_APP1_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_APP2_FLASH_SIZE        (0x18000)                                                             //
+#define OTA_UPDATE_APP2_FLASH_START_ADDR  (0x08030000)                                                          //
+#define OTA_UPDATE_APP2_FLASH_END_ADDR    (OTA_UPDATE_APP2_FLASH_START_ADDR+OTA_UPDATE_APP2_FLASH_SIZE-1)       //
+
+#define OTA_UPDATE_APP3_FLASH_SIZE        (0x18000)                                                             //
+#define OTA_UPDATE_APP3_FLASH_START_ADDR  (0x08048000)                                                          //
+#define OTA_UPDATE_APP3_FLASH_END_ADDR    (OTA_UPDATE_APP3_FLASH_START_ADDR+OTA_UPDATE_APP3_FLASH_SIZE-1)       //
+
+
+typedef struct _UPDATE_DATA_{
+    uint16_t updateCode; // 升级状态码,
+    uint8_t bResetUpdate;  // 升级完成后,需要上报升级的状态(包含从设备通过485上报,或是主设备通过4G上报)
+    uint8_t bReadUpdateCode; // 可以允许读取升级状态码了
+    uint16_t taskNo;         // 升级任务号
+    uint8_t bupdateFinish; // 升级是否完成
+    uint8_t brcvCmd0x16; // 收到16指令
+    uint8_t Work_State; // 当前升级状态
+    uint8_t bRetransmit;  // 是否允许重传 1:不允许, 0:允许
+	uint8_t iDentity; //升级时的身份(下发设备或被升级设备)
+	uint8_t retransmit_s;//是否发送了重传指令
+	uint8_t ResetUpdate_s;//是否需要上报升级状态
+	uint8_t Update_Source;//升级来源
+	uint16_t bUpdate_slave;//是否需要升级从设备
+	uint8_t bOffline_s;	//是否开始离线升级
+	uint32_t bOffline_addr; //离线升级首地址
+	uint8_t bfirmware_type;//升级的固件类型
+}__attribute__((packed))UpdateDa;
+extern UpdateDa g_updateDa;
+
+#define OTA_TIM_ONLOOKER 5000 // 旁观都 5S
+#define OTA_TIM_TOTALTMR (60000*5) // 升级总定时器
+#define OTA_TIM_REPEAT   (60*1000) // 重传定时器10S
+#define OTA_TIM_REPEAR_MASTER (10*1000) //重传定时器(主设备)
+//#define OTA_TIM_REPEAR_SLAVE_FAST (rand()%100+300) //重传定时器快(从设备)
+//#define OTA_TIM_REPEAR_SLAVE_SLOW (rand()%100+500) //重传定时器慢
+#define OTA_TIM_CONTINUE  3000   // 连续接收时间 3S
+enum {
+    OTA_TIMER_NULL = 0x00,
+    OTA_TIMER_START = 0x01,
+    OTA_TIMER_END   = 0x02,
+};
+typedef struct _ota_update_time_set_{
+    timeout_t timer;
+    uint8_t status;
+}__attribute__((packed))otaTimeSet;
+
+typedef struct _ota_update_time_{
+    otaTimeSet totalTmr;  // 升级总时间
+    otaTimeSet continueTmr; // 连续接收时间
+    otaTimeSet repeatTmr;  // 重传时间
+    otaTimeSet onlookerTmr; // 旁观者时间
+    otaTimeSet randomTmr;   // 随机定时器
+    otaTimeSet upstatusTmr; // 读取状态时间
+	otaTimeSet repeatRandomTmr;//重传随机时间
+}__attribute__((packed))OtaUpdateTime;
+extern OtaUpdateTime g_otaTimer;
+
+/*-----------------------------------------------升级标记----------------------------------*/
+#define UPDATE_FLAG  0x81   // 升级标志
+#define UPDATE_SUCCESS_FLAG 0x82   // 升级成功标志
+#define BACKOFF_OVER 0x83   // 回滚成功
+/*---------------------------------------------升级协议开始-------------------------------------*/
+
+enum {
+    OTA_UPDATE_NULL     = 0x00, // 默认状态
+    OTA_UPDATE_ONLOOKER = 0x01, // 旁观者模式
+    OTA_UPDATE_BEGIN = 0x02, // 启动升级
+    OTA_UPDATE_CONTINUE = 0x03, // 连续续传模式
+    OTA_UPDATE_REPEAT   = 0x04, // 重传模式
+    OTA_UPDATE_RCVEND   = 0x05, // 升级包接收完成
+    OTA_UPDATE_CONTINUE_END = 0x06, // 连续包结束
+    OTA_UPDATE_REPEAT_END  = 0x07, // 重传包结束
+};
+typedef struct _ota_update_msg_{
+    uint16_t rcvDevType;    // 接收设备类型
+    uint32_t rcvDevSn;      // 接收设备SN
+    uint16_t desDevType;    // 升级目标设备类型
+    uint32_t desDevSn;      // 升级目标设备SN
+    uint8_t  firmType;      // 固件类型
+    uint32_t version;       // 升级版本号
+    uint32_t totalByte;     // 升级总总长度
+    uint16_t eachMaxByte;   // 单包最大字节类
+    uint16_t losePage;      // 最大丢包百分比 最小为10%,最大为60%
+	uint16_t loseTotalPage;	// 最大丢包个数
+    uint16_t sendInterval;  // 连续阶段发 送包的时间间隔(单位:ms)
+    uint16_t totalPage;     // 升级包总个数
+    uint16_t subPkgId;      // 升级包编号
+    uint16_t subPkgLen;     // 本升级包的长度
+    uint8_t  losePkgNum;    // 丢包的个数
+    uint16_t lastRightPkgNum;
+    uint16_t lossPkgId[250];
+    uint8_t  retransLossPkts;  //重传丢包个数
+    uint8_t lossPkgIndex;
+}__attribute__((packed))otaUpdatMsg;
+
+typedef struct _update_cmd_0x1003_{ // 启动升级下行
+    uint16_t rcvDevType;    // 接收设备类型
+    uint32_t rcvDevSn;      // 接收设备SN
+    uint16_t desDevType;    // 升级目标设备类型
+    uint32_t desDevSn;      // 升级目标设备SN
+    uint8_t  firmType;      // 固件类型
+    uint32_t updateVer;     // 升级包版本
+    uint32_t totalByte;     // 升级总总长度
+    uint16_t eachMaxByte;   // 单包最大字节类
+    uint16_t losePage;      // 最大丢包面分比 最小为10%,最大为60%
+    uint16_t sendInterval;  // 连续阶段发 送包的时间间隔(单位:ms)
+}__attribute__((packed))updateCmd0x1003;
+
+typedef struct _update_cmd_0x1004_{ // 连续包下行
+    uint16_t rcvDevType;    // 接收设备类型
+    uint32_t rcvDevSn;      // 接收设备SN
+    uint16_t desDevType;    // 升级目标设备类型
+    uint32_t desDevSn;      // 升级目标设备SN
+    uint16_t totalPage;     // 升级包总个数
+    uint16_t subPkgId;      // 升级包编号
+    uint16_t subPkgLen;     // 本升级包的长度
+}__attribute__((packed))updateCmd0x1004;
+
+typedef struct _update_cmd_0x1005_{ // 重传包
+    uint16_t rcvDevType;    // 接收设备类型
+    uint32_t rcvDevSn;      // 接收设备SN
+    uint16_t desDevType;    // 升级目标设备类型
+    uint32_t desDevSn;      // 升级目标设备SN
+    uint16_t totalPage;     // 升级包总个数
+    uint16_t subPkgId;      // 升级包编号
+    uint16_t subPkgLen;     // 本升级包的长度
+}__attribute__((packed))updateCmd0x1005;
+
+typedef struct _update_cmd_0x2005_{ // 重传包请求上行
+    uint16_t slaveDevType;
+    uint32_t slaveDevSn;
+    uint16_t repDevType;    // 发起请求的设备类型
+    uint32_t repDevSn;      // 发起请求的设备SN
+    uint16_t repPkgId;      // 升级包编号
+}__attribute__((packed))updateCmd0x2005;
+
+typedef struct _update_cmd_0x1006_{ // 离线升级指令
+    uint16_t masterDevType;     // 主设备类型
+    uint32_t masterDevSn;       // 主设备SN
+    uint16_t slaveDevType;      // 从设备类型
+    uint32_t slaveDevSn;        // 从设备SN
+    uint16_t desDevType;        // 升级目标设备类型
+    uint32_t desDevSn;          // 升级目标设备SN
+    uint8_t  firmType;          // 固件类型
+    uint32_t reserve;           // 预留
+}__attribute__((packed))updateCmd0x1006;
+
+typedef struct _update_cmd_0x1007_{ // 升级状态读取下行
+    uint16_t rcvDevType;        // 接收设备类型
+    uint32_t rcvDevSn;          // 接收设备SN
+    uint16_t pointDevType;      // 指定读取的设备类型
+    uint32_t pointDevSn;        // 指定读取的设备SN
+    uint32_t reserve;           // 预留
+}__attribute__((packed))updateCmd0x1007;
+
+typedef struct _update_cmd_0x2007_{ // 升级状态读取上行
+    uint16_t slaveDevType;      // 从设备类型
+    uint32_t slaveDevSn;        // 从设备SN
+    uint16_t desDevType;        // 升级目标设备类型
+    uint32_t desDevSn;          // 升级目标设备SN
+    uint32_t bootVer;           // 升级目标bootloader版本
+    uint32_t ptVer;             // 升级目标的产测版本
+    uint32_t appVer;            // 升级目标的app版本
+    uint8_t updateCode;         // 升级状态码
+    uint32_t reserve;         // 预留
+}__attribute__((packed))updateCmd0x2007;
+
+#define OTA_START_INFO_LEN      sizeof(updateCmd0x1003)
+#define OTA_CONTINUES_INFO_LEN  sizeof(updateCmd0x1004)
+#define OTA_RETRNSMIT_INFO_LEN  sizeof(updateCmd0x1005)
+#define OTA_MASTER_SEND_PKG_SIZE 128 // 主下发每包的大小
+/*---------------------------------------------升级协议结束-------------------------------------*/
+
+extern void ota_repeat_rand_timer(uint8_t status);
+extern void ota_update_master_retransmit(uint8_t *data);
+extern void ota_timer_stop(otaTimeSet *timer);
+extern void set_start_ota_timer(otaTimeSet *timer, uint32_t delay);
+extern void ota_power_up_read_update_status(void);
+extern void ota_update_slave_task(uint16_t cmd, uint8_t *data, uint8_t len);
+extern void ota_check_update_timer(void);
+extern void ota_update_deal_upstatus(void);
+extern void ota_update_slave_continue_end(uint8_t workMode);
+
+extern void ota_master_init_update_msg_offline(uint16_t rcvdevtype,uint32_t rcvdevsn,uint16_t desdevtype,uint32_t desdevsn,uint8_t firmtype);
+extern uint8_t ota_offline_init(uint32_t addr,uint32_t len);
+extern void ota_offline_proc(void);
+extern void ota_offline_handle(void);
+extern void ota_update_slave_offline(uint8_t *data,uint8_t len);
+extern void master_update_status_rcv(uint8_t *data, uint32_t len);
+extern void ota_start_offline_update(void);
+
+#endif

+ 653 - 0
App/public.c

@@ -0,0 +1,653 @@
+#include "public.h"
+#include <string.h>
+#include "../Hardware/boardinit.h"
+#include "ota_update.h"
+#include "gd32f10x.h"
+#include "masterslave.h"
+typedef  void (*otafun)(void);				//定义一个函数类型的参数.
+otafun jump2_pt_app;
+
+
+DevMsg g_devMsg;
+DevFirmMsg g_devfirmMsg;
+nodeRun_t g_runNode;
+DevAppVersion g_devAppVer;
+LogMsg g_logMsg; // 日志
+
+
+sysCmd1027 g_table1027;
+sysCmd1027 g_temtable1027; // 临时表
+
+
+uint8_t g_bhavePrice = 0; // 是否有单价屏 0:没有单价屏 , 1:有单价屏
+
+void init_dev_msg(void)
+{
+    g_devMsg.devType = DEV_TYPE;
+    g_devMsg.devSn = 0x08;
+
+
+}
+
+/*---------------------------------------------------------------------------------
+ *  上电读取UUID
+ * ---------------------------------------------------------------------------------*/
+void power_up_read_uuid(void)
+{
+    memcpy(g_devfirmMsg.uuid,(uint8_t*)(0x1FFFF7E8),12);
+}
+
+void printf_dev_msg(void)
+{
+    uint8_t i = 0;
+    g_devResetMsg.resetflag = power_up_system_resettype(); // 读取上电的复位类型
+    power_up_read_uuid();
+    printf("dev_type:0x%04x\r\n",g_devMsg.devType);
+    printf("dev_sn  :%010u\r\n",g_devMsg.devSn);
+    printf("app1Ver :%08x\r\n",g_devAppVer.app1Ver);
+    printf("app2Ver :%08x\r\n",g_devAppVer.app2Ver);
+    printf("app3Ver :%08x\r\n",g_devAppVer.app3Ver);
+    printf("bootVer :%08x\r\n",g_devAppVer.bootVer);
+    printf("ptVer   :%08x\r\n",g_devAppVer.ptVer);
+    printf("resetnum: %u\r\n",g_devResetMsg.resetNum);
+    printf("work_mode: %d\r\n",g_devMsg.workMode);
+    printf("timer   : %u\r\n",rtc_counter_get());
+    printf("uuid            = ");
+    for(i=0;i<12;i++){
+        printf("%02x ",g_devfirmMsg.uuid[i]);
+    }
+    printf("\r\n");
+
+}
+
+/*-----------------------------------------------------------------------------
+ * 检查设备类型以及SN是否是设备本身的
+ *  返回值 1: 本设备  0: 错误
+ * ----------------------------------------------------------------------------*/
+uint8_t check_dev_type_sn(uint16_t devType, uint32_t devSn)
+{
+    if(devType == g_devMsg.devType){
+        if(devSn == g_devMsg.devSn) return 1;
+        else if(0xFFFFFFFF == devSn) return 1;
+        else return 0;
+    }
+    else return 0;
+}
+uint8_t check_dev_type_sn01(uint16_t devType, uint32_t devSn)
+{
+    if(devType==g_devMsg.devType && devSn==g_devMsg.devSn) return 1;
+    else if((0xFFFFFFFF == devSn) && (0xFFFF ==devType) ) return 1;
+    else if(0xFFFF == devType){
+        if(devSn==g_devMsg.devSn) return 1;
+        else return 0;
+    }
+    else if(0xFFFFFFFF == devSn) {
+        if(devType == g_devMsg.devType) return 1;
+        else return 0;
+    }
+    else return 0;
+
+}
+/*--------------------------------------------------------------------------------
+ *  crc_16 校验
+ * -------------------------------------------------------------------------------*/
+uint16_t crc16_get(uint8_t *data, uint8_t size)
+{
+    uint16_t crc=0;
+    int i;
+    for(i = 0; i < size; i++)
+    {
+        crc += data[i];
+    }
+    return crc;
+}
+uint16_t _crc16_get(uint8_t *_buff,uint32_t _len)
+{
+    uint32_t i,j;
+    uint16_t crc;
+    uint16_t temp;
+
+    crc=(uint16_t)CRC_INIT_VALUE;
+    for(i=0;i<_len;i++) {
+        temp=_buff[i];
+        temp &=0x00FF;
+        crc^=temp;
+
+        for(j=0;j<8;j++) {
+            if((crc&0x0001)!=0x00) {
+                crc>>=1;
+                crc^=0xA001;
+            } else {
+                crc>>=1;
+            }
+        }
+    }
+
+    return crc;
+}
+/*--------------------------------------------------------------------------------
+ *  转义
+ * 帧中除了帧头为 BB 外,不再出现 BB,如果出现 BB 则转义为
+    BA 01;如果出现 BA 则转义为 BA 00;帧长度和校验码都按转义前
+    来计算。
+ * -------------------------------------------------------------------------------*/
+int _ytsf_data_code(uint8_t *buff, uint8_t *len)
+{
+    uint8_t buff_code[128];
+    uint8_t i, tlen = 0;
+
+    for(i = 0;i < *len; i ++){
+        if(buff[i] == 0xba){
+            buff_code[tlen++] = 0xba;
+            buff_code[tlen++] = 0x00;
+        } else if(i&&buff[i] == 0xbb){
+            buff_code[tlen++] = 0xba;
+            buff_code[tlen++] = 0x01;
+        }
+        else{
+            buff_code[tlen++] = buff[i];
+        }
+    }
+    memcpy(buff, buff_code, tlen);
+    *len = tlen;
+    return 0;
+}
+/*--------------------------------------------------------------------------------
+ *  反转义
+ * 帧中除了帧头为 BB 外,不再出现 BB,如果出现 BB 则转义为
+    BA 01;如果出现 BA 则转义为 BA 00;帧长度和校验码都按转义前
+    来计算。
+ * -------------------------------------------------------------------------------*/
+int _ytsf_data_decode(uint8_t *buff, uint8_t *len)
+{
+    uint8_t buff_code[128];
+    uint8_t i, tlen = 0;
+
+    for(i = 0;i < *len; i ++){
+        if((buff[i] == 0xba)&&(buff[i+1] == 0x00)) {
+            buff_code[tlen++] = 0xba;
+            i += 1;
+        } else if((buff[i] == 0xba)&&(buff[i+1] == 0x01)){
+            buff_code[tlen++] = 0xbb;
+            i += 1;
+        }
+        else{
+        buff_code[tlen++] = buff[i];
+        }
+    }
+    memcpy(buff, buff_code, tlen);
+    *len = tlen;
+
+    return 0;
+}
+/*---------------------------------------------------------------------------
+ * 设置升级标志(设置标记高位取反)
+ * 将一个数设置为高八位是第八位的取反
+ * --------------------------------------------------------------------------*/
+uint16_t set_updata_state(uint16_t data)
+{
+    uint16_t temp_data,ret_data = 0;
+    uint16_t temp_h,temp_l;
+    temp_data = data;
+    temp_h = ((~temp_data)<<8)&0xff00;
+    temp_l = temp_data&0x00ff;
+    ret_data = temp_h | temp_l;
+    return ret_data;
+}
+/*-------------------------------------------------------------------------------
+ * 判断升级标志的本体和掩码
+ * 标记高位取反判断
+ * ------------------------------------------------------------------------------*/
+uint8_t updata_state_cmp(uint16_t data)
+{
+    uint8_t ret = 0;
+    uint16_t temp_data;
+    uint8_t temp_h,temp_l;
+    temp_data = data;
+    temp_h = (uint8_t)((temp_data&0xff00)>>8);
+    temp_l = (uint8_t)(temp_data&0x00ff);
+    if((temp_h^temp_l) == 0xff)
+    {
+        ret = 1;
+    }
+    return ret;
+}
+
+
+/*------------------------------------------------------------------------------------------
+ *对app进行校验
+ *参数:addr:app首地址
+ *         len: app长度
+ *         checkdata:计算的crc值
+ *返回:0:校验正确,1:校验失败
+*-------------------------------------------------------------------------------------------*/
+void app_check_crc(uint32_t addr, uint32_t len, uint32_t *checkdata)
+{
+    uint32_t datalen,read_crc,get_crc;
+    datalen = Flash_DatalenRead(addr,len);
+    read_crc = *(uint32_t*)(addr + datalen-4); //CRC校验
+
+    rcu_periph_clock_enable(RCU_CRC);           //打开crc时钟
+    crc_data_register_reset();                   //复位crc数据寄存器
+    get_crc = crc_block_data_calculate((uint32_t*)addr,(datalen -4)/4);//计算crc数值
+    rcu_periph_clock_disable(RCU_CRC);            //关闭crc时钟
+
+    *checkdata = get_crc;
+    if(read_crc != get_crc)
+    {
+        return; //ret = 1;
+    }
+    return;// ret;
+}
+
+/*--------------------------------------------------------------------------
+ *  读取复位次数
+ * -------------------------------------------------------------------------*/
+void epprom_read_reset_num(void)
+{
+    uint32_t resetnum = 0;
+    epprom_read(DEV_RESET_NUM,(uint8_t*)&resetnum,4);
+    g_devResetMsg.resetNum = resetnum;
+}
+
+/*----------------------------------------------------------------------------
+ *  初始化、读取 、 写入 路由表到EPPROm中
+ * ---------------------------------------------------------------------------*/
+void epprom_init_config_table(void)
+{
+    uint8_t buff[128] = {0};
+
+    g_runNode.slaveNum = 0x00;
+    memset(g_runNode.nodMsg,0,sizeof(nodeMsg_t));
+    epprom_write((uint32_t)CONFIGTABLE_ADDR,buff,128);
+}
+void epprom_read_config_table(void)
+{
+    uint8_t buff[128] = {0},len,i;
+    uint8_t *pbuff = buff;
+    nodeMsg_t *pNode = NULL;
+
+    epprom_read((uint32_t)CONFIGTABLE_ADDR,&g_runNode.slaveNum,1); // 读取从设备的个数
+    printf("config_table_num = %d\r\n",g_runNode.slaveNum);
+    if(g_runNode.slaveNum >16) return;
+    len = g_runNode.slaveNum*8+1;
+
+    epprom_read((uint32_t)CONFIGTABLE_ADDR,buff,len);
+
+    pbuff++;
+    for(i=0;i<g_runNode.slaveNum;i++){
+        pNode = &g_runNode.nodMsg[i];
+        pNode->devType = *(uint16_t*)pbuff;
+        pbuff += 2;
+        pNode->devSn = *(uint32_t*)pbuff;
+        pbuff += 4;
+        pbuff += 2; // 预留
+        if((pNode->devType == g_devMsg.devType) &&(pNode->devSn == g_devMsg.devSn))
+            pNode->bSelf = 1;
+        else pNode->bSelf = 0;
+        pNode->status = 0;
+        pNode->readCount = 0;
+        printf("slave_table type = %04x, sn = %010u bself=%d\r\n",pNode->devType,pNode->devSn,pNode->bSelf);
+    }
+}
+void epprom_write_config_table(uint8_t *data, uint8_t len)
+{
+    epprom_write((uint32_t)CONFIGTABLE_ADDR,data,len);
+}
+/*-----------------------------------------------------------------------------------------
+ *  com 端的配置文件的初始化 读取 写入
+ * ----------------------------------------------------------------------------------------*/
+void epprom_init_com_config(void)
+{
+
+}
+void epprom_read_com_config(void)
+{
+    uint8_t buff[128] = {0},len,group = 0;
+    uint8_t portIndex,pinIndex,i=0;
+    sysCmd1026 *msg = (sysCmd1026*)buff;
+    len = sizeof(sysCmd1026);
+
+    epprom_read((uint32_t)COMM_CONFIG_ADDR,buff,len);
+    if(msg->comGroup>=4) msg->comGroup = 3;
+    group    = msg->comGroup;
+    g_extimsg.groupNum = group;
+    printf("group = %d\n",group);
+    if((msg->confFileNum[0] == 'H')&&(msg->confFileNum[1]=='Y')){
+        printf("配置文件:HY\n");
+        g_devMsg.bHYdev = 0x01;
+    }
+    else {
+        g_devMsg.bHYdev = 0x00;
+    }
+    init_test_coll_data_info(1);
+#if (1)
+    g_devMsg.bhavePrice = msg->priceInuseCout;
+    for(i=0;i<group;i++){
+        portIndex = msg->param[i][2];
+        if((3==portIndex) ||(4==portIndex)) {
+            g_extimsg.csGroup[i] = GPIOA + (msg->param[i][0]*0x400);
+            g_extimsg.csPin[i] = BIT(msg->param[i][1]);
+//            switch(portIndex){
+//            case 3:
+//                g_extimsg.extiPort = GPIOD;
+//                g_extimsg.outputPort = GPIO_PORT_SOURCE_GPIOD;
+//                break;
+//            case 4:
+//                g_extimsg.extiPort = GPIOE;
+//                g_extimsg.outputPort = GPIO_PORT_SOURCE_GPIOE;
+//                break;
+//            default:
+//                g_extimsg.extiPort = GPIOD;
+//                g_extimsg.outputPort = GPIO_PORT_SOURCE_GPIOD;
+//                break;
+//            }
+            pinIndex = msg->param[i][3];
+//            g_extimsg.extiLine = BIT(pinIndex);
+//            g_extimsg.extiPin = BIT(pinIndex);
+//            g_extimsg.extiPinSource = GPIO_PIN_SOURCE_0 + pinIndex;
+//            if(pinIndex>=5 && pinIndex<=9) {
+//                g_extimsg.extiIRQn = EXTI5_9_IRQn;
+//            }
+//            else if(pinIndex == 0){
+//                g_extimsg.extiIRQn = EXTI0_IRQn;
+//            }
+//            else if((pinIndex==14) || (pinIndex == 15 )){
+//                g_extimsg.extiIRQn = EXTI10_15_IRQn;
+//            }
+            printf("com config msg csport = %d, cspin= %d,extipt = %d, extipin=%d\r\n",msg->param[i][0],\
+                msg->param[i][1],portIndex,pinIndex);
+        }
+        else {
+            g_extimsg.csGroup[i] = GPIOB;
+            g_extimsg.csPin[i]   = GPIO_PIN_9;
+//            g_extimsg.extiPin  = GPIO_PIN_6;
+//            g_extimsg.extiPort  = GPIOD;
+//            g_extimsg.extiIRQn = EXTI5_9_IRQn;
+//            g_extimsg.extiLine = EXTI_6;
+//            g_extimsg.extiPinSource = GPIO_PIN_SOURCE_6;
+//            g_extimsg.outputPort = GPIO_PORT_SOURCE_GPIOD;
+            msg->param[i][1] = 9;
+            msg->param[i][3] = 6;//
+            printf("  com config msg default:cs:pb,cspin:9,ad:pd,adpin:6\r\n");
+        }
+
+        if(msg->param[i][3] >=8) g_extimsg.comPin[i] = msg->param[i][3] - 8;
+        else g_extimsg.comPin[i] = msg->param[i][3];
+        g_extimsg.csPin[i]  = msg->param[i][1]; //9;//
+        if(g_extimsg.csGroup[i] == GPIOB) {
+            switch (g_extimsg.csPin[i]) {
+            case 9: g_extimsg.comPort[i] = 14; break; // CS_U_2
+            case 8: g_extimsg.comPort[i] = 15; break; // CS_U_3
+            case 7: g_extimsg.comPort[i] = 16; break; // CS_U_4
+            case 6: g_extimsg.comPort[i] = 17; break; // CS_U_5
+            case 5: g_extimsg.comPort[i] = 18; break; // CS_U_6
+
+            case 15: g_extimsg.comPort[i] = 0; break; // CS_D_0
+            case 14: g_extimsg.comPort[i] = 1; break; // CS_D_1
+            case 13: g_extimsg.comPort[i] = 2; break; // CS_D_2
+            case 12: g_extimsg.comPort[i] = 3; break; // CS_D_3
+            case 1 : g_extimsg.comPort[i] = 5; break; // CS_D_5
+            case 0 : g_extimsg.comPort[i] = 6; break; // CS_D_6
+            }
+        }
+        else if(g_extimsg.csGroup[i] == GPIOA) {
+            switch (g_extimsg.csPin[i]){
+            case 12: g_extimsg.comPort[i] = 22; break; // CS_U_10
+            case 11: g_extimsg.comPort[i] = 23; break; // CS_U_11
+
+            case 7: g_extimsg.comPort[i] = 9; break;  // CS_D_9
+            case 6: g_extimsg.comPort[i] = 10; break; // CS_D_10
+            case 5: g_extimsg.comPort[i] = 11; break; // CS_D_11
+            }
+        }
+        else if(g_extimsg.csGroup[i] == GPIOC) {
+            switch (g_extimsg.csPin[i]){
+            case 12: g_extimsg.comPort[i] = 19; break; // CS_U_7
+            case 11: g_extimsg.comPort[i] = 20; break; // CS_U_8
+            case 10: g_extimsg.comPort[i] = 21; break; // CS_U_9
+
+            case 5 : g_extimsg.comPort[i] = 7; break; // CS_D_7
+            case 4 : g_extimsg.comPort[i] = 8; break; // CS_D_8
+            }
+        }
+        else if(g_extimsg.csGroup[i] == GPIOD) {
+
+        }
+        else if(g_extimsg.csGroup[i] == GPIOE) {
+            switch (g_extimsg.csPin[i]) {
+            case 1: g_extimsg.comPort[i] = 12; break; // CS_U_0
+            case 0: g_extimsg.comPort[i] = 13; break; // CS_U_1
+
+            case 7 : g_extimsg.comPort[i] = 4; break; // CS_D_4
+            }
+        }
+
+        printf("comPort = %d, comPin = %d\n",g_extimsg.comPort[i],g_extimsg.comPin[i]);
+    }
+#else // 用于串转并时的芯片,74CH165
+    portIndex = msg->param[0][2];
+    if((3==portIndex) ||(4==portIndex)) {
+        switch(portIndex){
+        case 3:
+            g_extimsg.csGroup = GPIOD; break;
+        case 4:
+            g_extimsg.csGroup = GPIOE; break;
+        default:
+            g_extimsg.csGroup = GPIOD; break;
+        }
+        g_extimsg.outputPort = portIndex;
+        pinIndex = msg->param[0][3];
+        g_extimsg.csPin = BIT(pinIndex);
+        g_extimsg.extiLine = BIT(pinIndex);
+        g_extimsg.extiPin = BIT(pinIndex);
+        g_extimsg.extiPinSource = pinIndex;
+        if(pinIndex>=5 && pinIndex<=9) {
+            g_extimsg.extiIRQn = EXTI5_9_IRQn;
+        }
+        printf("  com config msg port = %d, pin=%d\r\n",portIndex,pinIndex);
+    }
+    else {
+        g_extimsg.csGroup = GPIOD;
+        g_extimsg.csPin   = GPIO_PIN_6;
+        g_extimsg.extiIRQn = EXTI5_9_IRQn;
+        g_extimsg.extiLine = EXTI_6;
+        g_extimsg.extiPinSource = GPIO_PIN_SOURCE_6;
+        g_extimsg.extiPin  = GPIO_PIN_6;
+        g_extimsg.outputPort = 3;
+        printf("  com config msg default\r\n");
+    }
+#endif
+}
+void epprom_write_com_config(uint8_t *data, uint8_t len)
+{
+    epprom_write((uint32_t)COMM_CONFIG_ADDR,data,len);
+}
+/*-----------------------------------------------------------------------------------------
+ *  探针板的管脚的配置文件的初始化 读取 写入
+ * ----------------------------------------------------------------------------------------*/
+void epprom_init_pin_config(void)
+{
+    memset(&g_table1027,0,sizeof(sysCmd1027));
+}
+void epprom_read_pin_config(void)
+{
+    g_bhavePrice = 0;
+
+    epprom_read((uint32_t)PIN_CONFIG_ADDR,(uint8_t*)&g_table1027,sizeof(sysCmd1027));
+    if(g_table1027.groupNum<97) g_bhavePrice = 0;
+    else g_bhavePrice = 1;
+
+    if((g_table1027.confFileNum[0] == 'H') && (g_table1027.confFileNum[1] == 'Y')){
+        g_devMsg.bHYdev = 0x01; // 根据配置文件判断是否是鸿洋显示屏
+    }
+    else g_devMsg.bHYdev = 0x00;
+    init_test_coll_data_info(1);
+    printf("table msg pointDev = 0x%04x,group = %d,bhaveprice = %d\r\n",g_table1027.appointDevModel,g_table1027.groupNum,g_bhavePrice);
+}
+void epprom_write_pin_config(uint8_t *data, uint16_t len)
+{
+    epprom_write((uint32_t)PIN_CONFIG_ADDR,data,len);
+}
+/*-----------------------------------------------------------------
+ *  读取设备的基本信息
+ * ----------------------------------------------------------------*/
+void epprom_read_dev_app_version(void)
+{
+    epprom_read((uint32_t)DEV_APP_VER,(uint8_t*)&g_devAppVer,sizeof(DevAppVersion));
+    if(g_devAppVer.app1Ver != APP_VERSION){
+        g_devAppVer.app1Ver = APP_VERSION;
+        epprom_write((uint32_t)DEV_APP_VER,(uint8_t*)&g_devAppVer,sizeof(DevAppVersion));
+    }
+}
+
+/*----------------------------------------------------
+ *  工作模式
+ * ----------------------------------------------------*/
+void reset_work_mode(void)
+{
+    if(g_devPtMsg.binit == 0x01){
+        g_devMsg.workMode = WORK_NORMAL;
+        g_devMsg.ledgreen = 1;
+        g_devMsg.ledred = 0;
+    }
+    else{
+        g_devMsg.ledgreen = 3;
+        g_devMsg.ledred = 1;
+        g_devMsg.workMode = WORK_NOINIT;
+    }
+}
+
+/*------------------------------------------------------------------------------------------
+ *  上电读取设备类型
+ * -----------------------------------------------------------------------------------------*/
+void epprom_power_up_deal(void)
+{
+    uint8_t num = 0;
+    epprom_read_dev_app_version();
+
+    num = (g_devAppVer.app1Ver&0x03);
+    g_devMsg.ledred = (num == 0) ? 4: num;
+    g_devMsg.ledgreen = 4;
+
+    epprom_read_reset_num();
+    //epprom_read_config_table(); // 上电时不需要读取路由表,收到是主的身份时再读取
+    epprom_read_pin_config();
+
+    start_delay_ms(3000);
+    do{
+        if((g_devMsg.ledgreen == 0x06)) break;
+    }while(!g_iDelayfinish);
+    stop_delay_ms();
+    epprom_read(0,(uint8_t*)&g_devPtMsg,sizeof(DevPtMsg));
+    if(g_devPtMsg.binit == 0x01){
+        g_devMsg.workMode = WORK_NORMAL;
+        g_devMsg.ledgreen = 1;
+        g_devMsg.ledred = 0;
+    }
+    else{
+        g_devMsg.ledgreen = 3;
+        g_devMsg.ledred = 1;
+        g_devMsg.workMode = WORK_NOINIT;
+    }
+
+    g_devMsg.devType = DEV_TYPE;// g_devPtMsg.devType1;
+    g_devMsg.devSn   = g_devPtMsg.devSn;
+
+
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//设置栈顶地址
+__asm void MSR_MSP(u32 addr)
+{
+    MSR MSP, r0 			//set Main Stack value
+    MSR PSP, r0 			//set Main Stack value
+    BX r14
+}
+
+
+//THUMB指令不支持汇编内联
+//采用如下方法实现执行汇编指令WFI
+void WFI_SET(void)
+{
+    __ASM volatile("wfi");
+}
+//关闭所有中断
+void INTX_DISABLE(void)
+{
+    __ASM volatile("cpsid i");
+}
+//开启所有中断
+void INTX_ENABLE(void)
+{
+    __ASM volatile("cpsie i");
+}
+
+
+typedef void (*usercode)(void);
+usercode EnterApp;
+
+//关中断
+void nvic_disable(void)
+{
+    int irq;
+    __disable_irq();
+    for (irq = RTC_IRQn; irq <= DMA1_Channel3_Channel4_IRQn; irq++)
+    {
+        NVIC_DisableIRQ(irq);
+        NVIC_ClearPendingIRQ(irq);
+    }
+}
+
+//运行pt
+uint32_t run_pt(void)
+{
+    uint32_t appxaddr=OTA_UPDATE_PT_FLASH_START_ADDR;//OTA_UPDATE_PT_FLASH_START_ADDR;
+
+    printf("jump to 0x%08X.\r\n",appxaddr);
+
+    if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.
+    {
+        nvic_disable();
+        INTX_DISABLE();
+
+        jump2_pt_app=(otafun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)
+        MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
+
+        gpio_deinit(GPIOB);
+        gpio_deinit(GPIOC);
+        jump2_pt_app();									//跳转到APP.
+        while(1);
+    }
+    else
+    {
+        printf("栈顶地址不合法\r\n");
+    }
+    return 0;
+}
+
+//产测处理
+void uart_pt_task(uint8_t *data,uint16_t len)
+{
+    if(strstr((char *)data,"AT+PTMOD=ON\r\n"))
+    {
+        run_pt();
+    }
+}
+
+//usart0接收解析
+void analysis_usart0_rx_fifo(void)
+{
+//    uint8_t readBuf[256],readlen;
+
+//    if(fifo_is_empty(&g_usart0rxfifo) == TRUE) return;
+//    readlen = fifo_read(&g_usart0rxfifo,readBuf);
+//        if(WORK_UPDATE != g_devMsg.workMode)//非升级模式
+//                uart_pt_task(readBuf,readlen);
+}
+
+
+

+ 138 - 0
App/public.h

@@ -0,0 +1,138 @@
+#ifndef _PUBLIC_H_
+#define _PUBLIC_H_
+
+#include "../User/gd32f10x_it.h"
+#include "../Hardware/boardinit.h"
+
+extern uint8_t g_bhavePrice;
+
+#define DEV_TYPE 0x0904
+#define APP_VERSION 0x0904302A
+
+
+#define BROADCAST_SN   0xFFFFFFFF // 广播地址
+#define BROADCAST_TYPE 0xFFFF     // 广播设备类型
+
+#define CRC_INIT_VALUE 0x0000
+
+
+
+enum { // workMode
+    WORK_NOINIT = 0x01,  // 未初始化模式
+    WORK_NORMAL = 0x02,  // 正常模式
+    WORK_UPDATE = 0x03,  // 升级模式
+
+};
+enum {
+    B4G_NOHAVE = 0x00, // 无4G模块
+    B4G_HAVE = 0x01,   // 有4G模块
+};
+typedef struct _dev_msg_{
+    uint16_t devType;   // 主设备类型
+    uint32_t devSn;     // 主设备SN
+    uint16_t devTypeS;  // 从设备类型
+    uint32_t devSnS;    // 从设备SN
+    uint8_t  bHave4G;   // 是否有4G模块
+    uint8_t  baskIdentity; // 是否询问自己的身份
+    uint8_t workMode;
+    uint8_t ledred; // 红灯状态
+    uint8_t ledgreen; //绿灯状态
+    uint8_t bhavePrice; // 是否用单价屏
+    uint8_t bHYdev;     // 是否是鸿洋的设备
+}__attribute__((packed))DevMsg;
+extern DevMsg g_devMsg;
+
+typedef struct _dev_firm_msg_{
+    uint32_t bootVer;   // bootloader版本
+    uint32_t ptVer;     // pt版本
+    uint32_t appVer;    // app版本
+    uint8_t uuid[12];   // UUID
+
+}__attribute__((packed))DevFirmMsg;
+extern DevFirmMsg g_devfirmMsg;
+
+enum {
+    LOG_TYPE_NULL = 0x00, // 默认类型
+    LOG_TYPE_7SEG = 0x01, // 错误去重七段码上报
+    LOG_TYPE_LOG  = 0x02, // 日志
+};
+
+typedef struct _log_msg_{
+    uint8_t blogOpen; // 日志是否打开 0:未打开, 1:打开
+    uint8_t logType; // 日志类型
+    timeout_t timer; // 超时计时器
+}LogMsg;
+extern LogMsg g_logMsg;
+
+#define NODE_MAX_SIZE 8
+#define OFF_LINE_COUNT  5 // 5次读取不到,则判断为离线
+typedef struct _node_msg_{
+    uint16_t devType;
+    uint32_t devSn;
+    uint8_t status;
+    uint8_t readCount; // 读取次数
+    uint8_t bSelf;     // 是自己的设备类型和SN
+}__attribute__((packed))nodeMsg_t;
+
+typedef struct _node_run_info_{
+    nodeMsg_t nodMsg[NODE_MAX_SIZE];
+    uint8_t nIndex;
+    uint8_t slaveNum; // 从的个数
+}__attribute__((packed))nodeRun_t;
+extern nodeRun_t g_runNode;
+
+
+typedef uint32_t  u32;
+typedef uint16_t u16;
+typedef uint8_t  u8;
+
+typedef const uint32_t uc32;  /*!< Read Only */
+typedef const uint16_t uc16;  /*!< Read Only */
+typedef const uint8_t uc8;   /*!< Read Only */
+
+typedef __IO uint32_t  vu32;
+typedef __IO uint16_t vu16;
+typedef __IO uint8_t  vu8;
+
+typedef __I uint32_t vuc32;  /*!< Read Only */
+typedef __I uint16_t vuc16;  /*!< Read Only */
+typedef __I uint8_t vuc8;   /*!< Read Only */
+
+
+
+extern void init_dev_msg(void);
+extern uint8_t check_dev_type_sn(uint16_t devType, uint32_t devSn);
+extern uint8_t check_dev_type_sn01(uint16_t devType, uint32_t devSn);
+extern uint16_t crc16_get(uint8_t *data, uint8_t size);
+extern uint16_t _crc16_get(uint8_t *_buff,uint32_t _len);
+extern int _ytsf_data_code(uint8_t *buff, uint8_t *len);
+extern int _ytsf_data_decode(uint8_t *buff, uint8_t *len);
+extern void printf_dev_msg(void);
+
+extern uint16_t set_updata_state(uint16_t data);
+extern uint8_t updata_state_cmp(uint16_t data);
+extern void app_check_crc(uint32_t addr, uint32_t len, uint32_t *checkdata);
+
+extern void epprom_read_reset_num(void);
+
+extern void epprom_init_config_table(void);
+extern void epprom_read_config_table(void);
+extern void epprom_write_config_table(uint8_t *data, uint8_t len);
+
+
+extern void epprom_init_com_config(void);
+extern void epprom_read_com_config(void);
+extern void epprom_write_com_config(uint8_t *data, uint8_t len);
+
+
+extern void epprom_init_pin_config(void);
+extern void epprom_read_pin_config(void);
+extern void epprom_write_pin_config(uint8_t *data, uint16_t len);
+
+
+extern void epprom_power_up_deal(void);
+
+
+extern void reset_work_mode(void);
+extern void uart_pt_task(uint8_t *data,uint16_t len);
+#endif

+ 205 - 0
App/taskOpt.c

@@ -0,0 +1,205 @@
+#include "taskOpt.h"
+#include "xspDataOpt.h"
+#include "masterslave.h"
+
+timeout_t g_upstatusTime; // 上报状态的时间
+timeout_t g_upfirmTime;  // 上报固件信息的时间
+
+taskRunData g_taskRunDa;
+/*----------------------------------------------------------------
+ *  上电读取20次 comm端,找出comm端一个电平的最小时间
+ * ---------------------------------------------------------------*/
+void power_up_read_comm_min_time(void)
+{
+#if(0)
+    volatile int i;
+    uint32_t minTick,maxTick,sum = 0;
+    uint8_t flag = 0;
+    //    return;
+    minTick=0xFFFFFFFF;
+    maxTick=0x00;
+
+    testcount.count = 0;
+    testcount.btestStart = 1;
+    exti_interrupt_enable(g_extimsg.extiLine);
+
+    gpio_bit_reset(g_extimsg.csGroup,g_extimsg.csPin);
+    start_delay_ms(2);
+    while(!g_iDelayfinish);
+
+
+    start_delay_ms(2000);
+
+    while(1){
+        if(testcount.count>21) {
+            gpio_bit_set(g_extimsg.csGroup,g_extimsg.csPin);
+            testcount.btestStart = 0;
+            break;
+        }
+        if(1 == g_iDelayfinish){
+            minTick = 0x00;
+            testcount.count = 1;
+            break;
+        }
+        if(testcount.count ==0){
+            if(timer_counter_read(TIMER5)>=300) {
+                printf("未检测到探针板插入\r\n");
+                flag =  1;
+                break;
+            }
+        }
+    }
+    stop_delay_ms();
+    testcount.wCount = 0;
+    if(flag == 0) {
+        for(i=0;i<testcount.count-1;i++){
+            if(testcount.exittest[i].status != testcount.exittest[i+1].status){
+                testcount.width[testcount.wCount++] = testcount.exittest[i+1].tick - testcount.exittest[i].tick;
+            }
+        }
+				printf("count = %d\n",testcount.wCount);
+        for(i=1;i<testcount.wCount;i++){
+            if(minTick>testcount.width[i]) minTick = testcount.width[i];
+            if(maxTick<testcount.width[i]) maxTick = testcount.width[i];
+            sum += testcount.width[i];
+            printf("%d ",testcount.width[i]);
+        }
+        printf("\n");
+        minTick = (sum - minTick - maxTick)/18;
+        g_timeInfo.delay = minTick/6;
+
+        
+    }
+
+
+    if(g_timeInfo.delay >200) g_timeInfo.delay = 150;
+    else if(g_timeInfo.delay ==0) g_timeInfo.delay = 150;
+    printf("maintick=%d,maxtick=%d,delay=%d\n",minTick,maxTick,g_timeInfo.delay);
+    gpio_bit_reset(g_extimsg.csGroup,g_extimsg.csPin);
+#endif
+}
+void init_run_data(void)
+{
+    //uint8_t i;
+    if(g_iDentity == IDENTITY_SLAVE) return;
+    timeout_setValue(&g_uart485.time,2000); // 发送延时
+    timeout_setValue(&g_upstatusTime,READ_STATUS_TIME); // 读取状态的时间
+    timeout_setValue(&g_upfirmTime,READ_FIRME_TIME); // 读取固件的时间
+    g_taskRunDa.breadstatus = 1;
+    g_taskRunDa.breadfirmmsg = 1;
+
+//    g_runNode.slaveNum = 2;
+//    g_runNode.nodMsg[0].devSn = 0x02;
+//    g_runNode.nodMsg[0].devType = DEV_TYPE;
+//    g_runNode.nodMsg[1].devSn = 0x03;
+//    g_runNode.nodMsg[1].devType = DEV_TYPE;
+//    for(i=0;i<g_runNode.slaveNum;i++){
+//        g_runNode.nodMsg[i].status = 1;
+//        g_runNode.nodMsg[i].readCount = 0;
+//    }
+
+}
+
+
+/*------------------------------------------------------------------------
+ *  主处理485的 发送fifo
+ *  用于服务器下发指令读取从的数据
+ *  没有数据发送时返回为1  有数据发送时,返回为0
+ * -----------------------------------------------------------------------*/
+uint8_t master_deal_485_tx_fifo(void)
+{
+    FIFO_T *fifo = &g_txfifo;
+    if(fifo_is_empty(fifo) == TRUE) return 1; // fifo为空时,退出
+    printf("发送485 tx fifo 中的数据\r\n");
+    usart_tx_dma_send(USART1,fifo->memory[fifo->front].da,fifo->memory[fifo->front].len);
+    fifo->memory[fifo->front].len = 0;
+    fifo->front++;
+    fifo->front %= MAXSIZE;
+    if (fifo->front == fifo->rear) // 设置队列为空
+        fifo->flag = FALSE;
+
+    return 0;
+}
+
+/*------------------------------------------------------------
+ *  判断配置文件是否过期
+ * -----------------------------------------------------------*/
+void config_file_is_timeout(void)
+{
+    if(1 == g_taskRunDa.bcfgfiletime) {
+        if(timeout_isOut(&g_taskRunDa.cfigFileTime)){
+            epprom_read_pin_config();
+            g_taskRunDa.bcfgfiletime = 0;
+        }
+    }
+}
+
+/*------------------------------------------------------------------------
+ *  主 从  解析485的接收fifo
+ * -----------------------------------------------------------------------*/
+void analysis_485_rx_fifo(void)
+{
+    uint8_t readBuf[256],readlen;
+    uint16_t crc,fcrc,randDa;
+    MasterSlave *msg = (MasterSlave*)readBuf;
+
+    if(fifo_is_empty(&g_rxfifo) == TRUE) return;
+    readlen = fifo_read(&g_rxfifo,readBuf);
+
+    if(0x01 == g_updateDa.bResetUpdate){
+        randDa = rand()%100 + 200;
+        printf("随机时间 = %d\r\n",randDa);
+        set_start_ota_timer(&g_otaTimer.randomTmr,randDa);
+    }
+    if(g_updateDa.Work_State == OTA_UPDATE_REPEAT && g_updateDa.retransmit_s == 0)//重传阶段
+    {
+        ota_repeat_rand_timer(1);//重传随机延时
+    }
+
+    if(msg->start != 0xfefe) {
+        uart_pt_task(readBuf,0); // 判断是否进入产测执行
+        return;
+    }
+//		printf("readlen = %d, msglne = %d\n",readlen,msg->palen);
+//		data_dump("aaaa",readBuf,readlen);
+    crc = _crc16_get(readBuf,msg->palen+COMM_HEAD_LEN-2);
+    fcrc = msg->comInfo.info[msg->palen-1];
+    fcrc = (fcrc<<8) | msg->comInfo.info[msg->palen-2];
+    if(fcrc != crc ) return;
+    if((0x2000 == (msg->msgType2&0x2000))) { // 要考虑离线升级和升级的指令????
+        if(WORK_UPDATE == g_devMsg.workMode){ // 升级模式
+            if(IDENTITY_SLAVE == g_iDentity) return; //
+        }
+        else {
+            if(B4G_NOHAVE== g_devMsg.bHave4G) {
+                return;
+            }
+            else {
+                if((g_devMsg.devSn != *(uint32_t*)&msg->comInfo.info[2]) \
+                   && (g_devMsg.devType != *(uint16_t*)&msg->comInfo.info[0])){
+                    printf("收到2000指令,设备类型和SN不匹配\r\n");
+                    return;
+                }
+            }
+        }
+    }
+    //data_dump("收到数据",readBuf,readlen);
+    switch(msg->msgType1){
+    case 0x01: // 系统指令
+        analysis_cmd_system(msg->msgType2,readBuf,readlen);
+        break;
+    case 0x02: // 状态指令
+        analysis_cmd_status(msg->msgType2,readBuf,readlen); // 直接透传
+        break;
+    case 0x03: // 数据指令
+        analysis_cmd_data(msg->msgType2,readBuf,readlen);
+        break;
+    case 0x04: // 升级指令
+        analysis_cmd_update(msg->msgType2,readBuf,readlen);
+        break;
+    case 0x10: // 日志指令
+        analysis_cmd_log(msg->msgType2,readBuf,readlen);
+        break;
+    }
+
+}

+ 33 - 0
App/taskOpt.h

@@ -0,0 +1,33 @@
+#ifndef _TASK_H_
+#define _TASK_H_
+
+#include "gd32f10x.h"
+#include "../Hardware/boardinit.h"
+#include "public.h"
+#include "ota_update.h"
+
+#define READ_STATUS_TIME 1000*60  // 状态读取时间,1分钟
+#define READ_FIRME_TIME  1000*60*3 // 读取固件信息的时间 3分钟
+typedef struct task_run_data_{
+    uint8_t workMode; // 当前的工作模式 初始化4G 正常工作  升级
+    uint8_t breadstatus; // 读取 状态
+    uint8_t breadfirmmsg; // 读取固件信息
+    uint8_t bcfgfiletime;  // 配置文件的时间是否已经过期
+    uint8_t bcomfiletime;  //com文件的时间是否已经过期
+    timeout_t cfigFileTime; // 配置文件的过期时间
+    timeout_t comFileTime;  // com 文件的过期时间
+    uint32_t timetamp;       // 时间戳
+    uint8_t keyReadcurData;  // 按键读取当前显示屏的值
+    uint8_t keySaveMasterDa;  // 主存储显示数据到flash中
+}__attribute__((packed))taskRunData;
+extern taskRunData g_taskRunDa;
+
+
+extern void power_up_read_comm_min_time(void);
+extern void config_file_is_timeout(void);
+
+extern void init_run_data(void);
+
+extern void analysis_485_rx_fifo(void);
+
+#endif

+ 0 - 0
App/upto485.c


+ 0 - 0
App/upto485.h


+ 1256 - 0
App/xspDataOpt.c

@@ -0,0 +1,1256 @@
+#include "xspDataOpt.h"
+#include "../Hardware/boardinit.h"
+#include <stdlib.h>
+#include <string.h>
+#include "public.h"
+#include "masterslave.h"
+
+testCollDa g_testCollDa;
+
+GunStatus g_gunStatus[4]; // 抬枪信号的状态
+//static uint8_t g_srcDa[4][12]; // 读取的原始数据,每个port最多96位数据
+uint8_t g_7egDa[29] = {0};
+
+XspErrDa g_xspErrDa;
+uint8_t g_logbuff[128] = {0};
+
+XspDataInfo g_xspReDa; // 显示屏的记录数据
+Up7segData g_up7segData;
+XspCollDa g_xspCollDa;
+Error7Seg g_error7seg;
+
+
+NeedleTable g_neTable[128] = {
+    {U1_ID,1,255,255},{U1_ID,0,18,5},{U1_ID,0,18,4},{U1_ID,0,18,3},{U1_ID,0,18,6},{U1_ID,1,18,6},{U1_ID,1,18,5},{U1_ID,1,18,4},//M1 P_A
+    {U1_ID,1,255,255},{U1_ID,0,17,0},{U1_ID,0,18,7},{U1_ID,0,17,6},{U1_ID,0,17,1},{U1_ID,1,17,1},{U1_ID,1,17,0},{U1_ID,1,18,7},//M2 P_A
+    {U1_ID,1,17,7},   {U1_ID,0,17,3},{U1_ID,0,17,2},{U1_ID,0,17,5},{U1_ID,0,17,4},{U1_ID,1,17,4},{U1_ID,1,17,3},{U1_ID,1,17,2},//M3 P_A
+    {U1_ID,1,16,3},   {U1_ID,0,16,1},{U1_ID,0,16,0},{U1_ID,0,17,7},{U1_ID,0,16,2},{U1_ID,1,16,2},{U1_ID,1,16,1},{U1_ID,1,16,0},//M4 P_A
+    {U1_ID,1,16,7},   {U1_ID,0,16,5},{U1_ID,0,16,4},{U1_ID,0,16,3},{U1_ID,0,16,6},{U1_ID,1,16,6},{U1_ID,1,16,5},{U1_ID,1,16,4},//M5 P_A
+    {U1_ID,1,255,255},{U1_ID,0,15,1},{U1_ID,0,15,0},{U1_ID,0,16,7},{U1_ID,0,15,2},{U1_ID,1,15,2},{U1_ID,1,15,1},{U1_ID,1,15,0},//M6 P_A
+
+    {U5_ID,0,255,255},{U5_ID,0, 2,4},{U5_ID,0, 2,5},{U5_ID,0, 2,3},{U5_ID,0, 2,2},{U5_ID,1, 2,2},{U5_ID,1, 2,4},{U5_ID,1, 2,5},//O1 P_A
+    {U5_ID,0,255,255},{U5_ID,0, 2,0},{U5_ID,0, 2,1},{U5_ID,0, 3,7},{U5_ID,0, 3,6},{U5_ID,1, 3,6},{U5_ID,1, 2,0},{U5_ID,1, 2,1},//O2 P_A
+    {U5_ID,0,6,0},    {U5_ID,0, 3,4},{U5_ID,0, 3,5},{U5_ID,0, 3,3},{U5_ID,0, 3,2},{U5_ID,1, 3,2},{U5_ID,1, 3,4},{U5_ID,1, 3,5},//O3 P_A
+    {U5_ID,0,7,4},    {U5_ID,0, 6,2},{U5_ID,0, 6,3},{U5_ID,0 ,6,1},{U5_ID,1, 6,0},{U5_ID,1, 6,1},{U5_ID,1, 6,2},{U5_ID,1, 6,3},//O4 P_A
+    {U5_ID,0,7,0},    {U5_ID,0, 7,6},{U5_ID,0, 7,7},{U5_ID,0, 7,5},{U5_ID,1, 7,4},{U5_ID,1, 7,5},{U5_ID,1, 7,6},{U5_ID,1, 7,7},//O5 P_A
+    {U5_ID,0,255,255},{U5_ID,0, 7,2},{U5_ID,0, 7,3},{U5_ID,0, 7,1},{U5_ID,1, 7,0},{U5_ID,1, 7,1},{U5_ID,1, 7,2},{U5_ID,1, 7,3},//O6 P_A
+
+    {U4_ID,0,5,7},    {U4_ID,0, 4,4},{U4_ID,0, 4,5},{U4_ID,0, 4,3},{U4_ID,0, 4,2},{U4_ID,1, 4,2},{U4_ID,1, 4,4},{U4_ID,1, 4,5},//P1 P_A
+    {U4_ID,0,5,3},    {U4_ID,0, 4,0},{U4_ID,0, 4,1},{U4_ID,1, 5,7},{U4_ID,0, 5,6},{U4_ID,1, 5,6},{U4_ID,1, 4,0},{U4_ID,1, 4,1},//P2 P_A
+    {U4_ID,0,6,7},    {U4_ID,0, 5,4},{U4_ID,0, 5,5},{U4_ID,1, 5,3},{U4_ID,0, 5,2},{U4_ID,1, 5,2},{U4_ID,1, 5,4},{U4_ID,1, 5,5},//P3 P_A
+    {U4_ID,0,255,255},{U4_ID,0, 5,0},{U4_ID,0, 5,1},{U4_ID,1, 6,7},{U4_ID,0, 6,6},{U4_ID,1, 6,6},{U4_ID,1, 5,0},{U4_ID,1, 5,1},//P4 P_A
+
+};
+static int8_t check_segCode(uint8_t segcode,uint8_t *error)
+{
+    int8_t da;
+    switch(segcode){
+    case 0x3E: case 0x3B: case 0x37: case 0x1F:  *error = 1;
+    case 0x3F: case 0xBF: da = 0; break;  //0
+
+    case 0x0E: case 0x16:   *error = 1;
+    case 0x06: case 0x86: da = 1; break;  //1
+
+    case 0x5A: case 0x59: case 0x53: case 0x1B:  *error = 1;
+    case 0x5B: case 0xDB: da = 2; break;  //2
+
+    case 0x4E: *error = 1;
+    case 0x4F: case 0xCF: da = 3; break;  //3
+
+    case 0x64: case 0x62: case 0x76: *error = 1;
+    case 0x66: case 0xE6: da = 4; break;  //4
+
+    case 0x6C: case 0x69: case 0x65:  case 0x2D: *error = 1;
+    case 0x6D: case 0xED: da = 5; break;  //5
+
+    case 0x7C: case 0x79: case 0x75: case 0x5D: *error =  1;
+    case 0x7D: case 0xFD: da = 6; break;  //6
+
+    case 0x05: case 0x03: case 0x17: case 0x27: *error = 1;
+    case 0x07: case 0x87: da = 7; break;  //7
+
+    case 0x7E: case 0x77:    *error = 1;
+    case 0x7F: case 0xFF: da = 8; break;  //8
+
+    case 0x6B: *error = 1;
+    case 0x6F: case 0xEF: da = 9; break;  //9
+
+    case 0x46: da = -1; break;
+    default: da = -1; break;
+    }
+    return da;
+}
+
+
+static int8_t check_segCode_first(uint8_t segcode[], Usrc7SegDa *seg, uint8_t *error)
+{
+    int8_t da = 0x00;
+    uint8_t i = 0;
+    uint16_t sum = 0;
+    static uint8_t flag = 0;
+
+    g_xspCollDa.bcorrect = 0;
+    for (i = 0; i < 16; i++) {
+        switch (segcode[i]) {
+        case 0x3E: case 0x3B: case 0x37: case 0x1F:  *error = 1;
+        case 0x3F: case 0xBF: seg->val[i] = 0x3F; break;  //0
+
+        case 0x0E: case 0x16:   *error = 1;
+        case 0x06: case 0x86: seg->val[i] = 0x06; break;  //1
+
+        case 0x5A: case 0x59: case 0x53: case 0x1B:  *error = 1;
+        case 0x5B: case 0xDB: seg->val[i] = 0x5B; break;  //2
+
+        case 0x4E: *error = 1;
+        case 0x4F: case 0xCF: seg->val[i] = 0x4F; break;  //3
+
+        case 0x64: case 0x62: case 0x76: *error = 1;
+        case 0x66: case 0xE6: seg->val[i] = 0x66; break;  //4
+
+        case 0x6C: case 0x69: case 0x65:  case 0x2D: *error = 1;
+        case 0x6D: case 0xED: seg->val[i] = 0x6D; break;  //5
+
+        case 0x7C: case 0x79: case 0x75: case 0x5D: *error = 1;
+        case 0x7D: case 0xFD: seg->val[i] = 0x7D; break;  //6
+
+        case 0x05: case 0x03: case 0x17: case 0x27: *error = 1;
+        case 0x07: case 0x87: seg->val[i] = 0x07; break;  //7
+
+        case 0x7E: case 0x77:    *error = 1;
+        case 0x7F: case 0xFF: seg->val[i] = 0x7F; break;  //8
+
+        case 0x6B: *error = 1;
+        case 0x6F: case 0xEF: seg->val[i] = 0x6F; break;  //9
+
+        case 0x01: case 0x02: case 0x04: case 0x08: // 处理七段码非针的情况
+        case 0x10: case 0x20: case 0x40:
+            seg->val[i] = 0x00;
+            g_xspCollDa.bcorrect |= 0x01;
+            break;
+        case 0x80:// 只有点的情况,不算是错误码,直接转成空即不显示
+            seg->val[i] = 0x00;
+            break;
+        case 0x72: case 0x38: case 0xF2: case 0xB8: // 去掉P和L的情况
+            *error = 1;
+            da = -1;
+            break;
+        case 0x00: // 处理没有显示的数据
+            seg->val[i] = segcode[i];
+            break;
+        default:
+            *error = 1;
+            seg->val[i] = segcode[i];
+            break;
+        }
+        sum += seg->val[i];
+        //printf("%02x,",segcode[i]);
+    }
+    //printf("\n");
+    if(da == 0x00){  //   考虑去掉P和L的情况
+        if (sum == 0) da = -1;
+        else da = 1;
+    }
+
+    if(*error == 0x00) return da;
+ERROR_END:
+    for(i=0;i<16;i++){
+        if(segcode[i] != g_xspErrDa.segDa[i]) {
+            memcpy(g_xspErrDa.segDa,segcode,16);
+            timeout_stop(&g_xspErrDa.timer);
+            timeout_start(&g_xspErrDa.timer);
+            flag = 1;
+            break;
+        }
+    }
+    if((g_logMsg.blogOpen == 1) && (g_logMsg.logType==LOG_TYPE_7SEG)){
+        if(flag == 1) {
+            g_xspErrDa.bsend = 2;
+            flag = 0;
+        }
+        if(timeout_isOut(&g_logMsg.timer)){
+            g_logMsg.blogOpen = 0;
+            g_logMsg.logType = LOG_TYPE_NULL;
+            timeout_stop(&g_logMsg.timer);
+        }
+    }
+    else if(g_logMsg.logType == LOG_TYPE_NULL){
+        if(timeout_isOut(&g_xspErrDa.timer) && flag == 1){
+            for(i=0;i<16;i++){
+                if(g_xspErrDa.lastsegDa[i] != g_xspErrDa.segDa[i]) {
+                    memcpy(g_xspErrDa.lastsegDa,g_xspErrDa.segDa,16);
+                    timeout_stop(&g_xspErrDa.timer);
+                    timeout_start(&g_xspErrDa.timer);
+                    flag = 2;
+                    break;
+                }
+            }
+            if(flag == 2) g_xspErrDa.bsend = 2; // 此条记录未发送
+            else g_xspErrDa.bsend = 1;
+            flag = 0;
+
+        }
+    }
+
+    if((segcode[0] == 0x78) &&(segcode[1]==0x5C) && (segcode[2]==0x78)) da = -1; //totl,在查询总累计的时候显示的
+
+    return da;
+
+}
+/*-----------------------------------------------------------------------
+ *  将映射数据转换为实际的数据
+ * -----------------------------------------------------------------------*/
+#if(0)
+static uint8_t get_data_from_7segCode(uint8_t *segcode, dispData *tempda )
+{
+    volatile uint8_t i,ret = 0,j=0,bprice = 0, bamount = 0, boil = 0;
+    int8_t da,comDa[6] = {0},corrDa[6] = {0},bcorrDa = 0;
+    uint8_t bsegright = 0, bright = 0, berror = 0; // 判断单价 油量 金额是否正确,0位:金额 1位:测量 2位:单价
+    uint32_t correctAmount = 0, calAmount = 0; // 纠正后的金额,计算的金额
+    char dastr[11] = {'\0'};
+    float price = 0,amount =0;
+    static uint8_t flag = 0;
+    uint16_t sum = 0, amountadd = 0;
+    uint8_t segcode01[16] = {0};
+    g_xspoptDa.bcorrect = 0;
+
+    if((segcode[0] == 0x72)){ // 去掉PP情况 定额加油的情况
+            ret = 0;
+            goto ERROR_END;
+    }
+    if((segcode[0] == 0x38) ) {// 去掉LL情况  定量加油的情况
+            ret = 0;
+            goto ERROR_END;
+    }
+
+    for(i=0;i<16;i++){// 去掉只有一个针的情况
+        switch (segcode[i]){
+        case 0x01: case 0x02: case 0x04: case 0x08:
+        case 0x10: case 0x20: case 0x40: case 0x80:
+            segcode01[i] = 0;
+            bsegright = 1;// 错误
+            g_xspoptDa.bcorrect |= 0x01;
+            break;
+        default:
+            segcode01[i] = segcode[i];
+            break;
+        }
+        if(i<6) amountadd += (segcode[i]&0x7F);
+        sum += segcode[i];
+
+    }
+    if(sum == 0) {
+        ret = 0;
+        goto ERROR_END;
+    }
+    if(segcode01[0] != 0x00){
+        if(segcode01[1] == 0x00 || segcode01[2] == 0x00 || segcode01[3] == 0x00){
+            ret = 0;
+            goto ERROR_END;
+        }
+    }
+    else {
+        if(amountadd == 0x00){
+            ret = 0;
+            goto ERROR_END;
+        }
+    }
+
+    for(i=0;i<6;i++){ // 金额
+        if(segcode01[i] == 0x00 ){ da = 0; dastr[i] = 0x30;}// value = ((value<<(i*8))|da);}
+        else {
+            da = check_segCode(segcode01[i],&berror);
+            if((i==5) && (da == -1)){ // 处理金额的最后一位错误,则不处理
+                dastr[i] = 0x30;
+            }
+            else if(da != -1){
+                dastr[i] = check_segCode(segcode01[i],&berror) |0x30;
+            }
+            else {bamount = 1; bright |= 0x01;} // 金额错误
+        }
+        comDa[i] = da;
+    }
+    if(bamount == 0){
+        dastr[i] = 0;
+        tempda->amount = atol(dastr);
+    }
+
+    j = 0;
+    for(i=6;i<12;i++,j++) { // 油量
+        if(segcode01[i] == 0x00 ) { da = 0; dastr[i-6] = 0x30;}// value = ((value<<(j*8))|da);}
+        else {
+            da = check_segCode(segcode01[i],&berror);
+            if(da != -1){
+                dastr[i-6] = check_segCode(segcode01[i],&berror) |0x30;
+            }
+            else {boil = 1; bright |= 0x02 ; break;} // 油量错误
+        }
+    }
+    if(boil == 0) {
+        dastr[i-6] = 0;
+        tempda->oil = atol(dastr);
+    }
+    if(0 == g_bhavePrice) {
+        if(bamount == 0 && boil ==0){
+            if(tempda->oil !=0) price = (float)tempda->amount/(float)tempda->oil;
+            else price = 0;
+            tempda->price = (uint32_t)(price*100.0+0.5);
+        }
+    }
+    else {
+        j = 0;
+        for(i=12;i<16;i++,j++){ // 单价
+            if(segcode01[i] == 0x00 ) { da = 0; dastr[i-12] = 0x30;}// value = ((value<<(j*8))|da);}
+            else {
+                da = check_segCode(segcode01[i],&berror);
+                if(da != -1){
+                    dastr[i-12] = check_segCode(segcode01[i],&berror) |0x30;
+                }
+                else {bprice = 1; bright |=0x04; break;} // 单价错误
+            }
+        }
+        if(bprice == 0){
+            dastr[i-12] = 0;
+            tempda->price = atol(dastr);
+        }
+    }
+    if((bright == 0x00) &&( bsegright==0x00)) { return 1;} // 数据是正确的
+    else if((bright == 0x00) && (bsegright == 0x01)) { // 数据除了有非针,其它情况全对
+        ret = 1;
+        goto ERROR_END;
+    }
+    else if(bright == 0x07){ret = 0;} // 全错,无法纠正
+    else if(bright == 0x04){ // 金额和油量正确,单价错误,可以纠正
+        ret = 1;
+        g_xspoptDa.bcorrect |= 0x02;
+        if(tempda->oil != 0)
+            tempda->price = (uint32_t)((float)tempda->amount/(float)tempda->oil*100.0);
+        else tempda->price = 0;
+    }
+    else if(bright == 0x02){// 金额和单价正确, 油量错误,可以纠正
+        ret = 1;
+        g_xspoptDa.bcorrect |= 0x02;
+        tempda->oil = (uint32_t)((float)tempda->amount/(float)tempda->price*100.0+0.5);
+    }
+    else if(bright == 0x01){// 油量和单价正确, 金额错误, 可以纠正
+        ret = 1;
+        g_xspoptDa.bcorrect |= 0x02;
+        amount = (float)tempda->oil/100.0 *((float)tempda->price/100.0);
+        calAmount = (uint32_t)(amount*100); // 直接计算的
+        correctAmount = (uint32_t)(amount+0.5)*100; // 取整后的
+        corrDa[0] = correctAmount/100000%10;
+        corrDa[1] = correctAmount/10000%10;
+        corrDa[2] = correctAmount/1000%10;
+        corrDa[3] = correctAmount/100%10;
+        corrDa[4] = correctAmount/10%10;
+        corrDa[5] = correctAmount%10;
+        for(i=0;i<6;i++){
+            if(comDa[i] == -1) continue;
+            if(corrDa[i] != comDa[i])  {bcorrDa = 1; break;} // 不能用纠正后的数据,用直接计算的值
+        }
+        if(bcorrDa == 1) tempda->amount = calAmount; // 直接计算的
+        else tempda->amount = correctAmount; // 校正后的
+
+    }
+    else {
+        ret = 0; // 错误其中任意两个
+    }
+
+ERROR_END:
+    for(i=0;i<16;i++){
+        if(segcode[i] != g_xspErrDa.segDa[i]) {
+            memcpy(g_xspErrDa.segDa,segcode,16);
+            timeout_stop(&g_xspErrDa.timer);
+            timeout_start(&g_xspErrDa.timer);
+            flag = 1;
+            break;
+        }
+    }
+    if((g_logMsg.blogOpen == 1) && (g_logMsg.logType==LOG_TYPE_7SEG)){
+        if(flag == 1) {
+            g_xspErrDa.bsend = 2;
+            flag = 0;
+        }
+        if(timeout_isOut(&g_logMsg.timer)){
+            g_logMsg.blogOpen = 0;
+            g_logMsg.logType = LOG_TYPE_NULL;
+            timeout_stop(&g_logMsg.timer);
+        }
+    }
+    else if(g_logMsg.logType == LOG_TYPE_NULL){
+        if(timeout_isOut(&g_xspErrDa.timer) && flag == 1){
+            for(i=0;i<16;i++){
+                if(g_xspErrDa.lastsegDa[i] != g_xspErrDa.segDa[i]) {
+                    memcpy(g_xspErrDa.lastsegDa,g_xspErrDa.segDa,16);
+                    timeout_stop(&g_xspErrDa.timer);
+                    timeout_start(&g_xspErrDa.timer);
+                    flag = 2;
+                    break;
+                }
+            }
+            if(flag == 2) g_xspErrDa.bsend = 2; // 此条记录未发送
+            else g_xspErrDa.bsend = 1;
+            flag = 0;
+
+        }
+    }
+    return ret;
+}
+
+#else
+
+uint8_t get_data_from_7segCode(Usrc7SegDa *seg, dispData *tempda)
+{
+    uint8_t i = 0, berror = 0,bright = 0, ret = 1;
+    int8_t da = 0, comDa[6] = { 0 };
+    uint8_t bprice = 0, bamount = 0, boil = 0,corrDa[6] = { 0 }, bcorrDa = 0;
+    uint8_t priceCnt = 0; // 单价的位数,单价必须为三个,如果为两数,则数据是错误的
+    char amountStr[6] = {'\0'};
+    char oilStr[6] = {'\0'};
+    char priceStr[5] = {'\0'};
+
+    uint32_t correctAmount = 0, calAmount = 0; // 纠正后的金额,计算的金额
+    static float price = 0;
+    float amount = 0;
+
+    for (i = 0; i < 6; i++) {
+        if (seg->da.amount[i] == 0x00) {
+            da = 0;
+            amountStr[i] = 0x30;
+            if(i>0) amountStr[i-1] = 0x30;
+        }
+        else {
+            da = check_segCode(seg->da.amount[i],&berror);
+            if ((i == 5) && (da == -1)) amountStr[i] = 0x30; // 处理金额的最后一位,如果金额的最后一位是错误的,则直接变为0
+            else if (da != -1) {
+                amountStr[i] = da | 0x30;
+            }
+            else {
+
+                bamount = 0x01;
+                bright |= 0x01;
+            }
+        }
+        comDa[i] = da;
+    }
+    if (bamount == 0) {
+        tempda->amount = atol(amountStr);
+    }
+
+    for (i = 0; i < 6; i++) {
+        if (seg->da.oil[i] == 0x00) {
+            da = 0;
+            oilStr[i] = 0x30;
+            if(i>0) oilStr[i-1] = 0x30;
+        }
+        else {
+            da = check_segCode(seg->da.oil[i], &berror);
+            if ((i == 5) && (da == -1)) oilStr[i] = 0x30;
+            else if (da != -1) {
+                oilStr[i] = da | 0x30;
+            }
+            else {
+                boil = 0x01;
+                bright |= 0x02;
+            }
+        }
+    }
+    if (boil == 0) {
+        tempda->oil = atol(oilStr);
+    }
+    if (0 == g_bhavePrice) { // 没有单价屏
+        if ((bamount == 0) &&( boil == 0)) {
+            if (tempda->oil != 0) price = (float)tempda->amount / (float)tempda->oil;
+            else price = 0;
+            tempda->price = (uint32_t)(price*100.0 + 0.5);
+        }
+        else if((bamount == 1) && (boil == 0)){ // 金额错误,油量对
+            tempda->amount = price * tempda->oil/100;
+        }
+        else if((bamount == 0) && (boil == 1)){ // 金额对,油量错误
+            if(price > 0.1)
+                tempda->oil = (uint32_t)((float)tempda->amount / price +0.5);
+        }
+    }
+    else { // 有单价屏
+        priceCnt = 0x00;
+        for (i = 0; i < 4; i++) {
+            if (seg->da.price[i] == 0x00) { da = 0; priceStr[i] = 0x30; }
+            else {
+                priceCnt |= ((uint8_t)0x01 << (3-i));
+                da = check_segCode(seg->da.price[i], &berror);
+                if (da != -1) {
+                    priceStr[i] = da | 0x30;
+                }
+                else {
+                    bprice = 0x01;
+                    bright |= 0x04;
+                }
+            }
+        }
+        if (bprice == 0) {
+            if(priceCnt == 0x07)
+                tempda->price = atol(priceStr);
+            else {
+               bright |= 0x04;
+            }
+        }
+    }
+
+
+    if(bright == 0x00) ret =  1; // 三项全对
+    else if (bright == 0x07) ret =  0; // 金额 油量 单价全部错误
+    else if (bright == 0x04) { // 单价错误 金额 油量正确
+        if (tempda->oil != 0)
+            tempda->price = (uint32_t)((float)tempda->amount / (float)tempda->oil*100.0 + 0.5);
+        else tempda->price = 0;
+        g_xspCollDa.bcorrect |= 0x02;
+    }
+    else if (bright == 0x02) { // 油量错误  金额 单价正确
+        if(tempda->price != 0)
+            tempda->oil = (uint32_t)((float)tempda->amount / (float)tempda->price*100.0 + 0.5);
+        g_xspCollDa.bcorrect |= 0x02;
+    }
+    else if (bright == 0x01) { // 金额错误  油量 单价正确
+        amount = (float)tempda->oil / 100.0 *((float)tempda->price / 100.0);
+        calAmount = (uint32_t)(amount * 100); // 直接计算的
+        correctAmount = (uint32_t)(amount + 0.5) * 100; // 取整后的
+        corrDa[0] = correctAmount / 100000 % 10;
+        corrDa[1] = correctAmount / 10000 % 10;
+        corrDa[2] = correctAmount / 1000 % 10;
+        corrDa[3] = correctAmount / 100 % 10;
+        corrDa[4] = correctAmount / 10 % 10;
+        corrDa[5] = correctAmount % 10;
+        for (i = 0; i < 6; i++) {
+            if (comDa[i] == -1) continue;
+            if (corrDa[i] != comDa[i]) { bcorrDa = 1; break; } // 不能用纠正后的数据,用直接计算的值
+        }
+        if (bcorrDa == 1) tempda->amount = calAmount; // 直接计算的
+        else tempda->amount = correctAmount; // 校正后的
+        g_xspCollDa.bcorrect |= 0x02;
+    }
+    else { // 错误其中两项,无法纠正
+        ret = 0;
+    }
+    return ret;
+}
+#endif
+/*-------------------------------------------------------------------------------
+ *  保存记录
+ * -------------------------------------------------------------------------------*/
+void save_record_to_flash(uint8_t recordMode)
+{
+    int amount = 0;
+//    uint32_t addTime;
+//    if(recordMode == 0x01){
+//        addTime = g_xspCollDa.gunDnTime - g_xspCollDa.gunUpTime; // 计算加油的时间 单位ms
+
+//        printf("~~~~~~~~~~~~~~addtime = %d, oil = %d\n",addTime, g_xspCollDa.curDisp.oil);
+//    }
+
+    if((recordMode == 0x01) &&(g_xspCollDa.bcheckDa == 0) ){//
+
+        if((g_xspCollDa.curDisp.amount == 888888) || (g_xspCollDa.curDisp.oil == 888888)) return;
+        if((g_xspCollDa.curDisp.amount == 0) || (g_xspCollDa.curDisp.oil == 0)) return ;
+        if(g_xspCollDa.curDisp.amount >=999999 || g_xspCollDa.curDisp.oil>=999999) return;
+
+        g_xspReDa.reDa.amount = g_xspCollDa.curDisp.amount;
+        g_xspReDa.reDa.price  = g_xspCollDa.curDisp.price;
+        g_xspReDa.reDa.oil    = g_xspCollDa.curDisp.oil;
+        g_xspReDa.reDa.tamount = g_xspCollDa.lastTamout + g_xspCollDa.curDisp.amount;
+        g_xspReDa.reDa.toil    = g_xspCollDa.lastToil   + g_xspCollDa.curDisp.oil;
+
+    }
+    else
+    {
+        if((g_xspCollDa.lastDisp.amount == 888888) || (g_xspCollDa.lastDisp.oil == 888888)) return;
+        if((g_xspCollDa.lastDisp.amount == 0) || (g_xspCollDa.lastDisp.oil == 0)) return ;
+        if(g_xspCollDa.lastDisp.amount == g_xspCollDa.lastDisp.oil) return;
+        if(g_xspCollDa.lastDisp.amount >=999999 || g_xspCollDa.lastDisp.oil>=999999) return;
+        amount = g_xspCollDa.curDisp.amount - g_xspCollDa.lastDisp.amount;
+        if((g_xspCollDa.curDisp.amount!=0) &&(amount>0) && (amount <50)){ // 和当前的值校正一下
+            g_xspCollDa.lastDisp.amount = g_xspCollDa.curDisp.amount;
+            g_xspCollDa.lastDisp.oil = g_xspCollDa.curDisp.oil;
+        }
+        g_xspReDa.reDa.amount = g_xspCollDa.lastDisp.amount;
+        g_xspReDa.reDa.price  = g_xspCollDa.lastDisp.price;
+        g_xspReDa.reDa.oil    = g_xspCollDa.lastDisp.oil;
+        g_xspReDa.reDa.tamount = g_xspCollDa.lastTamout + g_xspCollDa.lastDisp.amount;
+        g_xspReDa.reDa.toil    = g_xspCollDa.lastToil   + g_xspCollDa.lastDisp.oil;
+    }
+    g_xspReDa.reDa.bcorrect = ((g_xspCollDa.bcorrect|0xFFFF)<<8);
+    g_xspReDa.reDa.bsend   = 0xFFFF;
+    g_xspReDa.reDa.recodeMode   = recordMode;
+    g_xspReDa.reDa.timer   = rtc_counter_get();// 产生记录的时间
+    g_xspCollDa.lastTamout = g_xspReDa.reDa.tamount;
+    g_xspCollDa.lastToil    = g_xspReDa.reDa.toil;
+    g_xspReDa.reDa.recordId = (g_xspReDa.reDa.recordId+1)%0xFFFFFFFF;
+    write_flash(g_xspReDa.data);
+    printf("新记录: recordId=%d, amout:%d, oil:%d, tamout:%lld, toil:%lld\r\n",g_xspReDa.reDa.recordId,\
+           g_xspReDa.reDa.amount,g_xspReDa.reDa.oil,g_xspReDa.reDa.tamount,g_xspReDa.reDa.toil);
+    memset(&g_xspCollDa.lastDisp, 0, sizeof(dispData)); // 存储完成后,要清除保留的数据
+}
+
+/*------------------------------------------------------------------------
+ *  抬枪信号的处理
+ * -----------------------------------------------------------------------*/
+void init_gun_status(void)
+{
+    uint8_t i;
+    for(i=0;i<4;i++){
+        g_gunStatus[i].curst = HIGHT_LEVEL;
+        g_gunStatus[i].lastst = HIGHT_LEVEL;
+        g_gunStatus[i].timer = 0;
+        g_gunStatus[i].bsave = 0;
+    }
+    g_gunSta.bGunUp = 0;
+    timeout_setValue(&g_gunSta.guntime,2000);
+    timeout_setValue(&g_gunSta.taigunTime,500);
+}
+
+void deal_gun_status(uint32_t tick)
+{
+    uint8_t status;
+    static uint8_t laststatus = 0xFF;
+    static uint8_t count = 0;
+
+    if((tick%1000) != 0) return; // 10ms处理一次
+    if(g_xspCollDa.curstatus == STATUS_PROG) return; // 在加油过程中,不处理抬挂枪的信号
+    status = gpio_input_bit_get(TQ_PORT,TQ_PIN);
+    if(status != laststatus) {
+        laststatus = status;
+        count = 0;
+    }
+    else count++;
+
+    if(count>=4){
+        if(RESET == status) { // 有抬枪信号
+            g_gunStatus[0].curst = LOW_LEVEL;
+            g_gunStatus[0].bsave = 0;
+            timeout_stop(&g_gunSta.guntime);
+        }
+        else { // 没有抬枪信号,有挂枪
+            if(g_gunStatus[0].curst == LOW_LEVEL){
+                g_gunStatus[0].lastst = g_gunStatus[0].curst;
+                timeout_start(&g_gunSta.guntime); // 启动抬枪的时候
+                g_gunStatus[0].bsave = 1;
+                g_gunStatus[0].curst = LOW_HIGHT;
+            }
+        }
+        count = 0;
+    }
+}
+void check_gun_status_to_save_record(void)
+{
+    uint8_t status;
+    static uint8_t gunstatus = 0xFF;
+
+    if(gunstatus != g_gunStatus[0].curst){
+        printf("gunstatus = %d  ", g_gunStatus[0].curst);
+        switch(g_gunStatus[0].curst){
+        case HIGHT_LOW: case LOW_LEVEL:
+            if(gpio_input_bit_get(TQ_PORT,TQ_PIN)!= RESET) break;
+            printf("抬枪\n");
+            g_xspCollDa.gunUpTime = Get_SysTick(); // 得到抬枪的时间
+            if((Get_SysTick() - g_xspCollDa.gunDnTime) <1000) break;
+            if((g_xspCollDa.curstatus != STATUS_START) && (g_xspCollDa.curstatus != STATUS_PROG)){
+                g_xspCollDa.curstatus = STATUS_START;
+            }
+            g_xspCollDa.gunStatus = GUN_UP;
+            break;
+        case LOW_HIGHT: case HIGHT_LEVEL:
+            g_xspCollDa.gunDnTime = Get_SysTick(); // 得到挂枪的时间
+            printf("挂枪\n");
+            if((g_xspCollDa.gunUpTime==0)){
+                g_gunStatus[0].bsave = 0;
+                gunstatus = g_gunStatus[0].curst;
+                return;
+            }
+            else if((g_xspCollDa.gunDnTime >= g_xspCollDa.gunUpTime)){
+                if(g_xspCollDa.gunDnTime-g_xspCollDa.gunUpTime<1000) {
+                    printf("干扰产生的抬枪信号\n");
+                    g_gunStatus[0].bsave = 0;
+                    gunstatus = g_gunStatus[0].curst;
+                    return;
+                }
+            }
+            g_xspCollDa.gunStatus = GUN_DOWN;
+            g_xspCollDa.gunUpTime = 0;
+            break;
+        }
+
+        gunstatus = g_gunStatus[0].curst;
+    }
+    status = gpio_input_bit_get(TQ_PORT,TQ_PIN);
+
+
+    if(timeout_isOut(&g_gunSta.guntime) && (g_gunStatus[0].bsave == 1) && (g_xspCollDa.curstatus != STATUS_PROG)){
+        if((SET == gpio_input_bit_get(TQ_PORT,TQ_PIN)) && (g_xspCollDa.bSaveRecode == 1)){
+            printf("枪已经挂\n");
+            g_gunSta.bGunDn = 0;
+
+            save_record_to_flash(0x01);//存储数据
+            g_xspCollDa.bSaveRecode = 0;
+            printf("抬枪信号产生一笔新的记录\r\n");
+            g_gunSta.bgun = 0;
+            g_gunStatus[0].bsave = 0;
+            g_xspCollDa.curstatus = STATUS_END;
+            g_xspCollDa.gunUpTime = 0;
+            g_xspCollDa.startToprog = 0;
+        }
+        else {
+            printf("空抬枪,未加油\n");
+            g_gunStatus[0].bsave = 0;
+            g_xspCollDa.curstatus = STATUS_NULL;
+            g_xspCollDa.gunUpTime = 0;
+        }
+    }
+}
+/*------------------------------------------------------------------------
+ *  时间 30分钟没有保存记录,则保存
+ * -----------------------------------------------------------------------*/
+void init_xsp_run_data(void)
+{
+    timeout_setValue(&g_xspErrDa.timer,3000);
+    timeout_setValue(&g_xspCollDa.sameTimer, 3000);
+    g_logMsg.logType = LOG_TYPE_NULL;
+}
+/*-------------------------------------------------------------------------
+ *  上电对比上次保存和当前屏显是否一致
+ *  上电是只执行一次
+ * ------------------------------------------------------------------------*/
+void power_up_check_last_cur(dispData *da)
+{
+    return;
+//    if((da->amount == 0) && (da->oil == 0))  g_xspoptDa.lastDawrite = 1;
+//    else if((g_xspReDa.reDa.amount==da->amount) \
+//       && (g_xspReDa.reDa.oil==da->oil)) { //  当前屏显和上一比存储的是一比数据,本数据已存储
+//        g_xspoptDa.lastDawrite = 1;
+//        g_xspCollDa.curDisp.oil = da->oil;
+//        g_xspCollDa.curDisp.amount = da->amount;
+//        printf("当前屏显与flash中存储的一致");
+//    }
+//    else g_xspoptDa.lastDawrite = 0;
+}
+
+void analysis_7seg_code(uint8_t _7egDa[])
+{
+    uint8_t i = 0, bflag = 0,bequal = 0,bstart =0;
+    uint8_t boil = 0, bamt = 0;
+    uint32_t eAmount = 0, eOil = 0,tickoil,tickAm; // 用于存储差额的
+    int8_t ret = 0;
+    uint32_t tampTime = 0;
+    Usrc7SegDa *src7Da = NULL, *last1 = NULL, *last2 = NULL;
+    static dispData temp,nostart;
+//    float price;
+    uint16_t uprice = 0;
+
+
+    src7Da = &g_xspCollDa.cur;
+    last1 = &g_xspCollDa.last1;
+    last2 = &g_xspCollDa.last2;
+
+    g_error7seg.berror = 0;
+    ret = check_segCode_first(&_7egDa[START_ID],src7Da, &g_error7seg.berror); // 2. 第一次解析
+    if (ret == -1) {
+        printf("采集到的7段码全部为0\n");
+
+        return;
+    }
+
+    bflag = g_xspCollDa.cur.da.amount[0] | g_xspCollDa.cur.da.amount[1] | g_xspCollDa.cur.da.amount[2] | g_xspCollDa.cur.da.oil[0] | g_xspCollDa.cur.da.oil[1] | g_xspCollDa.cur.da.oil[2];
+    if (bflag == 0x00) { // 金额 油量的高3个字节都为0(即不显示任何数)则判断是否是加油开始
+        if(g_xspCollDa.cur.da.amount[3] == 0x3F) {bamt |=0x01;}
+        if(g_xspCollDa.cur.da.amount[4] == 0x3F) {bamt |=0x02;}
+        if(g_xspCollDa.cur.da.amount[5] == 0x3F) {bamt |=0x04;}
+        if(g_xspCollDa.cur.da.oil[3] == 0x3F) {boil |= 0x01; }
+        if(g_xspCollDa.cur.da.oil[4] == 0x3F) {boil |= 0x02; }
+        if(g_xspCollDa.cur.da.oil[5] == 0x3F) {boil |= 0x04; }
+        if((bamt== 0x07) && (boil == 0x07 || boil==0x06 || boil==0x05 || boil==0x03)) bstart = 1;
+        else if((boil== 0x07) && (bamt == 0x07 || bamt==0x06 || bamt==0x05 || bamt==0x03)) bstart=1;
+        else bstart = 0;
+        if (bstart == 0x01) {
+            printf("显示屏显示为0.00, 加油开始.......\n");
+            if(g_xspCollDa.bSaveRecode == 0x01) {// 判断是否需要存储记录
+                save_record_to_flash(0x00);
+                g_xspCollDa.bSaveRecode = 0x00;
+            }
+            memset(&g_xspCollDa.lastDisp, 0, sizeof(dispData));
+            memset(&g_xspCollDa.curDisp, 0, sizeof(dispData));
+            g_xspCollDa.lastTick = Get_SysTick();
+            g_xspCollDa.startTime = Get_SysTick();
+            g_xspCollDa.startToprog = 0;
+            g_xspCollDa.bcheckDa = 0;
+            temp.amount = 0;
+            temp.oil = 0;
+            g_xspCollDa.curstatus = STATUS_START; // 加油开始
+            g_xspCollDa.bstart00 = 1;
+        }
+    }
+    bequal = 0;
+    for (i = 0; i < 3; i++) {
+        if ((src7Da->uDa.da32[i] != last1->uDa.da32[i]) && (src7Da->uDa.da32[i] != last2->uDa.da32[i])) {
+            bequal = 1;
+            break;
+        }
+    }
+
+    if (bequal == 1) {
+        memcpy(last2->val, last1->val, 16);
+        memcpy(last1->val, src7Da->val, 16);
+
+        ret = get_data_from_7segCode(src7Da, &temp);
+        if(ret == 0) goto ERROR_END;
+        tampTime = Get_SysTick()-g_xspCollDa.lastcomTick;
+        g_xspCollDa.lastcomTick  = Get_SysTick();
+        if ((g_xspCollDa.curstatus == STATUS_START) ) {
+            if ((temp.amount > g_xspCollDa.curDisp.amount) || (temp.oil > g_xspCollDa.curDisp.oil)) {
+                eAmount = abs((int)temp.amount - (int)g_xspCollDa.curDisp.amount);
+                eOil = abs((int)temp.oil - (int)g_xspCollDa.curDisp.oil);
+                //printf("aaaaaa = %d, eamout = %d, eoil = %d\n",Get_SysTick()-g_xspCollDa.lastTick,eAmount,eOil);
+                if((eAmount < 100) && (eOil<50) && ((Get_SysTick()-g_xspCollDa.lastTick) < 500)){ //判断是额增长且时间差小于500ms
+                    g_xspCollDa.startToprog++;
+                    g_xspCollDa.lastTick = Get_SysTick();
+                }
+                if((g_xspCollDa.startToprog > 5)||(g_xspCollDa.gunStatus==GUN_UP)){//||(g_gunStatus[0].curst==HIGHT_LOW)||(g_gunStatus[0].curst == LOW_LEVEL)
+                    g_xspCollDa.curstatus = STATUS_PROG; // 加油过程
+                    memcpy(&g_xspCollDa.lastDisp, &temp, sizeof(dispData));
+                }
+                g_xspCollDa.bcheckDa = 0;
+            }
+
+        }
+        else {
+            if((temp.amount==0x00)&&(temp.oil==0x00)){
+                //printf("ccccccccccccccccccc\n");
+                if(g_xspCollDa.bSaveRecode == 0x01) {// 判断是否需要存储记录
+                    save_record_to_flash(0x00);
+                    g_xspCollDa.bSaveRecode = 0x00;
+                }
+                memset(&g_xspCollDa.lastDisp, 0, sizeof(dispData));
+                memset(&g_xspCollDa.curDisp, 0, sizeof(dispData));
+                g_xspCollDa.lastTick = Get_SysTick();
+                g_xspCollDa.startTime = Get_SysTick();
+                g_xspCollDa.startToprog = 0;
+                g_xspCollDa.bcheckDa = 0;
+                g_xspCollDa.curstatus = STATUS_START; // 加油开始
+            }
+        }
+
+        memcpy(&g_xspCollDa.curDisp, &temp, sizeof(dispData));
+        if (g_xspCollDa.curstatus == STATUS_PROG) { // 加油中
+            uprice = (uint32_t)((float)temp.amount/(float)temp.oil*100.0+0.5);
+
+            if ( (uprice<1200) && (temp.amount >= g_xspCollDa.lastDisp.amount) && (temp.oil >= g_xspCollDa.lastDisp.oil)) {
+                eAmount = temp.amount - g_xspCollDa.lastDisp.amount;
+                eOil = temp.oil - g_xspCollDa.lastDisp.oil;
+                tickoil = ((Get_SysTick()-g_xspCollDa.lastTick)/10)+1;//*10; // 12毫秒 加10毫升的油
+                tickoil = ((tickoil <5) ? 5: tickoil);
+                tickAm = (uint32_t)((float)tickoil*(float)temp.price/100.00+0.5)+1;
+                if((eAmount <= tickAm) && (eOil <=tickoil)  ){
+                    memcpy(&g_xspCollDa.lastDisp1,&g_xspCollDa.lastDisp,sizeof(dispData));
+                    memcpy(&g_xspCollDa.lastDisp, &temp, sizeof(dispData));
+                    printf("有效,显示屏加油中.......(%010u)  ", Get_SysTick());
+                    g_xspCollDa.lastTick1 = g_xspCollDa.lastTick;
+                    g_xspCollDa.lastTick = Get_SysTick();  // 只有在加油时,记录时间戳
+                    g_xspCollDa.bstart00 = 0;
+                }
+                else {
+                    printf("无效,显示屏加油中.......(%010u,%010u)  ", Get_SysTick(),g_xspCollDa.lastTick);
+                }
+                printf("(%02d,%02d) %d,%d,%d\n",tickAm,tickoil, temp.amount, temp.oil, temp.price);
+                g_xspCollDa.bSaveRecode = 1;
+            }
+            else { // 数据采集错误 ,是否可以纠正还原一下正确的数据???
+                if((temp.amount >=g_xspCollDa.lastDisp1.amount) && (temp.oil >= g_xspCollDa.lastDisp1.oil)){
+                    eAmount = temp.amount - g_xspCollDa.lastDisp1.amount;
+                    eOil = temp.oil - g_xspCollDa.lastDisp1.oil;
+                    tickoil = ((Get_SysTick()-g_xspCollDa.lastTick1)/10)+1;//*9;
+                    tickoil = ((tickoil <5) ? 5: tickoil);
+                    tickAm = (uint32_t)((float)tickoil*(float)temp.price/100.00+0.5)+1;
+                    if((eAmount <= tickAm) && (eOil <=tickoil)  ){
+                        memcpy(&g_xspCollDa.lastDisp, &temp, sizeof(dispData));
+                        printf("上次数据错误,这组数据矫正 %d, %d,%d\n ", temp.amount, temp.oil, temp.price);
+                        g_xspCollDa.lastTick = Get_SysTick();  // 只有在加油时,记录时间戳
+
+                    }
+                    else {
+                        printf("%d,%d\n",g_xspCollDa.lastDisp1.amount,g_xspCollDa.lastDisp1.oil);
+                        printf("abcdef~~~~~ %d,%d,%d,%d,%d\n",tickAm,tickoil,temp.amount, temp.oil, temp.price);
+                    }
+                }
+                else {
+                    printf("加油中,数据采集错误  ");
+                    printf("%d,%d,%d\n", temp.amount, temp.oil, temp.price);
+                }
+            }
+            g_xspCollDa.stopTime = Get_SysTick(); // 整个过程加油的停止时间
+            g_xspCollDa.bcheckDa = 0;
+            g_gunStatus[0].bsave = 0;
+        }
+        else if (g_xspCollDa.curstatus == STATUS_STOP) { // 停止后,又开始变化的,要判断一下当前的数据是继续加油还是数据的查询
+            eAmount = abs((int)temp.amount - (int)g_xspCollDa.lastDisp.amount);
+            eOil = abs((int)temp.oil - (int)g_xspCollDa.lastDisp.oil);
+            if ((eAmount < 100) && (eOil < 10)) {
+                printf("加油继续........(%010u) ", Get_SysTick());
+                printf("%d,%d,%d\n", temp.amount, temp.oil, temp.price);
+
+                memcpy(&g_xspCollDa.lastDisp, &temp, sizeof(dispData));
+                g_xspCollDa.lastTick = Get_SysTick();  // 只有在加油时,记录时间戳
+                g_xspCollDa.curstatus = STATUS_PROG;
+                g_xspCollDa.bSaveRecode = 1;
+            }
+            else {
+                printf("数据查询 ");
+                printf("%d,%d,%d\n", temp.amount, temp.oil, temp.price);
+                g_xspCollDa.curstatus = STATUS_CHECK;
+                g_xspCollDa.bcheckDa = 1;
+            }
+        }
+        else { // 加油停止,或是加油查询时 END, CHECK ,NULL 或是开始到加油中的转换过程
+            printf("数据显示(%d) ",g_xspCollDa.curstatus);
+            printf("%d,%d,%d\n", temp.amount, temp.oil, temp.price);
+            if(((gpio_input_bit_get(TQ_PORT,TQ_PIN)==RESET)||(tampTime<500)) &&(g_xspCollDa.bstart00==0)){ // 没有检测到00,但检测到抬枪信号的开始
+                if ((temp.amount > nostart.amount) || (temp.oil > nostart.oil)) {
+                    eAmount = abs((int)temp.amount - (int)nostart.amount);
+                    eOil = abs((int)temp.oil - (int)nostart.oil);
+                    //printf("aaaaaa = %d, eamout = %d, eoil = %d\n",Get_SysTick()-g_xspCollDa.lastTick,eAmount,eOil);
+                    if((eAmount < 100) && (eOil<50) ){ //判断是额增长且时间差小于500ms
+                        g_xspCollDa.startToprog++;
+                        g_xspCollDa.lastTick = Get_SysTick();
+                    }
+                    else g_xspCollDa.startToprog = 0;
+                    if(g_xspCollDa.startToprog > 5){
+                        if(g_xspCollDa.bSaveRecode==0x01){
+                            save_record_to_flash(0x00);
+                            g_xspCollDa.bSaveRecode = 0x00;
+                        }
+                        memcpy(&g_xspCollDa.lastDisp,&temp,sizeof(dispData));
+                        g_xspCollDa.lastTick1 = g_xspCollDa.lastTick;
+                        g_xspCollDa.lastTick = Get_SysTick();  // 只有在加油时,记录时间戳
+                        g_xspCollDa.curstatus = STATUS_PROG; // 加油过程
+
+                    }
+                    g_xspCollDa.bcheckDa = 0;
+
+                }
+                memcpy(&nostart, &temp, sizeof(dispData));
+                printf("aaaaaaaaaaaaaaaaaaa\n");
+            }
+
+        }
+
+        timeout_setValue(&g_xspCollDa.sameTimer, 3000);
+        timeout_start(&g_xspCollDa.sameTimer);
+
+    }
+    else {
+        if (timeout_isOut(&g_xspCollDa.sameTimer)) {
+            ret = get_data_from_7segCode(src7Da, &temp);
+            if(ret == 0) goto ERROR_END;
+            if (g_xspCollDa.curstatus == STATUS_PROG) {
+                memcpy(&g_xspCollDa.lastDisp, &temp, sizeof(dispData));
+                g_xspCollDa.curstatus = STATUS_STOP; // 加油停止
+                g_xspCollDa.bstart00 = 0;
+            }
+            if (g_xspCollDa.curstatus == STATUS_STOP) printf("加油中止,");
+            else if (g_xspCollDa.curstatus == STATUS_END) printf("加油结束,");
+            else if (g_xspCollDa.curstatus == STATUS_CHECK) {
+                printf("查询数据,");
+                g_xspCollDa.bcheckDa = 1;
+            }
+            printf("显示屏数据未变化.......(%010u)  ",Get_SysTick());
+            printf("%d,%d,%d\n", temp.amount, temp.oil, temp.price);
+
+
+            g_xspCollDa.startToprog = 0;
+            timeout_start(&g_xspCollDa.sameTimer);
+        }
+        else {
+            if((temp.amount==0x00) && (temp.oil==0x00)){//显示屏显示00的时候,
+                g_xspCollDa.lastTick = Get_SysTick();
+                g_xspCollDa.startTime = Get_SysTick();
+            }
+        }
+        return;
+    }
+
+    return;
+
+ERROR_END:
+    printf("数据采集错误:");
+    for(i=0;i<17;i++){
+        printf("%02x,",_7egDa[i]);
+    }
+    printf("\n");
+    g_xspCollDa.errorNum++;
+    return;
+}
+
+void anay_7eg(void)
+{
+    uint8_t i;//,j;
+    uint8_t index,pos;//,bindex
+//    dispData tempda;
+//    static uint8_t bfirst = 0;
+//    uint8_t ret = 0;
+
+
+
+    memset(g_7egDa,0,sizeof(g_7egDa));
+
+    if(g_devMsg.bHYdev == 0x00){
+        for(i=0;i<g_table1027.groupNum;i++){
+            pos = g_table1027.table[i][0]; // 片选,
+            index = g_table1027.table[i][1]; //位
+            if((pos >24) || (index >8)) continue; //最多24个片选,8个数据位
+            g_7egDa[i/8+1] |=  (((g_timeInfo.srcDa[pos]>>index)&0x01)<<(7-i%8));//(((g_srcDa[port][7-srcIndex]>>indexid)&0x01)<<(7-(i%8)));
+        }
+    }
+    else if(g_devMsg.bHYdev == 0x01) {
+        memcpy(g_7egDa,(char*)&g_timeInfo.srcDa[0],17);
+    }
+    else {
+        for(i=0;i<g_table1027.groupNum;i++){
+            pos = g_table1027.table[i][0]; // 片选,
+            index = g_table1027.table[i][1]; //位
+            if((pos >24) || (index >8)) continue; //最多24个片选,8个数据位
+            g_7egDa[i/8+1] |=  (((g_timeInfo.srcDa[pos]>>index)&0x01)<<(7-i%8));//(((g_srcDa[port][7-srcIndex]>>indexid)&0x01)<<(7-(i%8)));
+        }
+    }
+
+    //g_7egDa[12] = 0xFE;//g_7egDa[12]&(~0x01);
+    //g_7egDa[4] &= 0x3F;
+    check_gun_status_to_save_record();
+    analysis_7seg_code(g_7egDa);
+
+}
+void init_test_coll_data_info(uint8_t bstart)
+{
+    memset(&g_testCollDa,0,sizeof(testCollDa));
+    g_testCollDa.bTestCollDa = bstart;
+
+    if(g_devMsg.bHYdev == 0x01){
+        g_testCollDa.collTime = 20; // 100个节拍采集一次(即1ms)
+        init_comMsg();
+    }
+    else
+        g_testCollDa.collTime = 50; // 100个节拍采集一次(即1ms)
+
+}
+ComId _comMsg[3][2];
+
+void init_comMsg(void)
+{
+    _comMsg[U5_ID][0].comPort = 8;
+    _comMsg[U5_ID][0].comPin = 7;
+    _comMsg[U5_ID][1].comPort = 8;
+    _comMsg[U5_ID][1].comPin = 6;
+
+    _comMsg[U1_ID][0].comPort = 15;
+    _comMsg[U1_ID][0].comPin = 4;//5;
+    _comMsg[U1_ID][1].comPort = 15;
+    _comMsg[U1_ID][1].comPin = 3;
+
+    _comMsg[U4_ID][0].comPort = 6;
+    _comMsg[U4_ID][0].comPin = 5;
+    _comMsg[U4_ID][1].comPort = 6;
+    _comMsg[U4_ID][1].comPin = 4;
+}
+void deal_coll_data_com(void)
+{
+    volatile uint16_t i = 0,j = 0,k = 0,mm = 0,m=0, dealIndex = 0;
+    uint8_t val = 0,pos = 0,sameflag = 0,val1 = 0,bZero=0,bOne = 0;//,testi = 0;
+    static uint8_t  samecount = 0;
+    volatile static uint16_t curIndex = 0, dealnum = 1;
+    static uint32_t testflag = 0;
+    uint8_t comstatus = 0;
+
+//    uint8_t uid,cId,csId,pid,comval,bitval;
+
+    if((g_testCollDa.collNum == g_testCollDa.dealNum)) return;
+    if((g_testCollDa.bdealDa==0) && (g_testCollDa.collNum<2)) return;
+    dealIndex = ((g_testCollDa.collNum == 0) ? TEST_COLL_DA_MAX_NUM: g_testCollDa.collNum);
+    for(i=(curIndex+1);i<dealIndex;i++){
+        if(i == dealIndex) {printf("aaaaaaaaaaaaa\n");break;}
+        sameflag = 0;
+        for(j=0;j<TEST_COLL_GROUP;j++){
+            if((g_testCollDa.collDa[i-1][j]^g_testCollDa.collDa[i][j])) { // 不相同再处理位
+                for(k = 0;k <8;k++) {
+                    val = (g_testCollDa.collDa[i][j]>>k)&0x01;
+                    pos =  (j<<3) + 7- k; // j *8 + k;
+                    if(val != g_testCollDa.lastval[pos]){
+                        g_testCollDa.lastval[pos] = val;
+                        g_testCollDa.tcollNum[pos]++;
+                    }
+                    testflag++;
+                }
+                sameflag = 0;
+                samecount = 0;
+            }
+            else {
+                testflag += 8;
+                sameflag++;
+            }
+        }
+        dealnum++;
+        if(sameflag == (TEST_COLL_GROUP)){
+            memcpy(&g_testCollDa.lastDa[samecount][0],(char*)(&g_testCollDa.collDa[i][0]),TEST_COLL_GROUP);
+            samecount++;
+        }
+        else {
+            if(samecount>=SAME_GROUP) {
+                break;
+            }
+        }
+    }
+
+    if(samecount >=SAME_GROUP) {
+        if(i == (dealIndex)) curIndex = i-1;
+        else curIndex = i;
+        for(m=0;m<g_extimsg.groupNum;m++){
+            comstatus = (g_testCollDa.lastDa[0][g_extimsg.comPort[m]] >> g_extimsg.comPin[m])&0x01;
+            (comstatus == 0)?  (bZero++) : (bOne++);
+
+        }
+        comstatus = ((bZero>bOne)?0:1);
+        memset((char*)g_timeInfo.srcDa,0,sizeof(g_timeInfo.srcDa));
+        for(j=0;j<TEST_COLL_GROUP;j++){
+            for(k = 0;k <8;k++) {
+                val = (g_testCollDa.lastDa[0][j]>>k)&0x01;
+                if(val != comstatus) val1 = 1;
+                else val1 = 0;
+                g_timeInfo.srcDa[j] |= (val1<< k);
+            }
+        }
+        samecount = 0;
+        g_testCollDa.dealNum = i;
+        anay_7eg();
+    }
+    else {
+        curIndex = i-1;// dealIndex-1;
+        g_testCollDa.dealNum = i;//dealIndex;
+    }
+    if((g_testCollDa.bdealDa == 0x01)&& (dealnum ==(TEST_COLL_DA_MAX_NUM))) {
+
+//        for(i=0;i<192;i++){
+//            //if((i%16) == 0) printf("\n");
+//            //printf("%03d,",g_testCollDa.tcollNum[i]);
+//            g_testCollDa.tcollNum[i] = 0; // 这行必须有,确定放的位置
+//        }
+        memcpy(g_testCollDa.sendCollNum,g_testCollDa.tcollNum,192);
+        memset(g_testCollDa.tcollNum,0,192);
+        g_testCollDa.bdealDa = 0;
+        dealnum = 1;
+        curIndex = 0;
+        g_testCollDa.dealNum = 0;
+        //printf("test flag %d\n",testflag);
+        testflag = 0;
+        samecount = 0;
+    }
+}
+ComSrcDa g_comSrcDa;
+void deal_coll_data_HY(void)
+{
+    volatile uint16_t i = 0,j = 0,k = 0,mm = 0, m=0,dealIndex = 0;
+//    uint8_t val = 0,pos = 0,sameflag = 0,val1 = 0,bZero=0,bOne = 0,testi = 0;
+    static uint8_t  samecount = 0;
+    volatile static uint16_t curIndex = 0, dealnum = 1;
+    static uint32_t testflag = 0;
+//    uint8_t comstatus = 0;
+    uint8_t u1com0,flag;//u1com1,u4com0,u4com1,u5com0,u5com1,,valpos
+    uint8_t uid,cId,csId,pid,comval,bitval,num;
+
+    if((g_testCollDa.collNum == g_testCollDa.dealNum)) return;
+    if((g_testCollDa.bdealDa==0) && (g_testCollDa.collNum<6)) return;
+    dealIndex = ((g_testCollDa.collNum == 0) ? TEST_COLL_DA_MAX_NUM: g_testCollDa.collNum);
+    for(i=(curIndex+1);i<dealIndex;i++){
+        if(i == dealIndex) {printf("aaaaaaaaaaaaa\n");break;}
+//        sameflag = 0;
+//        u1com0 = (g_testCollDa.collDa[i][_comMsg[U1_ID][0].comPort] >>_comMsg[U1_ID][0].comPin)&0x01;
+//        u1com1 = (g_testCollDa.collDa[i][_comMsg[U1_ID][1].comPort] >>_comMsg[U1_ID][1].comPin)&0x01;
+
+//        u4com0 = (g_testCollDa.collDa[i][_comMsg[U4_ID][0].comPort] >>_comMsg[U4_ID][0].comPin)&0x01;
+//        u4com1 = (g_testCollDa.collDa[i][_comMsg[U4_ID][1].comPort] >>_comMsg[U4_ID][1].comPin)&0x01;
+
+//        u5com0 = (g_testCollDa.collDa[i][_comMsg[U5_ID][0].comPort] >>_comMsg[U5_ID][0].comPin)&0x01;
+//        u5com1 = (g_testCollDa.collDa[i][_comMsg[U5_ID][1].comPort] >>_comMsg[U5_ID][1].comPin)&0x01;
+
+        //printf("%d,%d,%d,%d,%d,%d\n",u1com0,u1com1,u4com0,u4com1,u5com0,u5com1);
+
+        for(j=0;j<3;j++){
+            for(k=0;k<2;k++){
+                flag = (0x01<<(j*2+k));
+
+                u1com0 = (g_testCollDa.collDa[i][_comMsg[U1_ID+j][k].comPort] >>_comMsg[U1_ID+j][k].comPin)&0x01;
+
+                if((u1com0 == 0x00) && (g_comSrcDa.daMsg[U1_ID+j][k].lastvl==0)&&((g_comSrcDa.flag&flag) !=flag)){
+                    num = g_comSrcDa.daMsg[U1_ID+j][k].num;
+                    memcpy(&g_comSrcDa.daMsg[U1_ID+j][k].tda[num][0],(char*)&g_testCollDa.collDa[i][0],TEST_COLL_GROUP);
+                    g_comSrcDa.daMsg[U1_ID+j][k].num++;
+
+                }
+                else {
+                    g_comSrcDa.daMsg[U1_ID+j][k].num = 0;
+
+                }
+                g_comSrcDa.daMsg[U1_ID+j][k].lastvl= u1com0;
+                if((g_comSrcDa.daMsg[U1_ID+j][k].num>5)&&((g_comSrcDa.flag&flag) !=flag)){
+                    g_comSrcDa.flag |= flag;
+                    g_comSrcDa.daMsg[U1_ID+j][k].num = 0;
+                    //valpos = (i - g_comSrcDa.daMsg[U1_ID+j][k].startpos)/2;
+                    memcpy(&g_comSrcDa.daMsg[U1_ID+j][k].da[0],&g_comSrcDa.daMsg[U1_ID+j][k].tda[3][0],TEST_COLL_GROUP);
+                    //break;
+                }
+                //printf("j=%d,k=%d,num = %d,flag = %02x\n",j,k,g_comSrcDa.daMsg[U1_ID+j][k].num,g_comSrcDa.flag);
+
+           }
+           if(g_comSrcDa.flag == 0x3F){
+               break;
+           }
+        }
+
+        dealnum++;
+        if(g_comSrcDa.flag == 0x3F){
+            g_comSrcDa.flag = 0;
+            samecount = 4;
+            break;
+        }
+    }
+
+    if(samecount >=3) {
+      //  printf("ccccccccccccc\n");
+        if(i == (dealIndex)) curIndex = i-1;
+        else curIndex = i;
+
+        memset((char*)g_timeInfo.srcDa,0,sizeof(g_timeInfo.srcDa));
+        for(mm=0;mm<128;mm++){
+            uid = g_neTable[mm].uId; // u1 u4 或 u5
+            cId = g_neTable[mm].comIndex; // com0 还是com1
+            csId = g_neTable[mm].csIndex; //
+            pid = g_neTable[mm].pinIndex;
+            if(csId ==0xFF || pid == 0xFF) continue;
+            comval = (g_comSrcDa.daMsg[uid][cId].da[_comMsg[uid][cId].comPort]>> _comMsg[uid][cId].comPin)&0x01;
+            bitval = (g_comSrcDa.daMsg[uid][cId].da[csId]>>pid)&0x01;
+            if(comval != bitval) g_timeInfo.srcDa[mm/8+1] |=  (0x01<<(7-mm%8));
+        }
+        samecount = 0;
+        g_testCollDa.dealNum = i;
+
+        anay_7eg();
+    }
+    else {
+        curIndex = i-1;// dealIndex-1;
+        g_testCollDa.dealNum = i;//dealIndex;
+    }
+    if((g_testCollDa.bdealDa == 0x01)&& (dealnum ==(TEST_COLL_DA_MAX_NUM))) {
+        memcpy(g_testCollDa.sendCollNum,g_testCollDa.tcollNum,192);
+        memset(g_testCollDa.tcollNum,0,192);
+        g_testCollDa.bdealDa = 0;
+        dealnum = 1;
+        curIndex = 0;
+        g_testCollDa.dealNum = 0;
+        //printf("test flag %d\n",testflag);
+        testflag = 0;
+        samecount = 0;
+    }
+}

+ 196 - 0
App/xspDataOpt.h

@@ -0,0 +1,196 @@
+#ifndef _XSPDATAOPT_H_
+#define _XSPDATAOPT_H_
+#include "../CMSIS/gd32f10x.h"
+#include "xspOptFlash.h"
+#include <string.h>
+#include "../Hardware/boardinit.h"
+
+#define XSP_SAVE_TIME  (1000*60*30)// 30分钟
+
+enum {
+    U1_ID = 0x00,
+    U4_ID = 0x01,
+    U5_ID = 0x02,
+};
+typedef struct _table_needle_{
+    uint8_t uId;
+    uint8_t comIndex; // 在那个com端下
+    uint8_t csIndex;  // 片选的索引
+    uint8_t pinIndex; // 管脚索引
+}__attribute__((packed))NeedleTable;
+
+typedef struct _com_data_msg_{
+    uint8_t num;
+    uint8_t lastvl;
+    uint8_t tda[10][24];
+    uint8_t da[24];
+}__attribute__((packed))comDaMsg;
+
+typedef struct _com_src_data_{
+    uint8_t flag; // 按位计算 3组com端 6组数据,共6个1,用3F表示
+    comDaMsg daMsg[3][2]; // 一共3组 每组中有两个小组
+}__attribute__((packed))ComSrcDa;
+
+typedef struct _table_com_{
+    uint8_t comPort;
+    uint8_t comPin;
+}__attribute__((packed))ComId;
+
+extern uint8_t g_7egDa[29];
+
+typedef struct display_data_{
+    uint32_t price; // 单价
+    uint32_t amount; // 金额
+    uint32_t oil;  // 油量
+}__attribute__((packed)) dispData;
+
+
+typedef union _c_to_u_ {
+    uint8_t  da8[16];
+    uint16_t da16[8];
+    uint32_t da32[4];
+    uint64_t da64[2];
+}__attribute__((packed)) UData;
+
+typedef struct _src_7seg_ {
+    uint8_t amount[6];
+    uint8_t oil[6];
+    uint8_t price[4];
+}__attribute__((packed)) Src7Seg;
+typedef union _data_src_7seg_ {
+    Src7Seg da;
+    UData uDa;
+    uint8_t val[16];
+}__attribute__((packed)) Usrc7SegDa;
+
+typedef struct _error_7seg_ {
+    uint8_t berror;
+}__attribute__((packed))Error7Seg;
+
+#define START_ID 1
+enum {
+    STATUS_NULL = 0x00, // 未初始化状态
+    STATUS_START = 0x01, // 加油开始
+    STATUS_PROG = 0x02, // 加油中
+    STATUS_END = 0x03, // 加油结束
+    STATUS_STOP = 0x04, // 加油停止
+    STATUS_CHECK = 0x05, // 数据查询
+};
+
+enum{
+    GUN_NULL = 0x00, // 未知
+    GUN_UP = 0x01, // 抬枪
+    GUN_DOWN = 0x02, // 挂枪
+};
+typedef struct xsp_coll_data_ {
+    Usrc7SegDa cur;		 // 原始的七段码记录
+    Usrc7SegDa last1;
+    Usrc7SegDa last2;
+    timeout_t sameTimer; // 相同数据的时间
+    uint8_t corrDa[16];
+    uint32_t startTime;  // 加油开始的时间
+    uint32_t stopTime;   // 加油结束时的时间
+    uint32_t gunUpTime;  // 抬枪的时间
+    uint32_t gunDnTime;  // 挂枪的时间
+    uint8_t gunStatus;
+    uint8_t  bcheckDa;   // 当前显示屏显示的数据是否是查询数据
+    uint8_t curstatus;   // 加油状态
+    dispData curDisp;	 // 解析好的数据记录
+    dispData lastDisp;   // 上一个需要存储的数据
+    dispData lastDisp1;  // 上上个数据,用于错误数据矫正
+    uint32_t lastTick1;  // 上上个加油的时间,用于错误数据矫正
+    uint32_t lastTick;   // 上一次记录的时间戳
+    uint32_t lastcomTick; // 只要变化不管数据的对错,就记录时间戳,
+    uint8_t bSaveRecode; // 是否需要存储当次的交易记录
+    uint32_t errorNum;   // 在加油开始的状态下,统计错误的次数
+    uint32_t  startToprog; // 小额增长变化次数(从加油开始,到加油中的判断过程
+    uint64_t lastTamout;
+    uint64_t lastToil;
+    uint8_t bcorrect; // 是否纠正
+    uint8_t bstart00; // 加油是从00开始的
+}__attribute__((packed)) XspCollDa;
+extern XspCollDa g_xspCollDa;
+
+typedef struct xsp_record_{
+    uint32_t recordId; // 记录ID
+    uint16_t bsend; // 0xff:没有发送 0x00:已经发送
+    uint8_t recodeMode; // 记录产生方式 0:逻辑产生 1:抬枪信号产生,3:按键产生
+    uint8_t priceUseCount; // 单价屏的索引
+    uint32_t amount;
+    uint32_t oil;
+    uint32_t price;
+    uint64_t tamount;
+    uint64_t toil;
+    uint32_t timer;// 记录时间
+    uint16_t bcorrect; // 用高8位表示是否是纠正数据 0:未纠正 1:纠正一位 2:计算纠正
+}__attribute__((packed)) xspRecord;
+
+typedef union xsp_data_info_{
+    uint8_t data[64];
+    xspRecord reDa;
+}__attribute__((packed)) XspDataInfo;
+extern XspDataInfo g_xspReDa;
+
+
+typedef struct _up_7seg_src_data_{
+    uint8_t bOpen;    // 是否开启 1:开启
+    uint8_t bAppointDev; // 是否指定的一个设备 0:否, 1:指令的设备为主 2:指定的设备为从
+    uint8_t bofflineTest; // 离线调试,主动上报
+    timeout_t upTime; // 上报的时长
+    uint8_t devMsg[17]; // 读取指令的从设备的8段数据,用于主设备问询从设备
+}__attribute__((packed))Up7segData;
+extern Up7segData g_up7segData;
+typedef enum {
+    LOW_LEVEL = 0x00,
+    HIGHT_LEVEL = 0x01,
+    LOW_HIGHT  = 0x02, // 由低变高
+    HIGHT_LOW  = 0x03, // 由高变低
+}gunstatus;
+#define GUN_STATUS_TIMER 50000 // 10ms  10000 // 1S,
+typedef struct gun_status_{
+    gunstatus curst; // 当前的状态
+    gunstatus lastst; // 上一次的状态
+    uint32_t timer; // 时间
+    uint8_t count;  // 检测次数 低电平的个数
+    uint8_t bsave;  // 是否已经挂枪需要存储数据
+}__attribute__((packed))GunStatus;
+
+/*-------探针板错误数据记录以及上传-------------*/
+typedef struct _xsp_err_da_{
+    timeout_t timer; // 数据不变的时间
+    uint8_t bsend; // 本条数据是否已经发送 1:已经发送,2:未发送,0:默认不需要处理
+    uint8_t segDa[29]; // 错误的七段码数据
+    uint8_t lastsegDa[29];
+}__attribute__((packed)) XspErrDa;
+extern XspErrDa g_xspErrDa;
+
+#define SAME_GROUP 3//1
+#define TEST_COLL_DA_MAX_NUM 1000
+#define TEST_COLL_GROUP 24
+typedef struct _test_coll_data_{ // 测试采集数据
+    volatile uint8_t collDa[TEST_COLL_DA_MAX_NUM][TEST_COLL_GROUP]; // 需要采集的数据
+    uint8_t lastDa[8][TEST_COLL_GROUP];
+    uint8_t tcollNum[TEST_COLL_GROUP*8];  // 存储每一位采集比较的结果
+    uint8_t lastval[TEST_COLL_GROUP*8];
+    uint8_t sendCollNum[TEST_COLL_GROUP*8];  // 需要上传的数据
+    uint8_t bTestCollDa;      //  是否是采集测试数据模式 1:是, 0:否
+    uint32_t collTime;        // 采集的时间, 多长时间采集一次
+    volatile uint16_t collNum;          // 记录采集的次数
+    uint16_t dealNum;          // 处理的次数
+    uint8_t bdealDa;           // 处理数据
+}__attribute__((packed)) testCollDa;
+extern testCollDa g_testCollDa;
+extern void init_test_coll_data_info(uint8_t bstart);
+extern void deal_coll_data_com(void);
+extern void deal_coll_data_HY(void);
+extern void init_xsp_run_data(void);
+
+
+extern void init_gun_status(void);
+extern void deal_gun_status(uint32_t tick);
+extern void anay_7eg(void);
+
+
+extern void init_comMsg(void);
+
+#endif

+ 369 - 0
App/xspOptFlash.c

@@ -0,0 +1,369 @@
+#include "xspOptFlash.h"
+#include "../Hardware/boardinit.h"
+#include "xspDataOpt.h"
+
+FlahOpt g_flashopt;
+/*-------------------------------------------------------------------------------
+ *  初始化
+ * ------------------------------------------------------------------------------*/
+void init_flash(void)
+{
+    g_flashopt.head = 0;
+    g_flashopt.tail  = 0;
+    g_flashopt.flag = FALSE;
+    g_flashopt.totalPage = 64; //一共64页
+    g_flashopt.pageRecord = 32; //  一页32条记录
+}
+
+/*-------------------------------------------------------------------------------------------
+ *  更新当前记录的上报标识 bsend ,将0xFF 更新为0x00, 说明已经上报
+ * ------------------------------------------------------------------------------------------*/
+static void update_bsend_to_0x00(uint32_t baseAddr)
+{
+    uint16_t data = 0x0000;
+    Flash_BufferWrite_uint16(baseAddr+4,&data,2);//正常的flash 写入
+    return;
+}
+
+/*-------------------------------------------------------------------------------
+ *  读取flash中的记录
+ *  返回值 1:成功  0:失败
+ * --------------------------------------------------------------------------------*/
+uint8_t read_flash(uint8_t *outda,uint8_t bupdateSend)
+{
+    uint32_t addr;
+    uint8_t curPage,curRecord;
+    if((g_flashopt.tail== g_flashopt.head) &&(g_flashopt.flag == FALSE)){ // 队列为空
+       // printf("没有新记录\r\n");
+        return 0;
+    }
+    curPage = g_flashopt.head/32;
+    curRecord = g_flashopt.head%32;
+    addr = START_FLASH_ADDR + curPage*PAGE_SIZE + curRecord*RECORD_SIZE;
+    Flash_BufferRead(addr,outda,64);//数据存入到outda中
+    if((1 == bupdateSend) &&(0xFFFFFFFF != *((uint32_t*)outda)) ) update_bsend_to_0x00(addr);
+    g_flashopt.head = (g_flashopt.head+1)%RECORD_FIFO;
+    if(g_flashopt.head == g_flashopt.tail) g_flashopt.flag = FALSE;
+    return 1;
+}
+
+/*-----------------------------------------------------------------------------------
+ *  写入
+ * ----------------------------------------------------------------------------------*/
+void write_flash(uint8_t *data)
+{
+    uint32_t addr;
+    uint8_t curPage,curRecord,ret;
+    if((g_flashopt.tail == g_flashopt.head) &&(g_flashopt.flag==TRUE)){ // fifo满了
+        printf("队列已满  tail=%d, head=%d\r\n",g_flashopt.tail,g_flashopt.head);
+        g_flashopt.head = (g_flashopt.head+1)%RECORD_FIFO;
+    }
+    curPage = g_flashopt.tail/32;
+    curRecord = g_flashopt.tail%32;
+    addr = START_FLASH_ADDR + curPage*PAGE_SIZE + curRecord*RECORD_SIZE;
+    if(curRecord==0){ // 第0条记录时 要擦除本页
+        Flash_RangeErase(addr,PAGE_SIZE);
+    }
+
+    ret = Flash_BufferWrite(addr,(uint32_t*)data,64);//正常的flash 写入
+    if(ret == 0) printf("++++++++++++++写入flash出错误\r\n");
+    g_flashopt.tail = (g_flashopt.tail+1)%RECORD_FIFO;
+    if(g_flashopt.tail == g_flashopt.head) g_flashopt.flag = TRUE;
+    printf("fifo head = %d, tail=%d\r\n",g_flashopt.head,g_flashopt.tail);
+
+}
+
+/*-------------------------------------------------------------------------------
+ *  读取
+ *  readsize:读取的字节数据
+ * --------------------------------------------------------------------------------*/
+void find_last_record(uint8_t pageIndex, uint8_t recordIndex, uint8_t readsize,uint8_t *outda)
+{
+    uint32_t addr;
+
+    addr = START_FLASH_ADDR + pageIndex*PAGE_SIZE + recordIndex*RECORD_SIZE;
+    Flash_BufferRead(addr,outda,readsize);//数据存入到outda中
+    return ;
+}
+#if( 1 )
+void find_fifo_head(void)
+{
+    uint8_t i=0,j=0;//,pageIndex = 0, recordIndex = 0,
+    uint8_t bfirst = 0;
+    uint32_t min = 0xFFFFFFFF;
+    tempRecord head;//,tail;
+    g_flashopt.head = 0;
+    for(i=0;i<g_flashopt.totalPage;i++){
+        for(j=0;j<g_flashopt.pageRecord;j++){
+            find_last_record(i,j,6,head.data);  // 一页的第一条记录
+            if(head.da.recordId != 0xFFFFFFFF){
+                if(head.da.bSend == 0xFFFF) {
+                    if(min>=head.da.recordId) {
+                        g_flashopt.head = i*g_flashopt.pageRecord + j;
+                        min = head.da.recordId;
+                    }
+                }
+            }
+            else if((head.da.recordId == 0xFFFFFFFF)&&(min == 0xFFFFFFFF)){
+                if(head.da.bSend == 0xFFFF && bfirst == 0){
+                    g_flashopt.head = i*g_flashopt.pageRecord + j;
+                    bfirst = 1;
+                }
+
+            }
+
+        }
+    }
+}
+
+void find_fifo_head00(void)
+{
+    uint8_t i=0,j=0,bfinish = 0;//,pageIndex = 0, recordIndex = 0;
+    uint32_t min = 0xFFFFFFFF;
+    tempRecord head,tail;
+
+    g_flashopt.head = 0;
+    for(i=0;i<g_flashopt.totalPage;i++){
+        find_last_record(i,0,6,head.data);  // 一页的第一条记录
+        find_last_record(i,31,6,tail.data); // 一页的最后一条记录
+        if(head.da.recordId != 0xFFFFFFFF) {
+            for(j=0;j<g_flashopt.pageRecord;j++){
+                find_last_record(i,j,6,head.data);
+                if((head.da.recordId != 0xFFFFFFFF)){
+                    if(head.da.bSend == 0xFFFF){
+                        if(min>head.da.recordId){
+                            min = head.da.recordId;
+                            g_flashopt.head = i*g_flashopt.pageRecord + j;
+                        }
+                    }
+                }
+            }
+        }
+        else if((head.da.recordId == 0xFFFFFFFF) &&(tail.da.recordId==0xFFFFFFFF)){
+            if(min != 0xFFFFFFFF) continue;
+            if((i+1) == g_flashopt.totalPage) break;
+            find_last_record(i+1,0,6,head.data);
+            if(head.da.recordId == 0xFFFFFFFF){
+                g_flashopt.head = i*g_flashopt.pageRecord;
+                break;
+            }
+            else {
+                if(head.da.bSend == 0xFFFF) {
+                    g_flashopt.head = i*g_flashopt.pageRecord;
+                    break;
+                }
+                else {
+                    for(j=1;j<g_flashopt.pageRecord;j++){
+                        find_last_record(i,j,6,head.data);
+                        if((head.da.recordId != 0xFFFFFFFF)){
+                            if(head.da.bSend == 0xFFFF){
+                                g_flashopt.head = i*g_flashopt.pageRecord + j;
+                                bfinish = 1;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if(bfinish == 1) break;
+    }
+   // g_flashopt.head = pageIndex*g_flashopt.pageRecord + recordIndex;
+}
+#else
+void find_fifo_head(void)
+{
+    uint8_t i=0,j=0,pageIndex = 0,recordIndex=0;
+    int8_t bfirst = -1,bfind = 0;
+    tempRecord head,tail;
+    uint32_t min = 0xFFFFFFFF;
+    for(i=0;i<g_flashopt.totalPage;i++){
+        find_last_record(i,0,6,head.data);
+        find_last_record(i,31,6,tail.data);
+        if(head.da.recordId == 0xFFFFFFFF && tail.da.recordId==0xFFFFFFFF) {
+            if((bfirst+1) == i){
+                if(i==0) pageIndex = 0;
+                else {
+                    find_last_record(i-1,31,6,tail.data); // 上一页的最后一条是否为FFFF
+                    if(tail.da.recordId==0xFFFFFFFF) pageIndex = bfirst-1;
+                    else pageIndex = bfirst;
+                }
+                recordIndex = 0;
+                break;
+            }
+            bfirst = i;
+            continue;
+        }
+        else if(head.da.recordId != 0xFFFFFFFF){
+            if(tail.da.bSend == 0x0000){
+                continue; // 如果最后一条为00,则表达这一页的数据都已经上发
+            }
+            if(head.da.bSend == 0xFFFF) {
+                min = head.da.recordId;
+            }
+            for(j=1;j<g_flashopt.pageRecord;j++){
+                find_last_record(i,j,6,head.data);
+                if(head.da.recordId == 0xFFFFFFFF) {
+                    if(head.da.bSend == 0xFFFF && min == 0xFFFFFFFF) {
+                        pageIndex = i;
+                        recordIndex = j;
+                        bfind = 1;
+                        break;
+                    }
+
+                }
+                else {
+                    if(head.da.bSend == 0xFFFF){
+                        if(min>head.da.recordId){
+                            pageIndex = i;
+                            recordIndex = j;
+                            min = head.da.recordId;
+                            bfind = 1;
+                            break;
+                        }
+                    }
+                }
+            }
+            if(bfind == 1) break;
+        }
+    }
+    g_flashopt.head = pageIndex*g_flashopt.pageRecord + recordIndex;
+}
+#endif
+/*-----------------------------------------------------------------------------------------
+ *  powerup 上电后,读取flash中的数据 且根据记录ID找出最新的一条记录的位置
+ *  以及找到最后一条没有上报的记录的位置
+ * ----------------------------------------------------------------------------------------*/
+void powerup_read_record_from_flash(uint8_t *recordDA)
+{
+    uint8_t i=0,j=0,bfind=0;//,curpage=0,currecord=0
+    uint8_t data[4] = {0};
+    uint32_t curread;//,maxread = 0;
+
+    /*for(i=0;i<g_flashopt.totalPage;i++){ // 找页
+        find_last_record(i,0,4,data);
+        curread = *((uint32_t*)data);
+        if(curread == 0xFFFFFFFF) {
+            curpage = (i==0 ? 0:i-1);
+            break;
+        }
+        else {
+                find_last_record(i,31,4,data); // 判断本页的最后一条,最后一条为空,则最大的记录就在本页
+                if(*((uint32_t*)data) == 0xFFFFFFFF){
+                    curpage = i;
+                    break;
+                }
+                else {
+                    if(maxread<curread){
+                    maxread = curread;
+                    }
+                    else {
+                        curpage = i;
+                        break;
+                    }
+                }
+        }
+    }
+    maxread = 0;
+    for(i=0;i<g_flashopt.pageRecord;i++){ // 找页中的最大记录
+        find_last_record(curpage,i,4,data);
+        curread = *((uint32_t*)data);
+        if(curread == 0xFFFFFFFF){
+            currecord = (i==0?0:i-1);
+            break;
+        }
+        else if(maxread<=curread){
+            maxread = curread;
+        }
+        else {
+            currecord = i;
+            break;
+        }
+        if((i == (g_flashopt.pageRecord-1))&&(currecord==0)){ // 说明为最后一条
+            currecord = 31;
+        }
+    }
+    g_flashopt.tail = curpage*g_flashopt.pageRecord+currecord;
+    g_flashopt.head = g_flashopt.tail;
+    g_flashopt.tail = (g_flashopt.tail==0?0:g_flashopt.tail+1);*/
+
+    for(i=0;i<g_flashopt.totalPage;i++){
+        for(j=0;j<g_flashopt.pageRecord;j++){
+            find_last_record(i,j,4,data);
+            curread = *((uint32_t*)data);
+            if(curread == 0xFFFFFFFF){
+                g_flashopt.tail = i*g_flashopt.pageRecord+j;
+                bfind = 1;
+                break;
+            }
+        }
+        if(bfind == 1) break;
+    }
+    g_flashopt.head = g_flashopt.tail-1; // 为了读取最后一条记录
+    read_flash(recordDA,0); // 读取的最后一条记录
+
+//    for(i=0;i<4;i++){
+//        update_bsend_to_0x00();
+//    }
+    find_fifo_head();// 找到fifo的头
+    printf("fifo_head = %d,fifo_tail = %d\r\n",g_flashopt.head, g_flashopt.tail);
+    if(g_flashopt.head != g_flashopt.tail) g_flashopt.flag = TRUE;
+    else {
+        g_flashopt.flag = FALSE;
+    }
+
+    if(g_xspReDa.reDa.recordId==0xFFFFFFFF)
+        memset(&g_xspReDa,0,64);
+    g_xspCollDa.lastTamout = g_xspReDa.reDa.tamount;
+    g_xspCollDa.lastToil = g_xspReDa.reDa.toil;
+    printf("读取flash中最后记录 record=%d,amout=%d,oil=%d,tamout=%lld,toil=%lld\r\n",\
+           g_xspReDa.reDa.recordId,g_xspReDa.reDa.amount,g_xspReDa.reDa.oil,
+           g_xspReDa.reDa.tamount,g_xspReDa.reDa.toil);
+    return;
+}
+/*-----------------------------------------------------------------------------
+ *  根据记录ID查找交易记录
+ * ----------------------------------------------------------------------------*/
+uint8_t xsp_check_point_record(uint32_t recordId,uint8_t *recordDa)
+{
+    uint8_t i=0,ret = 0,j=0;
+    uint8_t data[4] = {0};
+    uint32_t curread;
+
+    for(i=0;i<g_flashopt.totalPage;i++){ // 找页
+        find_last_record(i,0,4,data); // 读取本页第一条
+        curread = *((uint32_t*)data);
+        if(curread == 0xFFFFFFFF) continue;
+        else if(curread == recordId){ // 说明找到了
+            find_last_record(i,0,64,recordDa);
+            ret = 1;
+            break;
+        }
+        else if(curread <recordId){
+            find_last_record(i,63,4,data); // 读取本页是后一条
+            curread = *((uint32_t*)data);
+            if(curread < recordId) continue;
+            else if(curread == recordId) { // 说明找到了
+                find_last_record(i,63,64,recordDa);
+                ret = 1;
+                break;
+            }
+            else {
+                for(j=1;j<g_flashopt.pageRecord;j++){
+                    find_last_record(i,j,4,data); // 读取本页是后一条
+                    curread = *((uint32_t*)data);
+                    if(curread == recordId){
+                        find_last_record(i,j,64,recordDa);
+                        ret = 1;
+                        break;
+                    }
+                }
+                if(ret == 1) break;
+            }
+        }
+    }
+
+    return ret;
+}
+

+ 36 - 0
App/xspOptFlash.h

@@ -0,0 +1,36 @@
+#ifndef _XSPOPT_FLASH_H_
+#define _XSPOPT_FLASH_H_
+#include "gd32f10x.h"
+
+
+#define START_FLASH_ADDR 0x08060000
+#define END_FLAH_ADDR    0x0807FFFF
+#define PAGE_SIZE        2048
+#define RECORD_FIFO      2048 // 记录的条数一共有2048个
+#define RECORD_SIZE      64 // 一条记录的大小为64个字节
+typedef struct _flash_opt_{
+    uint16_t head; // 头地址
+    uint16_t tail; //  尾地址
+    bool flag; // 队列标志
+    uint8_t totalPage; // 总的页数 64页
+    uint8_t pageRecord; // 一页的总记录数
+   // uint8_t curPage;   // 当前页的索引 从0开始
+    //uint8_t curRecord; // 当前页的记录数
+}__attribute__((packed)) FlahOpt;
+typedef struct _temp_read_{
+    uint32_t recordId;
+    uint16_t bSend;
+}__attribute__((packed))tempread;
+typedef union _temp_record_{
+    tempread da;
+    uint8_t data[6];
+}__attribute__((packed))tempRecord;
+
+extern void init_flash(void);
+extern uint8_t read_flash(uint8_t *outda, uint8_t bupdateSend);
+extern void write_flash(uint8_t *data);
+extern uint8_t Flash_RangeErase(uint32_t FlashAddress, uint32_t Size);
+
+extern void powerup_read_record_from_flash(uint8_t *recordDA);
+extern uint8_t xsp_check_point_record(uint32_t recordId,uint8_t *recordDa);
+#endif

+ 1638 - 0
CMSIS/core_cm3.h

@@ -0,0 +1,1638 @@
+/**************************************************************************//**
+ * @file     core_cm3.h
+ * @brief    CMSIS Cortex-M3 Core Peripheral Access Layer Header File
+ * @version  V3.30
+ * @date     17. February 2014
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2014 ARM LIMITED
+
+   All rights reserved.
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   - Neither the name of ARM nor the names of its contributors may be used
+     to endorse or promote products derived from this software without
+     specific prior written permission.
+   *
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+   ---------------------------------------------------------------------------*/
+
+
+#if defined ( __ICCARM__ )
+ #pragma system_include  /* treat file as system include file for MISRA check */
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef __CORE_CM3_H_GENERIC
+#define __CORE_CM3_H_GENERIC
+
+/** \page CMSIS_MISRA_Exceptions  MISRA-C:2004 Compliance Exceptions
+  CMSIS violates the following MISRA-C:2004 rules:
+
+   \li Required Rule 8.5, object/function definition in header file.<br>
+     Function definitions in header files are used to allow 'inlining'.
+
+   \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
+     Unions are used for effective representation of core registers.
+
+   \li Advisory Rule 19.7, Function-like macro defined.<br>
+     Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ *                 CMSIS definitions
+ ******************************************************************************/
+/** \ingroup Cortex_M3
+  @{
+ */
+
+/*  CMSIS CM3 definitions */
+#define __CM3_CMSIS_VERSION_MAIN  (0x03)                                   /*!< [31:16] CMSIS HAL main version   */
+#define __CM3_CMSIS_VERSION_SUB   (0x20)                                   /*!< [15:0]  CMSIS HAL sub version    */
+#define __CM3_CMSIS_VERSION       ((__CM3_CMSIS_VERSION_MAIN << 16) | \
+                                    __CM3_CMSIS_VERSION_SUB          )     /*!< CMSIS HAL version number         */
+
+#define __CORTEX_M                (0x03)                                   /*!< Cortex-M Core                    */
+
+
+#if   defined ( __CC_ARM )
+  #define __ASM            __asm                                      /*!< asm keyword for ARM Compiler          */
+  #define __INLINE         __inline                                   /*!< inline keyword for ARM Compiler       */
+  #define __STATIC_INLINE  static __inline
+
+#elif defined ( __GNUC__ )
+  #define __ASM            __asm                                      /*!< asm keyword for GNU Compiler          */
+  #define __INLINE         inline                                     /*!< inline keyword for GNU Compiler       */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __ICCARM__ )
+  #define __ASM            __asm                                      /*!< asm keyword for IAR Compiler          */
+  #define __INLINE         inline                                     /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __TMS470__ )
+  #define __ASM            __asm                                      /*!< asm keyword for TI CCS Compiler       */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __TASKING__ )
+  #define __ASM            __asm                                      /*!< asm keyword for TASKING Compiler      */
+  #define __INLINE         inline                                     /*!< inline keyword for TASKING Compiler   */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __CSMC__ )  /* Cosmic */
+  #define __packed
+  #define __ASM            _asm                                      /*!< asm keyword for COSMIC Compiler      */
+  #define __INLINE         inline                                    /*use -pc99 on compile line !< inline keyword for COSMIC Compiler   */
+  #define __STATIC_INLINE  static inline
+
+#endif
+
+/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
+*/
+#define __FPU_USED       0
+
+#if defined ( __CC_ARM )
+  #if defined __TARGET_FPU_VFP
+    #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+
+#elif defined ( __GNUC__ )
+  #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+    #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+
+#elif defined ( __ICCARM__ )
+  #if defined __ARMVFP__
+    #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+
+#elif defined ( __TMS470__ )
+  #if defined __TI__VFP_SUPPORT____
+    #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+
+#elif defined ( __TASKING__ )
+  #if defined __FPU_VFP__
+    #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+
+#elif defined ( __CSMC__ )    /* Cosmic */
+  #if ( __CSMC__ & 0x400)    // FPU present for parser
+    #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+  #endif
+#endif
+
+#include <stdint.h>                      /* standard types definitions                      */
+#include <core_cmInstr.h>                /* Core Instruction Access                         */
+#include <core_cmFunc.h>                 /* Core Function Access                            */
+
+#endif /* __CORE_CM3_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM3_H_DEPENDANT
+#define __CORE_CM3_H_DEPENDANT
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+  #ifndef __CM3_REV
+    #define __CM3_REV               0x0200
+    #warning "__CM3_REV not defined in device header file; using default!"
+  #endif
+
+  #ifndef __MPU_PRESENT
+    #define __MPU_PRESENT             0
+    #warning "__MPU_PRESENT not defined in device header file; using default!"
+  #endif
+
+  #ifndef __NVIC_PRIO_BITS
+    #define __NVIC_PRIO_BITS          4
+    #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+  #endif
+
+  #ifndef __Vendor_SysTickConfig
+    #define __Vendor_SysTickConfig    0
+    #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+  #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+    \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+    <strong>IO Type Qualifiers</strong> are used
+    \li to specify the access to peripheral variables.
+    \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+  #define   __I     volatile             /*!< Defines 'read only' permissions                 */
+#else
+  #define   __I     volatile const       /*!< Defines 'read only' permissions                 */
+#endif
+#define     __O     volatile             /*!< Defines 'write only' permissions                */
+#define     __IO    volatile             /*!< Defines 'read / write' permissions              */
+
+/*@} end of group Cortex_M3 */
+
+
+
+/*******************************************************************************
+ *                 Register Abstraction
+  Core Register contain:
+  - Core Register
+  - Core NVIC Register
+  - Core SCB Register
+  - Core SysTick Register
+  - Core Debug Register
+  - Core MPU Register
+ ******************************************************************************/
+/** \defgroup CMSIS_core_register Defines and Type Definitions
+    \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_CORE  Status and Control Registers
+    \brief  Core Register type definitions.
+  @{
+ */
+
+/** \brief  Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+  struct
+  {
+#if (__CORTEX_M != 0x04)
+    uint32_t _reserved0:27;              /*!< bit:  0..26  Reserved                           */
+#else
+    uint32_t _reserved0:16;              /*!< bit:  0..15  Reserved                           */
+    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags        */
+    uint32_t _reserved1:7;               /*!< bit: 20..26  Reserved                           */
+#endif
+    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag          */
+    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag       */
+    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag          */
+    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag           */
+    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag       */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} APSR_Type;
+
+
+/** \brief  Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number                   */
+    uint32_t _reserved0:23;              /*!< bit:  9..31  Reserved                           */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} IPSR_Type;
+
+
+/** \brief  Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number                   */
+#if (__CORTEX_M != 0x04)
+    uint32_t _reserved0:15;              /*!< bit:  9..23  Reserved                           */
+#else
+    uint32_t _reserved0:7;               /*!< bit:  9..15  Reserved                           */
+    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags        */
+    uint32_t _reserved1:4;               /*!< bit: 20..23  Reserved                           */
+#endif
+    uint32_t T:1;                        /*!< bit:     24  Thumb bit        (read 0)          */
+    uint32_t IT:2;                       /*!< bit: 25..26  saved IT state   (read 0)          */
+    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag          */
+    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag       */
+    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag          */
+    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag           */
+    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag       */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} xPSR_Type;
+
+
+/** \brief  Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t nPRIV:1;                    /*!< bit:      0  Execution privilege in Thread mode */
+    uint32_t SPSEL:1;                    /*!< bit:      1  Stack to be used                   */
+    uint32_t FPCA:1;                     /*!< bit:      2  FP extension active flag           */
+    uint32_t _reserved0:29;              /*!< bit:  3..31  Reserved                           */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} CONTROL_Type;
+
+/*@} end of group CMSIS_CORE */
+
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_NVIC  Nested Vectored Interrupt Controller (NVIC)
+    \brief      Type definitions for the NVIC Registers
+  @{
+ */
+
+/** \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
+       uint32_t RESERVED0[24];
+  __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
+       uint32_t RSERVED1[24];
+  __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
+       uint32_t RESERVED2[24];
+  __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
+       uint32_t RESERVED3[24];
+  __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
+       uint32_t RESERVED4[56];
+  __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
+       uint32_t RESERVED5[644];
+  __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
+}  NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos                 0                                          /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk                (0x1FFUL << NVIC_STIR_INTID_Pos)            /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SCB     System Control Block (SCB)
+    \brief      Type definitions for the System Control Block Registers
+  @{
+ */
+
+/** \brief  Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+  __I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
+  __IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
+  __IO uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */
+  __IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
+  __IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
+  __IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
+  __IO uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */
+  __IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
+  __IO uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */
+  __IO uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */
+  __IO uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */
+  __IO uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */
+  __IO uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */
+  __IO uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */
+  __I  uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */
+  __I  uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */
+  __I  uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */
+  __I  uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */
+  __I  uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */
+       uint32_t RESERVED0[5];
+  __IO uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos          24                                             /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk          (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos)          /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos              20                                             /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk              (0xFUL << SCB_CPUID_VARIANT_Pos)               /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos         16                                             /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk         (0xFUL << SCB_CPUID_ARCHITECTURE_Pos)          /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos                4                                             /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk               (0xFFFUL << SCB_CPUID_PARTNO_Pos)              /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos              0                                             /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk             (0xFUL << SCB_CPUID_REVISION_Pos)              /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos            31                                             /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk            (1UL << SCB_ICSR_NMIPENDSET_Pos)               /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos             28                                             /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk             (1UL << SCB_ICSR_PENDSVSET_Pos)                /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos             27                                             /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk             (1UL << SCB_ICSR_PENDSVCLR_Pos)                /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos             26                                             /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk             (1UL << SCB_ICSR_PENDSTSET_Pos)                /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos             25                                             /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk             (1UL << SCB_ICSR_PENDSTCLR_Pos)                /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos            23                                             /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk            (1UL << SCB_ICSR_ISRPREEMPT_Pos)               /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos            22                                             /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk            (1UL << SCB_ICSR_ISRPENDING_Pos)               /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos           12                                             /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk           (0x1FFUL << SCB_ICSR_VECTPENDING_Pos)          /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos             11                                             /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk             (1UL << SCB_ICSR_RETTOBASE_Pos)                /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos             0                                             /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk            (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos)           /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#if (__CM3_REV < 0x0201)                   /* core r2p1 */
+#define SCB_VTOR_TBLBASE_Pos               29                                             /*!< SCB VTOR: TBLBASE Position */
+#define SCB_VTOR_TBLBASE_Msk               (1UL << SCB_VTOR_TBLBASE_Pos)                  /*!< SCB VTOR: TBLBASE Mask */
+
+#define SCB_VTOR_TBLOFF_Pos                 7                                             /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk                (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos)            /*!< SCB VTOR: TBLOFF Mask */
+#else
+#define SCB_VTOR_TBLOFF_Pos                 7                                             /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk                (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos)           /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos              16                                             /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk              (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos)            /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos          16                                             /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk          (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos)        /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos            15                                             /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk            (1UL << SCB_AIRCR_ENDIANESS_Pos)               /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos              8                                             /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk             (7UL << SCB_AIRCR_PRIGROUP_Pos)                /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos           2                                             /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk          (1UL << SCB_AIRCR_SYSRESETREQ_Pos)             /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos         1                                             /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk        (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos)           /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos             0                                             /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk            (1UL << SCB_AIRCR_VECTRESET_Pos)               /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos               4                                             /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk              (1UL << SCB_SCR_SEVONPEND_Pos)                 /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos               2                                             /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk              (1UL << SCB_SCR_SLEEPDEEP_Pos)                 /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos             1                                             /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk            (1UL << SCB_SCR_SLEEPONEXIT_Pos)               /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos                9                                             /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk               (1UL << SCB_CCR_STKALIGN_Pos)                  /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos               8                                             /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk              (1UL << SCB_CCR_BFHFNMIGN_Pos)                 /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos               4                                             /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk              (1UL << SCB_CCR_DIV_0_TRP_Pos)                 /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos             3                                             /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk            (1UL << SCB_CCR_UNALIGN_TRP_Pos)               /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos            1                                             /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk           (1UL << SCB_CCR_USERSETMPEND_Pos)              /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos          0                                             /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk         (1UL << SCB_CCR_NONBASETHRDENA_Pos)            /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos          18                                             /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk          (1UL << SCB_SHCSR_USGFAULTENA_Pos)             /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos          17                                             /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk          (1UL << SCB_SHCSR_BUSFAULTENA_Pos)             /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos          16                                             /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk          (1UL << SCB_SHCSR_MEMFAULTENA_Pos)             /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos         15                                             /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk         (1UL << SCB_SHCSR_SVCALLPENDED_Pos)            /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos       14                                             /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk       (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos)          /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos       13                                             /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk       (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos)          /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos       12                                             /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk       (1UL << SCB_SHCSR_USGFAULTPENDED_Pos)          /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos           11                                             /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk           (1UL << SCB_SHCSR_SYSTICKACT_Pos)              /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos            10                                             /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk            (1UL << SCB_SHCSR_PENDSVACT_Pos)               /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos            8                                             /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk           (1UL << SCB_SHCSR_MONITORACT_Pos)              /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos             7                                             /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk            (1UL << SCB_SHCSR_SVCALLACT_Pos)               /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos           3                                             /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk          (1UL << SCB_SHCSR_USGFAULTACT_Pos)             /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos           1                                             /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk          (1UL << SCB_SHCSR_BUSFAULTACT_Pos)             /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos           0                                             /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk          (1UL << SCB_SHCSR_MEMFAULTACT_Pos)             /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Registers Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos            16                                             /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk            (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos)          /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos             8                                             /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk            (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos)            /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos             0                                             /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk            (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos)            /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* SCB Hard Fault Status Registers Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos              31                                             /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk              (1UL << SCB_HFSR_DEBUGEVT_Pos)                 /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos                30                                             /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk                (1UL << SCB_HFSR_FORCED_Pos)                   /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos                1                                             /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk               (1UL << SCB_HFSR_VECTTBL_Pos)                  /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos               4                                             /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk              (1UL << SCB_DFSR_EXTERNAL_Pos)                 /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos                 3                                             /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk                (1UL << SCB_DFSR_VCATCH_Pos)                   /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos                2                                             /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk               (1UL << SCB_DFSR_DWTTRAP_Pos)                  /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos                   1                                             /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk                  (1UL << SCB_DFSR_BKPT_Pos)                     /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos                 0                                             /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk                (1UL << SCB_DFSR_HALTED_Pos)                   /*!< SCB DFSR: HALTED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+    \brief      Type definitions for the System Control and ID Register not in the SCB
+  @{
+ */
+
+/** \brief  Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+       uint32_t RESERVED0[1];
+  __I  uint32_t ICTR;                    /*!< Offset: 0x004 (R/ )  Interrupt Controller Type Register      */
+#if ((defined __CM3_REV) && (__CM3_REV >= 0x200))
+  __IO uint32_t ACTLR;                   /*!< Offset: 0x008 (R/W)  Auxiliary Control Register      */
+#else
+       uint32_t RESERVED1[1];
+#endif
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos         0                                          /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk        (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos)      /*!< ICTR: INTLINESNUM Mask */
+
+/* Auxiliary Control Register Definitions */
+
+#define SCnSCB_ACTLR_DISFOLD_Pos            2                                          /*!< ACTLR: DISFOLD Position */
+#define SCnSCB_ACTLR_DISFOLD_Msk           (1UL << SCnSCB_ACTLR_DISFOLD_Pos)           /*!< ACTLR: DISFOLD Mask */
+
+#define SCnSCB_ACTLR_DISDEFWBUF_Pos         1                                          /*!< ACTLR: DISDEFWBUF Position */
+#define SCnSCB_ACTLR_DISDEFWBUF_Msk        (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos)        /*!< ACTLR: DISDEFWBUF Mask */
+
+#define SCnSCB_ACTLR_DISMCYCINT_Pos         0                                          /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk        (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos)        /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SysTick     System Tick Timer (SysTick)
+    \brief      Type definitions for the System Timer Registers.
+  @{
+ */
+
+/** \brief  Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+  __IO uint32_t CTRL;                    /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
+  __IO uint32_t LOAD;                    /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register       */
+  __IO uint32_t VAL;                     /*!< Offset: 0x008 (R/W)  SysTick Current Value Register      */
+  __I  uint32_t CALIB;                   /*!< Offset: 0x00C (R/ )  SysTick Calibration Register        */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos         16                                             /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk         (1UL << SysTick_CTRL_COUNTFLAG_Pos)            /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk         (1UL << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk           (1UL << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk            (1UL << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos             0                                             /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos)        /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos            31                                             /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk            (1UL << SysTick_CALIB_NOREF_Pos)               /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos             30                                             /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk             (1UL << SysTick_CALIB_SKEW_Pos)                /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos             0                                             /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_ITM     Instrumentation Trace Macrocell (ITM)
+    \brief      Type definitions for the Instrumentation Trace Macrocell (ITM)
+  @{
+ */
+
+/** \brief  Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+  __O  union
+  {
+    __O  uint8_t    u8;                  /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 8-bit                   */
+    __O  uint16_t   u16;                 /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 16-bit                  */
+    __O  uint32_t   u32;                 /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 32-bit                  */
+  }  PORT [32];                          /*!< Offset: 0x000 ( /W)  ITM Stimulus Port Registers               */
+       uint32_t RESERVED0[864];
+  __IO uint32_t TER;                     /*!< Offset: 0xE00 (R/W)  ITM Trace Enable Register                 */
+       uint32_t RESERVED1[15];
+  __IO uint32_t TPR;                     /*!< Offset: 0xE40 (R/W)  ITM Trace Privilege Register              */
+       uint32_t RESERVED2[15];
+  __IO uint32_t TCR;                     /*!< Offset: 0xE80 (R/W)  ITM Trace Control Register                */
+       uint32_t RESERVED3[29];
+  __O  uint32_t IWR;                     /*!< Offset: 0xEF8 ( /W)  ITM Integration Write Register            */
+  __I  uint32_t IRR;                     /*!< Offset: 0xEFC (R/ )  ITM Integration Read Register             */
+  __IO uint32_t IMCR;                    /*!< Offset: 0xF00 (R/W)  ITM Integration Mode Control Register     */
+       uint32_t RESERVED4[43];
+  __O  uint32_t LAR;                     /*!< Offset: 0xFB0 ( /W)  ITM Lock Access Register                  */
+  __I  uint32_t LSR;                     /*!< Offset: 0xFB4 (R/ )  ITM Lock Status Register                  */
+       uint32_t RESERVED5[6];
+  __I  uint32_t PID4;                    /*!< Offset: 0xFD0 (R/ )  ITM Peripheral Identification Register #4 */
+  __I  uint32_t PID5;                    /*!< Offset: 0xFD4 (R/ )  ITM Peripheral Identification Register #5 */
+  __I  uint32_t PID6;                    /*!< Offset: 0xFD8 (R/ )  ITM Peripheral Identification Register #6 */
+  __I  uint32_t PID7;                    /*!< Offset: 0xFDC (R/ )  ITM Peripheral Identification Register #7 */
+  __I  uint32_t PID0;                    /*!< Offset: 0xFE0 (R/ )  ITM Peripheral Identification Register #0 */
+  __I  uint32_t PID1;                    /*!< Offset: 0xFE4 (R/ )  ITM Peripheral Identification Register #1 */
+  __I  uint32_t PID2;                    /*!< Offset: 0xFE8 (R/ )  ITM Peripheral Identification Register #2 */
+  __I  uint32_t PID3;                    /*!< Offset: 0xFEC (R/ )  ITM Peripheral Identification Register #3 */
+  __I  uint32_t CID0;                    /*!< Offset: 0xFF0 (R/ )  ITM Component  Identification Register #0 */
+  __I  uint32_t CID1;                    /*!< Offset: 0xFF4 (R/ )  ITM Component  Identification Register #1 */
+  __I  uint32_t CID2;                    /*!< Offset: 0xFF8 (R/ )  ITM Component  Identification Register #2 */
+  __I  uint32_t CID3;                    /*!< Offset: 0xFFC (R/ )  ITM Component  Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos                0                                             /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk               (0xFUL << ITM_TPR_PRIVMASK_Pos)                /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos                   23                                             /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk                   (1UL << ITM_TCR_BUSY_Pos)                      /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos             16                                             /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk             (0x7FUL << ITM_TCR_TraceBusID_Pos)             /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos                10                                             /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk                (3UL << ITM_TCR_GTSFREQ_Pos)                   /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos              8                                             /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk             (3UL << ITM_TCR_TSPrescale_Pos)                /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos                  4                                             /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk                 (1UL << ITM_TCR_SWOENA_Pos)                    /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos                  3                                             /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk                 (1UL << ITM_TCR_DWTENA_Pos)                    /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos                 2                                             /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk                (1UL << ITM_TCR_SYNCENA_Pos)                   /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos                   1                                             /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk                  (1UL << ITM_TCR_TSENA_Pos)                     /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos                  0                                             /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk                 (1UL << ITM_TCR_ITMENA_Pos)                    /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos                0                                             /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk               (1UL << ITM_IWR_ATVALIDM_Pos)                  /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos                0                                             /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk               (1UL << ITM_IRR_ATREADYM_Pos)                  /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos            0                                             /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk           (1UL << ITM_IMCR_INTEGRATION_Pos)              /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos                 2                                             /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk                (1UL << ITM_LSR_ByteAcc_Pos)                   /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos                  1                                             /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk                 (1UL << ITM_LSR_Access_Pos)                    /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos                 0                                             /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk                (1UL << ITM_LSR_Present_Pos)                   /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_DWT     Data Watchpoint and Trace (DWT)
+    \brief      Type definitions for the Data Watchpoint and Trace (DWT)
+  @{
+ */
+
+/** \brief  Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+  __IO uint32_t CTRL;                    /*!< Offset: 0x000 (R/W)  Control Register                          */
+  __IO uint32_t CYCCNT;                  /*!< Offset: 0x004 (R/W)  Cycle Count Register                      */
+  __IO uint32_t CPICNT;                  /*!< Offset: 0x008 (R/W)  CPI Count Register                        */
+  __IO uint32_t EXCCNT;                  /*!< Offset: 0x00C (R/W)  Exception Overhead Count Register         */
+  __IO uint32_t SLEEPCNT;                /*!< Offset: 0x010 (R/W)  Sleep Count Register                      */
+  __IO uint32_t LSUCNT;                  /*!< Offset: 0x014 (R/W)  LSU Count Register                        */
+  __IO uint32_t FOLDCNT;                 /*!< Offset: 0x018 (R/W)  Folded-instruction Count Register         */
+  __I  uint32_t PCSR;                    /*!< Offset: 0x01C (R/ )  Program Counter Sample Register           */
+  __IO uint32_t COMP0;                   /*!< Offset: 0x020 (R/W)  Comparator Register 0                     */
+  __IO uint32_t MASK0;                   /*!< Offset: 0x024 (R/W)  Mask Register 0                           */
+  __IO uint32_t FUNCTION0;               /*!< Offset: 0x028 (R/W)  Function Register 0                       */
+       uint32_t RESERVED0[1];
+  __IO uint32_t COMP1;                   /*!< Offset: 0x030 (R/W)  Comparator Register 1                     */
+  __IO uint32_t MASK1;                   /*!< Offset: 0x034 (R/W)  Mask Register 1                           */
+  __IO uint32_t FUNCTION1;               /*!< Offset: 0x038 (R/W)  Function Register 1                       */
+       uint32_t RESERVED1[1];
+  __IO uint32_t COMP2;                   /*!< Offset: 0x040 (R/W)  Comparator Register 2                     */
+  __IO uint32_t MASK2;                   /*!< Offset: 0x044 (R/W)  Mask Register 2                           */
+  __IO uint32_t FUNCTION2;               /*!< Offset: 0x048 (R/W)  Function Register 2                       */
+       uint32_t RESERVED2[1];
+  __IO uint32_t COMP3;                   /*!< Offset: 0x050 (R/W)  Comparator Register 3                     */
+  __IO uint32_t MASK3;                   /*!< Offset: 0x054 (R/W)  Mask Register 3                           */
+  __IO uint32_t FUNCTION3;               /*!< Offset: 0x058 (R/W)  Function Register 3                       */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos               28                                          /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk               (0xFUL << DWT_CTRL_NUMCOMP_Pos)             /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos              27                                          /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk              (0x1UL << DWT_CTRL_NOTRCPKT_Pos)            /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos             26                                          /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk             (0x1UL << DWT_CTRL_NOEXTTRIG_Pos)           /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos              25                                          /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk              (0x1UL << DWT_CTRL_NOCYCCNT_Pos)            /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos              24                                          /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk              (0x1UL << DWT_CTRL_NOPRFCNT_Pos)            /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos             22                                          /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk             (0x1UL << DWT_CTRL_CYCEVTENA_Pos)           /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos            21                                          /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk            (0x1UL << DWT_CTRL_FOLDEVTENA_Pos)          /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos             20                                          /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk             (0x1UL << DWT_CTRL_LSUEVTENA_Pos)           /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos           19                                          /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk           (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos)         /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos             18                                          /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk             (0x1UL << DWT_CTRL_EXCEVTENA_Pos)           /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos             17                                          /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk             (0x1UL << DWT_CTRL_CPIEVTENA_Pos)           /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos             16                                          /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk             (0x1UL << DWT_CTRL_EXCTRCENA_Pos)           /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos            12                                          /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk            (0x1UL << DWT_CTRL_PCSAMPLENA_Pos)          /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos               10                                          /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk               (0x3UL << DWT_CTRL_SYNCTAP_Pos)             /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos                 9                                          /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk                (0x1UL << DWT_CTRL_CYCTAP_Pos)              /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos               5                                          /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk              (0xFUL << DWT_CTRL_POSTINIT_Pos)            /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos             1                                          /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk            (0xFUL << DWT_CTRL_POSTPRESET_Pos)          /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos              0                                          /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk             (0x1UL << DWT_CTRL_CYCCNTENA_Pos)           /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos               0                                          /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk              (0xFFUL << DWT_CPICNT_CPICNT_Pos)           /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos               0                                          /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk              (0xFFUL << DWT_EXCCNT_EXCCNT_Pos)           /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos           0                                          /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk          (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos)       /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos               0                                          /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk              (0xFFUL << DWT_LSUCNT_LSUCNT_Pos)           /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos             0                                          /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk            (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos)         /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos                   0                                          /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk                  (0x1FUL << DWT_MASK_MASK_Pos)               /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos           24                                          /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk           (0x1UL << DWT_FUNCTION_MATCHED_Pos)         /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos        16                                          /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk        (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos)      /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos        12                                          /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk        (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos)      /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos         10                                          /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk         (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos)       /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos            9                                          /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk           (0x1UL << DWT_FUNCTION_LNK1ENA_Pos)         /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos         8                                          /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk        (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos)      /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos           7                                          /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk          (0x1UL << DWT_FUNCTION_CYCMATCH_Pos)        /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos          5                                          /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk         (0x1UL << DWT_FUNCTION_EMITRANGE_Pos)       /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos           0                                          /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk          (0xFUL << DWT_FUNCTION_FUNCTION_Pos)        /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_TPI     Trace Port Interface (TPI)
+    \brief      Type definitions for the Trace Port Interface (TPI)
+  @{
+ */
+
+/** \brief  Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+  __IO uint32_t SSPSR;                   /*!< Offset: 0x000 (R/ )  Supported Parallel Port Size Register     */
+  __IO uint32_t CSPSR;                   /*!< Offset: 0x004 (R/W)  Current Parallel Port Size Register */
+       uint32_t RESERVED0[2];
+  __IO uint32_t ACPR;                    /*!< Offset: 0x010 (R/W)  Asynchronous Clock Prescaler Register */
+       uint32_t RESERVED1[55];
+  __IO uint32_t SPPR;                    /*!< Offset: 0x0F0 (R/W)  Selected Pin Protocol Register */
+       uint32_t RESERVED2[131];
+  __I  uint32_t FFSR;                    /*!< Offset: 0x300 (R/ )  Formatter and Flush Status Register */
+  __IO uint32_t FFCR;                    /*!< Offset: 0x304 (R/W)  Formatter and Flush Control Register */
+  __I  uint32_t FSCR;                    /*!< Offset: 0x308 (R/ )  Formatter Synchronization Counter Register */
+       uint32_t RESERVED3[759];
+  __I  uint32_t TRIGGER;                 /*!< Offset: 0xEE8 (R/ )  TRIGGER */
+  __I  uint32_t FIFO0;                   /*!< Offset: 0xEEC (R/ )  Integration ETM Data */
+  __I  uint32_t ITATBCTR2;               /*!< Offset: 0xEF0 (R/ )  ITATBCTR2 */
+       uint32_t RESERVED4[1];
+  __I  uint32_t ITATBCTR0;               /*!< Offset: 0xEF8 (R/ )  ITATBCTR0 */
+  __I  uint32_t FIFO1;                   /*!< Offset: 0xEFC (R/ )  Integration ITM Data */
+  __IO uint32_t ITCTRL;                  /*!< Offset: 0xF00 (R/W)  Integration Mode Control */
+       uint32_t RESERVED5[39];
+  __IO uint32_t CLAIMSET;                /*!< Offset: 0xFA0 (R/W)  Claim tag set */
+  __IO uint32_t CLAIMCLR;                /*!< Offset: 0xFA4 (R/W)  Claim tag clear */
+       uint32_t RESERVED7[8];
+  __I  uint32_t DEVID;                   /*!< Offset: 0xFC8 (R/ )  TPIU_DEVID */
+  __I  uint32_t DEVTYPE;                 /*!< Offset: 0xFCC (R/ )  TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos              0                                          /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk             (0x1FFFUL << TPI_ACPR_PRESCALER_Pos)        /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos                 0                                          /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk                (0x3UL << TPI_SPPR_TXMODE_Pos)              /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos              3                                          /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk             (0x1UL << TPI_FFSR_FtNonStop_Pos)           /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos              2                                          /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk             (0x1UL << TPI_FFSR_TCPresent_Pos)           /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos              1                                          /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk             (0x1UL << TPI_FFSR_FtStopped_Pos)           /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos               0                                          /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk              (0x1UL << TPI_FFSR_FlInProg_Pos)            /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos                 8                                          /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk                (0x1UL << TPI_FFCR_TrigIn_Pos)              /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos                1                                          /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk               (0x1UL << TPI_FFCR_EnFCont_Pos)             /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos             0                                          /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk            (0x1UL << TPI_TRIGGER_TRIGGER_Pos)          /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos          29                                          /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk          (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos)        /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos        27                                          /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk        (0x3UL << TPI_FIFO0_ITM_bytecount_Pos)      /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos          26                                          /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk          (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos)        /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos        24                                          /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk        (0x3UL << TPI_FIFO0_ETM_bytecount_Pos)      /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos                 16                                          /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk                 (0xFFUL << TPI_FIFO0_ETM2_Pos)              /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos                  8                                          /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk                 (0xFFUL << TPI_FIFO0_ETM1_Pos)              /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos                  0                                          /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk                 (0xFFUL << TPI_FIFO0_ETM0_Pos)              /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY_Pos           0                                          /*!< TPI ITATBCTR2: ATREADY Position */
+#define TPI_ITATBCTR2_ATREADY_Msk          (0x1UL << TPI_ITATBCTR2_ATREADY_Pos)        /*!< TPI ITATBCTR2: ATREADY Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos          29                                          /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk          (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos)        /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos        27                                          /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk        (0x3UL << TPI_FIFO1_ITM_bytecount_Pos)      /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos          26                                          /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk          (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos)        /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos        24                                          /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk        (0x3UL << TPI_FIFO1_ETM_bytecount_Pos)      /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos                 16                                          /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk                 (0xFFUL << TPI_FIFO1_ITM2_Pos)              /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos                  8                                          /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk                 (0xFFUL << TPI_FIFO1_ITM1_Pos)              /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos                  0                                          /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk                 (0xFFUL << TPI_FIFO1_ITM0_Pos)              /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY_Pos           0                                          /*!< TPI ITATBCTR0: ATREADY Position */
+#define TPI_ITATBCTR0_ATREADY_Msk          (0x1UL << TPI_ITATBCTR0_ATREADY_Pos)        /*!< TPI ITATBCTR0: ATREADY Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos                 0                                          /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk                (0x1UL << TPI_ITCTRL_Mode_Pos)              /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos             11                                          /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk             (0x1UL << TPI_DEVID_NRZVALID_Pos)           /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos            10                                          /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk            (0x1UL << TPI_DEVID_MANCVALID_Pos)          /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos             9                                          /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk            (0x1UL << TPI_DEVID_PTINVALID_Pos)          /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos              6                                          /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk             (0x7UL << TPI_DEVID_MinBufSz_Pos)           /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos             5                                          /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk            (0x1UL << TPI_DEVID_AsynClkIn_Pos)          /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos          0                                          /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk         (0x1FUL << TPI_DEVID_NrTraceInput_Pos)      /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos             0                                          /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk            (0xFUL << TPI_DEVTYPE_SubType_Pos)          /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos           4                                          /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk          (0xFUL << TPI_DEVTYPE_MajorType_Pos)        /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if (__MPU_PRESENT == 1)
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_MPU     Memory Protection Unit (MPU)
+    \brief      Type definitions for the Memory Protection Unit (MPU)
+  @{
+ */
+
+/** \brief  Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+  __I  uint32_t TYPE;                    /*!< Offset: 0x000 (R/ )  MPU Type Register                              */
+  __IO uint32_t CTRL;                    /*!< Offset: 0x004 (R/W)  MPU Control Register                           */
+  __IO uint32_t RNR;                     /*!< Offset: 0x008 (R/W)  MPU Region RNRber Register                     */
+  __IO uint32_t RBAR;                    /*!< Offset: 0x00C (R/W)  MPU Region Base Address Register               */
+  __IO uint32_t RASR;                    /*!< Offset: 0x010 (R/W)  MPU Region Attribute and Size Register         */
+  __IO uint32_t RBAR_A1;                 /*!< Offset: 0x014 (R/W)  MPU Alias 1 Region Base Address Register       */
+  __IO uint32_t RASR_A1;                 /*!< Offset: 0x018 (R/W)  MPU Alias 1 Region Attribute and Size Register */
+  __IO uint32_t RBAR_A2;                 /*!< Offset: 0x01C (R/W)  MPU Alias 2 Region Base Address Register       */
+  __IO uint32_t RASR_A2;                 /*!< Offset: 0x020 (R/W)  MPU Alias 2 Region Attribute and Size Register */
+  __IO uint32_t RBAR_A3;                 /*!< Offset: 0x024 (R/W)  MPU Alias 3 Region Base Address Register       */
+  __IO uint32_t RASR_A3;                 /*!< Offset: 0x028 (R/W)  MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+/* MPU Type Register */
+#define MPU_TYPE_IREGION_Pos               16                                             /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk               (0xFFUL << MPU_TYPE_IREGION_Pos)               /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos                8                                             /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk               (0xFFUL << MPU_TYPE_DREGION_Pos)               /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos               0                                             /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk              (1UL << MPU_TYPE_SEPARATE_Pos)                 /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register */
+#define MPU_CTRL_PRIVDEFENA_Pos             2                                             /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk            (1UL << MPU_CTRL_PRIVDEFENA_Pos)               /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos               1                                             /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk              (1UL << MPU_CTRL_HFNMIENA_Pos)                 /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos                 0                                             /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk                (1UL << MPU_CTRL_ENABLE_Pos)                   /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register */
+#define MPU_RNR_REGION_Pos                  0                                             /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk                 (0xFFUL << MPU_RNR_REGION_Pos)                 /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register */
+#define MPU_RBAR_ADDR_Pos                   5                                             /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk                  (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos)             /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos                  4                                             /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk                 (1UL << MPU_RBAR_VALID_Pos)                    /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos                 0                                             /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk                (0xFUL << MPU_RBAR_REGION_Pos)                 /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register */
+#define MPU_RASR_ATTRS_Pos                 16                                             /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk                 (0xFFFFUL << MPU_RASR_ATTRS_Pos)               /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos                    28                                             /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk                    (1UL << MPU_RASR_XN_Pos)                       /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos                    24                                             /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk                    (0x7UL << MPU_RASR_AP_Pos)                     /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos                   19                                             /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk                   (0x7UL << MPU_RASR_TEX_Pos)                    /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos                     18                                             /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk                     (1UL << MPU_RASR_S_Pos)                        /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos                     17                                             /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk                     (1UL << MPU_RASR_C_Pos)                        /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos                     16                                             /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk                     (1UL << MPU_RASR_B_Pos)                        /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos                    8                                             /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk                   (0xFFUL << MPU_RASR_SRD_Pos)                   /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos                   1                                             /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk                  (0x1FUL << MPU_RASR_SIZE_Pos)                  /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos                 0                                             /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk                (1UL << MPU_RASR_ENABLE_Pos)                   /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_CoreDebug       Core Debug Registers (CoreDebug)
+    \brief      Type definitions for the Core Debug Registers
+  @{
+ */
+
+/** \brief  Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+  __IO uint32_t DHCSR;                   /*!< Offset: 0x000 (R/W)  Debug Halting Control and Status Register    */
+  __O  uint32_t DCRSR;                   /*!< Offset: 0x004 ( /W)  Debug Core Register Selector Register        */
+  __IO uint32_t DCRDR;                   /*!< Offset: 0x008 (R/W)  Debug Core Register Data Register            */
+  __IO uint32_t DEMCR;                   /*!< Offset: 0x00C (R/W)  Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register */
+#define CoreDebug_DHCSR_DBGKEY_Pos         16                                             /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk         (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos)       /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos     25                                             /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk     (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos)        /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos    24                                             /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk    (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos)       /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos       19                                             /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk       (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos)          /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos        18                                             /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk        (1UL << CoreDebug_DHCSR_S_SLEEP_Pos)           /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos         17                                             /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk         (1UL << CoreDebug_DHCSR_S_HALT_Pos)            /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos       16                                             /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk       (1UL << CoreDebug_DHCSR_S_REGRDY_Pos)          /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos     5                                             /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk    (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos)       /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos      3                                             /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk     (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos)        /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos          2                                             /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk         (1UL << CoreDebug_DHCSR_C_STEP_Pos)            /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos          1                                             /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk         (1UL << CoreDebug_DHCSR_C_HALT_Pos)            /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos       0                                             /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk      (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos)         /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register */
+#define CoreDebug_DCRSR_REGWnR_Pos         16                                             /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk         (1UL << CoreDebug_DCRSR_REGWnR_Pos)            /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos          0                                             /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk         (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos)         /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_TRCENA_Pos         24                                             /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk         (1UL << CoreDebug_DEMCR_TRCENA_Pos)            /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos        19                                             /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk        (1UL << CoreDebug_DEMCR_MON_REQ_Pos)           /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos       18                                             /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk       (1UL << CoreDebug_DEMCR_MON_STEP_Pos)          /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos       17                                             /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk       (1UL << CoreDebug_DEMCR_MON_PEND_Pos)          /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos         16                                             /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk         (1UL << CoreDebug_DEMCR_MON_EN_Pos)            /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos     10                                             /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk     (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos)        /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos       9                                             /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk      (1UL << CoreDebug_DEMCR_VC_INTERR_Pos)         /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos       8                                             /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk      (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos)         /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos      7                                             /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk     (1UL << CoreDebug_DEMCR_VC_STATERR_Pos)        /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos       6                                             /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk      (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos)         /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos      5                                             /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk     (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos)        /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos        4                                             /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk       (1UL << CoreDebug_DEMCR_VC_MMERR_Pos)          /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos    0                                             /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk   (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos)      /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_core_base     Core Definitions
+    \brief      Definitions for base addresses, unions, and structures.
+  @{
+ */
+
+/* Memory mapping of Cortex-M3 Hardware */
+#define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address  */
+#define ITM_BASE            (0xE0000000UL)                            /*!< ITM Base Address                   */
+#define DWT_BASE            (0xE0001000UL)                            /*!< DWT Base Address                   */
+#define TPI_BASE            (0xE0040000UL)                            /*!< TPI Base Address                   */
+#define CoreDebug_BASE      (0xE000EDF0UL)                            /*!< Core Debug Base Address            */
+#define SysTick_BASE        (SCS_BASE +  0x0010UL)                    /*!< SysTick Base Address               */
+#define NVIC_BASE           (SCS_BASE +  0x0100UL)                    /*!< NVIC Base Address                  */
+#define SCB_BASE            (SCS_BASE +  0x0D00UL)                    /*!< System Control Block Base Address  */
+
+#define SCnSCB              ((SCnSCB_Type    *)     SCS_BASE      )   /*!< System control Register not in SCB */
+#define SCB                 ((SCB_Type       *)     SCB_BASE      )   /*!< SCB configuration struct           */
+#define SysTick             ((SysTick_Type   *)     SysTick_BASE  )   /*!< SysTick configuration struct       */
+#define NVIC                ((NVIC_Type      *)     NVIC_BASE     )   /*!< NVIC configuration struct          */
+#define ITM                 ((ITM_Type       *)     ITM_BASE      )   /*!< ITM configuration struct           */
+#define DWT                 ((DWT_Type       *)     DWT_BASE      )   /*!< DWT configuration struct           */
+#define TPI                 ((TPI_Type       *)     TPI_BASE      )   /*!< TPI configuration struct           */
+#define CoreDebug           ((CoreDebug_Type *)     CoreDebug_BASE)   /*!< Core Debug configuration struct    */
+
+#if (__MPU_PRESENT == 1)
+  #define MPU_BASE          (SCS_BASE +  0x0D90UL)                    /*!< Memory Protection Unit             */
+  #define MPU               ((MPU_Type       *)     MPU_BASE      )   /*!< Memory Protection Unit             */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ *                Hardware Abstraction Layer
+  Core Function Interface contains:
+  - Core NVIC Functions
+  - Core SysTick Functions
+  - Core Debug Functions
+  - Core Register Access Functions
+ ******************************************************************************/
+/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ##########################   NVIC functions  #################################### */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+    \brief      Functions that manage interrupts and exceptions via the NVIC.
+    @{
+ */
+
+/** \brief  Set Priority Grouping
+
+  The function sets the priority grouping field using the required unlock sequence.
+  The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+  Only values from 0..7 are used.
+  In case of a conflict between priority grouping and available
+  priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+
+    \param [in]      PriorityGroup  Priority grouping field.
+ */
+__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+  uint32_t reg_value;
+  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07);               /* only values 0..7 are used          */
+
+  reg_value  =  SCB->AIRCR;                                                   /* read old register configuration    */
+  reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk);             /* clear bits to change               */
+  reg_value  =  (reg_value                                 |
+                ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) |
+                (PriorityGroupTmp << 8));                                     /* Insert write key and priorty group */
+  SCB->AIRCR =  reg_value;
+}
+
+
+/** \brief  Get Priority Grouping
+
+  The function reads the priority grouping field from the NVIC Interrupt Controller.
+
+    \return                Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+{
+  return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos);   /* read priority grouping field */
+}
+
+
+/** \brief  Enable External Interrupt
+
+    The function enables a device-specific interrupt in the NVIC interrupt controller.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+  NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
+}
+
+
+/** \brief  Disable External Interrupt
+
+    The function disables a device-specific interrupt in the NVIC interrupt controller.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+  NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */
+}
+
+
+/** \brief  Get Pending Interrupt
+
+    The function reads the pending register in the NVIC and returns the pending bit
+    for the specified interrupt.
+
+    \param [in]      IRQn  Interrupt number.
+
+    \return             0  Interrupt status is not pending.
+    \return             1  Interrupt status is pending.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+  return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */
+}
+
+
+/** \brief  Set Pending Interrupt
+
+    The function sets the pending bit of an external interrupt.
+
+    \param [in]      IRQn  Interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+  NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
+}
+
+
+/** \brief  Clear Pending Interrupt
+
+    The function clears the pending bit of an external interrupt.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+  NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
+}
+
+
+/** \brief  Get Active Interrupt
+
+    The function reads the active register in NVIC and returns the active bit.
+
+    \param [in]      IRQn  Interrupt number.
+
+    \return             0  Interrupt status is not active.
+    \return             1  Interrupt status is active.
+ */
+__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+{
+  return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */
+}
+
+
+/** \brief  Set Interrupt Priority
+
+    The function sets the priority of an interrupt.
+
+    \note The priority cannot be set for every core interrupt.
+
+    \param [in]      IRQn  Interrupt number.
+    \param [in]  priority  Priority to set.
+ */
+__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+  if(IRQn < 0) {
+    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M  System Interrupts */
+  else {
+    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
+}
+
+
+/** \brief  Get Interrupt Priority
+
+    The function reads the priority of an interrupt. The interrupt
+    number can be positive to specify an external (device specific)
+    interrupt, or negative to specify an internal (core) interrupt.
+
+
+    \param [in]   IRQn  Interrupt number.
+    \return             Interrupt Priority. Value is aligned automatically to the implemented
+                        priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+  if(IRQn < 0) {
+    return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS)));  } /* get priority for Cortex-M  system interrupts */
+  else {
+    return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)]           >> (8 - __NVIC_PRIO_BITS)));  } /* get priority for device specific interrupts  */
+}
+
+
+/** \brief  Encode Priority
+
+    The function encodes the priority for an interrupt with the given priority group,
+    preemptive priority value, and subpriority value.
+    In case of a conflict between priority grouping and available
+    priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set.
+
+    \param [in]     PriorityGroup  Used priority group.
+    \param [in]   PreemptPriority  Preemptive priority value (starting from 0).
+    \param [in]       SubPriority  Subpriority value (starting from 0).
+    \return                        Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */
+  uint32_t PreemptPriorityBits;
+  uint32_t SubPriorityBits;
+
+  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+  return (
+           ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
+           ((SubPriority     & ((1 << (SubPriorityBits    )) - 1)))
+         );
+}
+
+
+/** \brief  Decode Priority
+
+    The function decodes an interrupt priority value with a given priority group to
+    preemptive priority value and subpriority value.
+    In case of a conflict between priority grouping and available
+    priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set.
+
+    \param [in]         Priority   Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+    \param [in]     PriorityGroup  Used priority group.
+    \param [out] pPreemptPriority  Preemptive priority value (starting from 0).
+    \param [out]     pSubPriority  Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority)
+{
+  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */
+  uint32_t PreemptPriorityBits;
+  uint32_t SubPriorityBits;
+
+  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+  *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1);
+  *pSubPriority     = (Priority                   ) & ((1 << (SubPriorityBits    )) - 1);
+}
+
+
+/** \brief  System Reset
+
+    The function initiates a system reset request to reset the MCU.
+ */
+__STATIC_INLINE void NVIC_SystemReset(void)
+{
+  __DSB();                                                     /* Ensure all outstanding memory accesses included
+                                                                  buffered write are completed before reset */
+  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
+                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
+  __DSB();                                                     /* Ensure completion of memory access */
+  while(1);                                                    /* wait until reset */
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+
+/* ##################################    SysTick function  ############################################ */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+    \brief      Functions that configure the System.
+  @{
+ */
+
+#if (__Vendor_SysTickConfig == 0)
+
+/** \brief  System Tick Configuration
+
+    The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
+    Counter is in free running mode to generate periodic interrupts.
+
+    \param [in]  ticks  Number of ticks between two interrupts.
+
+    \return          0  Function succeeded.
+    \return          1  Function failed.
+
+    \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
+    function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
+    must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+  if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)  return (1);      /* Reload value impossible */
+
+  SysTick->LOAD  = ticks - 1;                                  /* set reload register */
+  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
+  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
+  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
+                   SysTick_CTRL_TICKINT_Msk   |
+                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
+  return (0);                                                  /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_core_DebugFunctions ITM Functions
+    \brief   Functions that access the ITM debug interface.
+  @{
+ */
+
+extern volatile int32_t ITM_RxBuffer;                    /*!< External variable to receive characters.                         */
+#define                 ITM_RXBUFFER_EMPTY    0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/** \brief  ITM Send Character
+
+    The function transmits a character via the ITM channel 0, and
+    \li Just returns when no debugger is connected that has booked the output.
+    \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+
+    \param [in]     ch  Character to transmit.
+
+    \returns            Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+  if ((ITM->TCR & ITM_TCR_ITMENA_Msk)                  &&      /* ITM enabled */
+      (ITM->TER & (1UL << 0)        )                    )     /* ITM Port #0 enabled */
+  {
+    while (ITM->PORT[0].u32 == 0);
+    ITM->PORT[0].u8 = (uint8_t) ch;
+  }
+  return (ch);
+}
+
+
+/** \brief  ITM Receive Character
+
+    The function inputs a character via the external variable \ref ITM_RxBuffer.
+
+    \return             Received character.
+    \return         -1  No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void) {
+  int32_t ch = -1;                           /* no character available */
+
+  if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) {
+    ch = ITM_RxBuffer;
+    ITM_RxBuffer = ITM_RXBUFFER_EMPTY;       /* ready for next character */
+  }
+
+  return (ch);
+}
+
+
+/** \brief  ITM Check Character
+
+    The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+
+    \return          0  No character available.
+    \return          1  Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void) {
+
+  if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) {
+    return (0);                                 /* no character available */
+  } else {
+    return (1);                                 /*    character available */
+  }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+#endif /* __CORE_CM3_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
+
+#ifdef __cplusplus
+}
+#endif

+ 637 - 0
CMSIS/core_cmFunc.h

@@ -0,0 +1,637 @@
+/**************************************************************************//**
+ * @file     core_cmFunc.h
+ * @brief    CMSIS Cortex-M Core Function Access Header File
+ * @version  V3.30
+ * @date     17. February 2014
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2014 ARM LIMITED
+
+   All rights reserved.
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   - Neither the name of ARM nor the names of its contributors may be used
+     to endorse or promote products derived from this software without
+     specific prior written permission.
+   *
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+   ---------------------------------------------------------------------------*/
+
+
+#ifndef __CORE_CMFUNC_H
+#define __CORE_CMFUNC_H
+
+
+/* ###########################  Core Function Access  ########################### */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+  @{
+ */
+
+#if   defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+
+#if (__ARMCC_VERSION < 400677)
+  #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
+#endif
+
+/* intrinsic void __enable_irq();     */
+/* intrinsic void __disable_irq();    */
+
+/** \brief  Get Control Register
+
+    This function returns the content of the Control Register.
+
+    \return               Control Register value
+ */
+__STATIC_INLINE uint32_t __get_CONTROL(void)
+{
+  register uint32_t __regControl         __ASM("control");
+  return(__regControl);
+}
+
+
+/** \brief  Set Control Register
+
+    This function writes the given value to the Control Register.
+
+    \param [in]    control  Control Register value to set
+ */
+__STATIC_INLINE void __set_CONTROL(uint32_t control)
+{
+  register uint32_t __regControl         __ASM("control");
+  __regControl = control;
+}
+
+
+/** \brief  Get IPSR Register
+
+    This function returns the content of the IPSR Register.
+
+    \return               IPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_IPSR(void)
+{
+  register uint32_t __regIPSR          __ASM("ipsr");
+  return(__regIPSR);
+}
+
+
+/** \brief  Get APSR Register
+
+    This function returns the content of the APSR Register.
+
+    \return               APSR Register value
+ */
+__STATIC_INLINE uint32_t __get_APSR(void)
+{
+  register uint32_t __regAPSR          __ASM("apsr");
+  return(__regAPSR);
+}
+
+
+/** \brief  Get xPSR Register
+
+    This function returns the content of the xPSR Register.
+
+    \return               xPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_xPSR(void)
+{
+  register uint32_t __regXPSR          __ASM("xpsr");
+  return(__regXPSR);
+}
+
+
+/** \brief  Get Process Stack Pointer
+
+    This function returns the current value of the Process Stack Pointer (PSP).
+
+    \return               PSP Register value
+ */
+__STATIC_INLINE uint32_t __get_PSP(void)
+{
+  register uint32_t __regProcessStackPointer  __ASM("psp");
+  return(__regProcessStackPointer);
+}
+
+
+/** \brief  Set Process Stack Pointer
+
+    This function assigns the given value to the Process Stack Pointer (PSP).
+
+    \param [in]    topOfProcStack  Process Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+{
+  register uint32_t __regProcessStackPointer  __ASM("psp");
+  __regProcessStackPointer = topOfProcStack;
+}
+
+
+/** \brief  Get Main Stack Pointer
+
+    This function returns the current value of the Main Stack Pointer (MSP).
+
+    \return               MSP Register value
+ */
+__STATIC_INLINE uint32_t __get_MSP(void)
+{
+  register uint32_t __regMainStackPointer     __ASM("msp");
+  return(__regMainStackPointer);
+}
+
+
+/** \brief  Set Main Stack Pointer
+
+    This function assigns the given value to the Main Stack Pointer (MSP).
+
+    \param [in]    topOfMainStack  Main Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+{
+  register uint32_t __regMainStackPointer     __ASM("msp");
+  __regMainStackPointer = topOfMainStack;
+}
+
+
+/** \brief  Get Priority Mask
+
+    This function returns the current state of the priority mask bit from the Priority Mask Register.
+
+    \return               Priority Mask value
+ */
+__STATIC_INLINE uint32_t __get_PRIMASK(void)
+{
+  register uint32_t __regPriMask         __ASM("primask");
+  return(__regPriMask);
+}
+
+
+/** \brief  Set Priority Mask
+
+    This function assigns the given value to the Priority Mask Register.
+
+    \param [in]    priMask  Priority Mask
+ */
+__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+{
+  register uint32_t __regPriMask         __ASM("primask");
+  __regPriMask = (priMask);
+}
+
+
+#if       (__CORTEX_M >= 0x03)
+
+/** \brief  Enable FIQ
+
+    This function enables FIQ interrupts by clearing the F-bit in the CPSR.
+    Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq                __enable_fiq
+
+
+/** \brief  Disable FIQ
+
+    This function disables FIQ interrupts by setting the F-bit in the CPSR.
+    Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq               __disable_fiq
+
+
+/** \brief  Get Base Priority
+
+    This function returns the current value of the Base Priority register.
+
+    \return               Base Priority register value
+ */
+__STATIC_INLINE uint32_t  __get_BASEPRI(void)
+{
+  register uint32_t __regBasePri         __ASM("basepri");
+  return(__regBasePri);
+}
+
+
+/** \brief  Set Base Priority
+
+    This function assigns the given value to the Base Priority register.
+
+    \param [in]    basePri  Base Priority value to set
+ */
+__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
+{
+  register uint32_t __regBasePri         __ASM("basepri");
+  __regBasePri = (basePri & 0xff);
+}
+
+
+/** \brief  Get Fault Mask
+
+    This function returns the current value of the Fault Mask register.
+
+    \return               Fault Mask register value
+ */
+__STATIC_INLINE uint32_t __get_FAULTMASK(void)
+{
+  register uint32_t __regFaultMask       __ASM("faultmask");
+  return(__regFaultMask);
+}
+
+
+/** \brief  Set Fault Mask
+
+    This function assigns the given value to the Fault Mask register.
+
+    \param [in]    faultMask  Fault Mask value to set
+ */
+__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+  register uint32_t __regFaultMask       __ASM("faultmask");
+  __regFaultMask = (faultMask & (uint32_t)1);
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#if       (__CORTEX_M == 0x04)
+
+/** \brief  Get FPSCR
+
+    This function returns the current value of the Floating Point Status/Control register.
+
+    \return               Floating Point Status/Control register value
+ */
+__STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+  register uint32_t __regfpscr         __ASM("fpscr");
+  return(__regfpscr);
+#else
+   return(0);
+#endif
+}
+
+
+/** \brief  Set FPSCR
+
+    This function assigns the given value to the Floating Point Status/Control register.
+
+    \param [in]    fpscr  Floating Point Status/Control value to set
+ */
+__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+  register uint32_t __regfpscr         __ASM("fpscr");
+  __regfpscr = (fpscr);
+#endif
+}
+
+#endif /* (__CORTEX_M == 0x04) */
+
+
+#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+/** \brief  Enable IRQ Interrupts
+
+  This function enables IRQ interrupts by clearing the I-bit in the CPSR.
+  Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
+{
+  __ASM volatile ("cpsie i" : : : "memory");
+}
+
+
+/** \brief  Disable IRQ Interrupts
+
+  This function disables IRQ interrupts by setting the I-bit in the CPSR.
+  Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
+{
+  __ASM volatile ("cpsid i" : : : "memory");
+}
+
+
+/** \brief  Get Control Register
+
+    This function returns the content of the Control Register.
+
+    \return               Control Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, control" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Control Register
+
+    This function writes the given value to the Control Register.
+
+    \param [in]    control  Control Register value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
+{
+  __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+/** \brief  Get IPSR Register
+
+    This function returns the content of the IPSR Register.
+
+    \return               IPSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Get APSR Register
+
+    This function returns the content of the APSR Register.
+
+    \return               APSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Get xPSR Register
+
+    This function returns the content of the xPSR Register.
+
+    \return               xPSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Get Process Stack Pointer
+
+    This function returns the current value of the Process Stack Pointer (PSP).
+
+    \return               PSP Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
+{
+  register uint32_t result;
+
+  __ASM volatile ("MRS %0, psp\n"  : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Process Stack Pointer
+
+    This function assigns the given value to the Process Stack Pointer (PSP).
+
+    \param [in]    topOfProcStack  Process Stack Pointer value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+{
+  __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
+}
+
+
+/** \brief  Get Main Stack Pointer
+
+    This function returns the current value of the Main Stack Pointer (MSP).
+
+    \return               MSP Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
+{
+  register uint32_t result;
+
+  __ASM volatile ("MRS %0, msp\n" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Main Stack Pointer
+
+    This function assigns the given value to the Main Stack Pointer (MSP).
+
+    \param [in]    topOfMainStack  Main Stack Pointer value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+{
+  __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
+}
+
+
+/** \brief  Get Priority Mask
+
+    This function returns the current state of the priority mask bit from the Priority Mask Register.
+
+    \return               Priority Mask value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, primask" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Priority Mask
+
+    This function assigns the given value to the Priority Mask Register.
+
+    \param [in]    priMask  Priority Mask
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+{
+  __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if       (__CORTEX_M >= 0x03)
+
+/** \brief  Enable FIQ
+
+    This function enables FIQ interrupts by clearing the F-bit in the CPSR.
+    Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
+{
+  __ASM volatile ("cpsie f" : : : "memory");
+}
+
+
+/** \brief  Disable FIQ
+
+    This function disables FIQ interrupts by setting the F-bit in the CPSR.
+    Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
+{
+  __ASM volatile ("cpsid f" : : : "memory");
+}
+
+
+/** \brief  Get Base Priority
+
+    This function returns the current value of the Base Priority register.
+
+    \return               Base Priority register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Base Priority
+
+    This function assigns the given value to the Base Priority register.
+
+    \param [in]    basePri  Base Priority value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
+{
+  __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
+}
+
+
+/** \brief  Get Fault Mask
+
+    This function returns the current value of the Fault Mask register.
+
+    \return               Fault Mask register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
+{
+  uint32_t result;
+
+  __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+  return(result);
+}
+
+
+/** \brief  Set Fault Mask
+
+    This function assigns the given value to the Fault Mask register.
+
+    \param [in]    faultMask  Fault Mask value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+  __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#if       (__CORTEX_M == 0x04)
+
+/** \brief  Get FPSCR
+
+    This function returns the current value of the Floating Point Status/Control register.
+
+    \return               Floating Point Status/Control register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+  uint32_t result;
+
+  /* Empty asm statement works as a scheduling barrier */
+  __ASM volatile ("");
+  __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
+  __ASM volatile ("");
+  return(result);
+#else
+   return(0);
+#endif
+}
+
+
+/** \brief  Set FPSCR
+
+    This function assigns the given value to the Floating Point Status/Control register.
+
+    \param [in]    fpscr  Floating Point Status/Control value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+  /* Empty asm statement works as a scheduling barrier */
+  __ASM volatile ("");
+  __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
+  __ASM volatile ("");
+#endif
+}
+
+#endif /* (__CORTEX_M == 0x04) */
+
+
+#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
+/* IAR iccarm specific functions */
+#include <cmsis_iar.h>
+
+
+#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
+/* TI CCS specific functions */
+#include <cmsis_ccs.h>
+
+
+#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
+/* TASKING carm specific functions */
+/*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+
+#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
+/* Cosmic specific functions */
+#include <cmsis_csm.h>
+
+#endif
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+#endif /* __CORE_CMFUNC_H */

+ 687 - 0
CMSIS/core_cmInstr.h

@@ -0,0 +1,687 @@
+/**************************************************************************//**
+ * @file     core_cmInstr.h
+ * @brief    CMSIS Cortex-M Core Instruction Access Header File
+ * @version  V3.30
+ * @date     17. February 2014
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2014 ARM LIMITED
+
+   All rights reserved.
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   - Neither the name of ARM nor the names of its contributors may be used
+     to endorse or promote products derived from this software without
+     specific prior written permission.
+   *
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+   ---------------------------------------------------------------------------*/
+
+
+#ifndef __CORE_CMINSTR_H
+#define __CORE_CMINSTR_H
+
+
+/* ##########################  Core Instruction Access  ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+  Access to dedicated instructions
+  @{
+*/
+
+#if   defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+
+#if (__ARMCC_VERSION < 400677)
+  #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
+#endif
+
+
+/** \brief  No Operation
+
+    No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP                             __nop
+
+
+/** \brief  Wait For Interrupt
+
+    Wait For Interrupt is a hint instruction that suspends execution
+    until one of a number of events occurs.
+ */
+#define __WFI                             __wfi
+
+
+/** \brief  Wait For Event
+
+    Wait For Event is a hint instruction that permits the processor to enter
+    a low-power state until one of a number of events occurs.
+ */
+#define __WFE                             __wfe
+
+
+/** \brief  Send Event
+
+    Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV                             __sev
+
+
+/** \brief  Instruction Synchronization Barrier
+
+    Instruction Synchronization Barrier flushes the pipeline in the processor,
+    so that all instructions following the ISB are fetched from cache or
+    memory, after the instruction has been completed.
+ */
+#define __ISB()                           __isb(0xF)
+
+
+/** \brief  Data Synchronization Barrier
+
+    This function acts as a special kind of Data Memory Barrier.
+    It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB()                           __dsb(0xF)
+
+
+/** \brief  Data Memory Barrier
+
+    This function ensures the apparent order of the explicit memory operations before
+    and after the instruction, without ensuring their completion.
+ */
+#define __DMB()                           __dmb(0xF)
+
+
+/** \brief  Reverse byte order (32 bit)
+
+    This function reverses the byte order in integer value.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+#define __REV                             __rev
+
+
+/** \brief  Reverse byte order (16 bit)
+
+    This function reverses the byte order in two unsigned short values.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
+{
+  rev16 r0, r0
+  bx lr
+}
+#endif
+
+/** \brief  Reverse byte order in signed short value
+
+    This function reverses the byte order in a signed short value with sign extension to integer.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
+{
+  revsh r0, r0
+  bx lr
+}
+#endif
+
+
+/** \brief  Rotate Right in unsigned value (32 bit)
+
+    This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+
+    \param [in]    value  Value to rotate
+    \param [in]    value  Number of Bits to rotate
+    \return               Rotated value
+ */
+#define __ROR                             __ror
+
+
+/** \brief  Breakpoint
+
+    This function causes the processor to enter Debug state.
+    Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+
+    \param [in]    value  is ignored by the processor.
+                   If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value)                       __breakpoint(value)
+
+
+#if       (__CORTEX_M >= 0x03)
+
+/** \brief  Reverse bit order of value
+
+    This function reverses the bit order of the given value.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+#define __RBIT                            __rbit
+
+
+/** \brief  LDR Exclusive (8 bit)
+
+    This function performs a exclusive LDR command for 8 bit value.
+
+    \param [in]    ptr  Pointer to data
+    \return             value of type uint8_t at (*ptr)
+ */
+#define __LDREXB(ptr)                     ((uint8_t ) __ldrex(ptr))
+
+
+/** \brief  LDR Exclusive (16 bit)
+
+    This function performs a exclusive LDR command for 16 bit values.
+
+    \param [in]    ptr  Pointer to data
+    \return        value of type uint16_t at (*ptr)
+ */
+#define __LDREXH(ptr)                     ((uint16_t) __ldrex(ptr))
+
+
+/** \brief  LDR Exclusive (32 bit)
+
+    This function performs a exclusive LDR command for 32 bit values.
+
+    \param [in]    ptr  Pointer to data
+    \return        value of type uint32_t at (*ptr)
+ */
+#define __LDREXW(ptr)                     ((uint32_t ) __ldrex(ptr))
+
+
+/** \brief  STR Exclusive (8 bit)
+
+    This function performs a exclusive STR command for 8 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+#define __STREXB(value, ptr)              __strex(value, ptr)
+
+
+/** \brief  STR Exclusive (16 bit)
+
+    This function performs a exclusive STR command for 16 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+#define __STREXH(value, ptr)              __strex(value, ptr)
+
+
+/** \brief  STR Exclusive (32 bit)
+
+    This function performs a exclusive STR command for 32 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+#define __STREXW(value, ptr)              __strex(value, ptr)
+
+
+/** \brief  Remove the exclusive lock
+
+    This function removes the exclusive lock which is created by LDREX.
+
+ */
+#define __CLREX                           __clrex
+
+
+/** \brief  Signed Saturate
+
+    This function saturates a signed value.
+
+    \param [in]  value  Value to be saturated
+    \param [in]    sat  Bit position to saturate to (1..32)
+    \return             Saturated value
+ */
+#define __SSAT                            __ssat
+
+
+/** \brief  Unsigned Saturate
+
+    This function saturates an unsigned value.
+
+    \param [in]  value  Value to be saturated
+    \param [in]    sat  Bit position to saturate to (0..31)
+    \return             Saturated value
+ */
+#define __USAT                            __usat
+
+
+/** \brief  Count leading zeros
+
+    This function counts the number of leading zeros of a data value.
+
+    \param [in]  value  Value to count the leading zeros
+    \return             number of leading zeros in value
+ */
+#define __CLZ                             __clz
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constrant "l"
+ * Otherwise, use general registers, specified by constrant "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/** \brief  No Operation
+
+    No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
+{
+  __ASM volatile ("nop");
+}
+
+
+/** \brief  Wait For Interrupt
+
+    Wait For Interrupt is a hint instruction that suspends execution
+    until one of a number of events occurs.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
+{
+  __ASM volatile ("wfi");
+}
+
+
+/** \brief  Wait For Event
+
+    Wait For Event is a hint instruction that permits the processor to enter
+    a low-power state until one of a number of events occurs.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
+{
+  __ASM volatile ("wfe");
+}
+
+
+/** \brief  Send Event
+
+    Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
+{
+  __ASM volatile ("sev");
+}
+
+
+/** \brief  Instruction Synchronization Barrier
+
+    Instruction Synchronization Barrier flushes the pipeline in the processor,
+    so that all instructions following the ISB are fetched from cache or
+    memory, after the instruction has been completed.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
+{
+  __ASM volatile ("isb");
+}
+
+
+/** \brief  Data Synchronization Barrier
+
+    This function acts as a special kind of Data Memory Barrier.
+    It completes when all explicit memory accesses before this instruction complete.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
+{
+  __ASM volatile ("dsb");
+}
+
+
+/** \brief  Data Memory Barrier
+
+    This function ensures the apparent order of the explicit memory operations before
+    and after the instruction, without ensuring their completion.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
+{
+  __ASM volatile ("dmb");
+}
+
+
+/** \brief  Reverse byte order (32 bit)
+
+    This function reverses the byte order in integer value.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+  return __builtin_bswap32(value);
+#else
+  uint32_t result;
+
+  __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+  return(result);
+#endif
+}
+
+
+/** \brief  Reverse byte order (16 bit)
+
+    This function reverses the byte order in two unsigned short values.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
+{
+  uint32_t result;
+
+  __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+  return(result);
+}
+
+
+/** \brief  Reverse byte order in signed short value
+
+    This function reverses the byte order in a signed short value with sign extension to integer.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+  return (short)__builtin_bswap16(value);
+#else
+  uint32_t result;
+
+  __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+  return(result);
+#endif
+}
+
+
+/** \brief  Rotate Right in unsigned value (32 bit)
+
+    This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+
+    \param [in]    value  Value to rotate
+    \param [in]    value  Number of Bits to rotate
+    \return               Rotated value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+  return (op1 >> op2) | (op1 << (32 - op2)); 
+}
+
+
+/** \brief  Breakpoint
+
+    This function causes the processor to enter Debug state.
+    Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+
+    \param [in]    value  is ignored by the processor.
+                   If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value)                       __ASM volatile ("bkpt "#value)
+
+
+#if       (__CORTEX_M >= 0x03)
+
+/** \brief  Reverse bit order of value
+
+    This function reverses the bit order of the given value.
+
+    \param [in]    value  Value to reverse
+    \return               Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
+{
+  uint32_t result;
+
+   __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
+   return(result);
+}
+
+
+/** \brief  LDR Exclusive (8 bit)
+
+    This function performs a exclusive LDR command for 8 bit value.
+
+    \param [in]    ptr  Pointer to data
+    \return             value of type uint8_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
+{
+    uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+   __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+    /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+       accepted by assembler. So has to use following less efficient pattern.
+    */
+   __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+   return ((uint8_t) result);    /* Add explicit type cast here */
+}
+
+
+/** \brief  LDR Exclusive (16 bit)
+
+    This function performs a exclusive LDR command for 16 bit values.
+
+    \param [in]    ptr  Pointer to data
+    \return        value of type uint16_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
+{
+    uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+   __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+    /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+       accepted by assembler. So has to use following less efficient pattern.
+    */
+   __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+   return ((uint16_t) result);    /* Add explicit type cast here */
+}
+
+
+/** \brief  LDR Exclusive (32 bit)
+
+    This function performs a exclusive LDR command for 32 bit values.
+
+    \param [in]    ptr  Pointer to data
+    \return        value of type uint32_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
+{
+    uint32_t result;
+
+   __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
+   return(result);
+}
+
+
+/** \brief  STR Exclusive (8 bit)
+
+    This function performs a exclusive STR command for 8 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
+{
+   uint32_t result;
+
+   __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+   return(result);
+}
+
+
+/** \brief  STR Exclusive (16 bit)
+
+    This function performs a exclusive STR command for 16 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
+{
+   uint32_t result;
+
+   __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+   return(result);
+}
+
+
+/** \brief  STR Exclusive (32 bit)
+
+    This function performs a exclusive STR command for 32 bit values.
+
+    \param [in]  value  Value to store
+    \param [in]    ptr  Pointer to location
+    \return          0  Function succeeded
+    \return          1  Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
+{
+   uint32_t result;
+
+   __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+   return(result);
+}
+
+
+/** \brief  Remove the exclusive lock
+
+    This function removes the exclusive lock which is created by LDREX.
+
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
+{
+  __ASM volatile ("clrex" ::: "memory");
+}
+
+
+/** \brief  Signed Saturate
+
+    This function saturates a signed value.
+
+    \param [in]  value  Value to be saturated
+    \param [in]    sat  Bit position to saturate to (1..32)
+    \return             Saturated value
+ */
+#define __SSAT(ARG1,ARG2) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1); \
+  __ASM ("ssat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
+  __RES; \
+ })
+
+
+/** \brief  Unsigned Saturate
+
+    This function saturates an unsigned value.
+
+    \param [in]  value  Value to be saturated
+    \param [in]    sat  Bit position to saturate to (0..31)
+    \return             Saturated value
+ */
+#define __USAT(ARG1,ARG2) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1); \
+  __ASM ("usat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
+  __RES; \
+ })
+
+
+/** \brief  Count leading zeros
+
+    This function counts the number of leading zeros of a data value.
+
+    \param [in]  value  Value to count the leading zeros
+    \return             number of leading zeros in value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
+{
+  uint32_t result;
+
+  __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
+   return ((uint8_t) result);    /* Add explicit type cast here */
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
+/* IAR iccarm specific functions */
+#include <cmsis_iar.h>
+
+
+#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
+/* TI CCS specific functions */
+#include <cmsis_ccs.h>
+
+
+#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
+/* TASKING carm specific functions */
+/*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+
+#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
+/* Cosmic specific functions */
+#include <cmsis_csm.h>
+
+#endif
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+#endif /* __CORE_CMINSTR_H */

+ 380 - 0
CMSIS/gd32f10x.h

@@ -0,0 +1,380 @@
+/*!
+    \file    gd32f10x.h
+    \brief   general definitions for GD32F10x
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_H
+#define GD32F10X_H
+
+#ifdef cplusplus
+ extern "C" {
+#endif 
+
+/* define GD32F10x */
+#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL)
+  /* #define GD32F10X_MD */     /*!< GD32F10X_MD: GD32 Medium density devices */
+  /* #define GD32F10X_HD */     /*!< GD32F10X_HD: GD32 High density Value Line devices */  
+  /* #define GD32F10X_XD */     /*!< GD32F10X_XD: GD32 Extra density devices */
+  /* #define GD32F10X_CL */     /*!< GD32F10X_CL: GD32 Connectivity line devices */  
+#endif /* define GD32F10x */
+   
+#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL)
+ #error "Please select the target GD32F10x device in gd32f10x.h file"
+#endif /* undefine GD32F10x tip */
+
+/* define value of high speed crystal oscillator (HXTAL) in Hz */
+#if !defined  HXTAL_VALUE    
+#ifdef GD32F10X_CL   
+#define HXTAL_VALUE    ((uint32_t)25000000) /*!< value of the external oscillator in Hz */
+#else 
+#define HXTAL_VALUE    ((uint32_t)8000000) /* !< from 4M to 16M *!< value of the external oscillator in Hz*/
+#endif /* HXTAL_VALUE */
+#endif /* high speed crystal oscillator value */
+
+/* define startup timeout value of high speed crystal oscillator (HXTAL) */
+#if !defined  (HXTAL_STARTUP_TIMEOUT)
+#define HXTAL_STARTUP_TIMEOUT   ((uint16_t)0xFFFF)
+#endif /* high speed crystal oscillator startup timeout */
+
+/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */
+#if !defined  (IRC8M_VALUE) 
+#define IRC8M_VALUE  ((uint32_t)8000000)
+#endif /* internal 8MHz RC oscillator value */
+
+/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */
+#if !defined  (IRC8M_STARTUP_TIMEOUT)
+#define IRC8M_STARTUP_TIMEOUT   ((uint16_t)0x0500)
+#endif /* internal 8MHz RC oscillator startup timeout */
+
+/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */
+#if !defined  (IRC40K_VALUE) 
+#define IRC40K_VALUE  ((uint32_t)40000)
+#endif /* internal 40KHz RC oscillator value */
+
+/* define value of low speed crystal oscillator (LXTAL)in Hz */
+#if !defined  (LXTAL_VALUE) 
+#define LXTAL_VALUE  ((uint32_t)32768)
+#endif /* low speed crystal oscillator value */
+
+/* GD32F10x firmware library version number V2.0 */
+#define __GD32F10x_STDPERIPH_VERSION_MAIN   (0x01) /*!< [31:24] main version     */
+#define __GD32F10x_STDPERIPH_VERSION_SUB1   (0x00) /*!< [23:16] sub1 version     */
+#define __GD32F10x_STDPERIPH_VERSION_SUB2   (0x00) /*!< [15:8]  sub2 version     */
+#define __GD32F10x_STDPERIPH_VERSION_RC     (0x00) /*!< [7:0]  release candidate */ 
+#define __GD32F10x_STDPERIPH_VERSION        ((__GD32F10x_STDPERIPH_VERSION_MAIN << 24)\
+                                            |(__GD32F10x_STDPERIPH_VERSION_SUB1 << 16)\
+                                            |(__GD32F10x_STDPERIPH_VERSION_SUB2 << 8)\
+                                            |(__GD32F10x_STDPERIPH_VERSION_RC))
+
+/* configuration of the Cortex-M3 processor and core peripherals */
+#define __MPU_PRESENT             0        /*!< GD32F10x do not provide MPU                              */
+#define __NVIC_PRIO_BITS          4        /*!< GD32F10x uses 4 bits for the priority levels             */
+#define __Vendor_SysTickConfig    0        /*!< set to 1 if different sysTick config is used             */
+/* define interrupt number */
+typedef enum IRQn
+{
+    /* Cortex-M3 processor exceptions numbers */
+    NonMaskableInt_IRQn          = -14,    /*!< 2 non maskable interrupt                                 */
+    MemoryManagement_IRQn        = -12,    /*!< 4 Cortex-M3 memory management interrupt                  */
+    BusFault_IRQn                = -11,    /*!< 5 Cortex-M3 bus fault interrupt                          */
+    UsageFault_IRQn              = -10,    /*!< 6 Cortex-M3 usage fault interrupt                        */
+    SVCall_IRQn                  = -5,     /*!< 11 Cortex-M3 SV call interrupt                           */
+    DebugMonitor_IRQn            = -4,     /*!< 12 Cortex-M3 debug monitor interrupt                     */
+    PendSV_IRQn                  = -2,     /*!< 14 Cortex-M3 pend SV interrupt                           */
+    SysTick_IRQn                 = -1,     /*!< 15 Cortex-M3 system tick interrupt                       */
+
+    /* interruput numbers */
+    WWDGT_IRQn                   = 0,      /*!< window watchDog timer interrupt                          */
+    LVD_IRQn                     = 1,      /*!< LVD through EXTI line detect interrupt                   */
+    TAMPER_IRQn                  = 2,      /*!< tamper through EXTI line detect                          */
+    RTC_IRQn                     = 3,      /*!< RTC through EXTI line interrupt                          */
+    FMC_IRQn                     = 4,      /*!< FMC interrupt                                            */
+    RCU_CTC_IRQn                 = 5,      /*!< RCU and CTC interrupt                                    */
+    EXTI0_IRQn                   = 6,      /*!< EXTI line 0 interrupts                                   */
+    EXTI1_IRQn                   = 7,      /*!< EXTI line 1 interrupts                                   */
+    EXTI2_IRQn                   = 8,      /*!< EXTI line 2 interrupts                                   */
+    EXTI3_IRQn                   = 9,      /*!< EXTI line 3 interrupts                                   */
+    EXTI4_IRQn                   = 10,     /*!< EXTI line 4 interrupts                                   */
+    DMA0_Channel0_IRQn           = 11,     /*!< DMA0 channel0 interrupt                                  */
+    DMA0_Channel1_IRQn           = 12,     /*!< DMA0 channel1 interrupt                                  */
+    DMA0_Channel2_IRQn           = 13,     /*!< DMA0 channel2 interrupt                                  */
+    DMA0_Channel3_IRQn           = 14,     /*!< DMA0 channel3 interrupt                                  */
+    DMA0_Channel4_IRQn           = 15,     /*!< DMA0 channel4 interrupt                                  */
+    DMA0_Channel5_IRQn           = 16,     /*!< DMA0 channel5 interrupt                                  */
+    DMA0_Channel6_IRQn           = 17,     /*!< DMA0 channel6 interrupt                                  */
+    ADC0_1_IRQn                  = 18,     /*!< ADC0 and ADC1 interrupt                                  */
+
+#ifdef GD32F10X_MD
+    USBD_HP_CAN0_TX_IRQn         = 19,     /*!< CAN0 TX interrupts                                       */
+    USBD_LP_CAN0_RX0_IRQn        = 20,     /*!< CAN0 RX0 interrupts                                      */
+    CAN0_RX1_IRQn                = 21,     /*!< CAN0 RX1 interrupts                                      */
+    CAN0_EWMC_IRQn               = 22,     /*!< CAN0 EWMC interrupts                                     */
+    EXTI5_9_IRQn                 = 23,     /*!< EXTI[9:5] interrupts                                     */
+    TIMER0_BRK_IRQn              = 24,     /*!< TIMER0 break interrupts                                  */
+    TIMER0_UP_IRQn               = 25,     /*!< TIMER0 update interrupts                                 */
+    TIMER0_TRG_CMT_IRQn          = 26,     /*!< TIMER0 trigger and commutation interrupts                */
+    TIMER0_Channel_IRQn          = 27,     /*!< TIMER0 channel capture compare interrupts                */
+    TIMER1_IRQn                  = 28,     /*!< TIMER1 interrupt                                         */
+    TIMER2_IRQn                  = 29,     /*!< TIMER2 interrupt                                         */
+    TIMER3_IRQn                  = 30,     /*!< TIMER3 interrupts                                        */
+    I2C0_EV_IRQn                 = 31,     /*!< I2C0 event interrupt                                     */
+    I2C0_ER_IRQn                 = 32,     /*!< I2C0 error interrupt                                     */
+    I2C1_EV_IRQn                 = 33,     /*!< I2C1 event interrupt                                     */
+    I2C1_ER_IRQn                 = 34,     /*!< I2C1 error interrupt                                     */
+    SPI0_IRQn                    = 35,     /*!< SPI0 interrupt                                           */
+    SPI1_IRQn                    = 36,     /*!< SPI1 interrupt                                           */
+    USART0_IRQn                  = 37,     /*!< USART0 interrupt                                         */
+    USART1_IRQn                  = 38,     /*!< USART1 interrupt                                         */
+    USART2_IRQn                  = 39,     /*!< USART2 interrupt                                         */
+    EXTI10_15_IRQn               = 40,     /*!< EXTI[15:10] interrupts                                   */
+    RTC_Alarm_IRQn               = 41,     /*!< RTC alarm interrupt                                      */
+    USBD_WKUP_IRQn               = 42,     /*!< USBD Wakeup interrupt                                    */
+    EXMC_IRQn                    = 48,     /*!< EXMC global interrupt                                    */
+#endif /* GD32F10X_MD */
+
+#ifdef GD32F10X_HD
+    USBD_HP_CAN0_TX_IRQn         = 19,     /*!< CAN0 TX interrupts                                       */
+    USBD_LP_CAN0_RX0_IRQn        = 20,     /*!< CAN0 RX0 interrupts                                      */
+    CAN0_RX1_IRQn                = 21,     /*!< CAN0 RX1 interrupts                                      */
+    CAN0_EWMC_IRQn               = 22,     /*!< CAN0 EWMC interrupts                                     */
+    EXTI5_9_IRQn                 = 23,     /*!< EXTI[9:5] interrupts                                     */
+    TIMER0_BRK_IRQn              = 24,     /*!< TIMER0 break interrupts                                  */
+    TIMER0_UP_IRQn               = 25,     /*!< TIMER0 update interrupts                                 */
+    TIMER0_TRG_CMT_IRQn          = 26,     /*!< TIMER0 trigger and commutation interrupts                */
+    TIMER0_Channel_IRQn          = 27,     /*!< TIMER0 channel capture compare interrupts                */
+    TIMER1_IRQn                  = 28,     /*!< TIMER1 interrupt                                         */
+    TIMER2_IRQn                  = 29,     /*!< TIMER2 interrupt                                         */
+    TIMER3_IRQn                  = 30,     /*!< TIMER3 interrupts                                        */
+    I2C0_EV_IRQn                 = 31,     /*!< I2C0 event interrupt                                     */
+    I2C0_ER_IRQn                 = 32,     /*!< I2C0 error interrupt                                     */
+    I2C1_EV_IRQn                 = 33,     /*!< I2C1 event interrupt                                     */
+    I2C1_ER_IRQn                 = 34,     /*!< I2C1 error interrupt                                     */
+    SPI0_IRQn                    = 35,     /*!< SPI0 interrupt                                           */
+    SPI1_IRQn                    = 36,     /*!< SPI1 interrupt                                           */
+    USART0_IRQn                  = 37,     /*!< USART0 interrupt                                         */
+    USART1_IRQn                  = 38,     /*!< USART1 interrupt                                         */
+    USART2_IRQn                  = 39,     /*!< USART2 interrupt                                         */
+    EXTI10_15_IRQn               = 40,     /*!< EXTI[15:10] interrupts                                   */
+    RTC_Alarm_IRQn               = 41,     /*!< RTC alarm interrupt                                      */
+    USBD_WKUP_IRQn               = 42,     /*!< USBD Wakeup interrupt                                    */
+    TIMER7_BRK_IRQn              = 43,     /*!< TIMER7 break interrupts                                  */
+    TIMER7_UP_IRQn               = 44,     /*!< TIMER7 update interrupts                                 */
+    TIMER7_TRG_CMT_IRQn          = 45,     /*!< TIMER7 trigger and commutation interrupts                */
+    TIMER7_Channel_IRQn          = 46,     /*!< TIMER7 channel capture compare interrupts                */
+    ADC2_IRQn                    = 47,     /*!< ADC2 global interrupt                                    */
+    EXMC_IRQn                    = 48,     /*!< EXMC global interrupt                                    */
+    SDIO_IRQn                    = 49,     /*!< SDIO global interrupt                                    */
+    TIMER4_IRQn                  = 50,     /*!< TIMER4 global interrupt                                  */
+    SPI2_IRQn                    = 51,     /*!< SPI2 global interrupt                                    */
+    UART3_IRQn                   = 52,     /*!< UART3 global interrupt                                   */
+    UART4_IRQn                   = 53,     /*!< UART4 global interrupt                                   */
+    TIMER5_IRQn                  = 54,     /*!< TIMER5 global interrupt                                  */
+    TIMER6_IRQn                  = 55,     /*!< TIMER6 global interrupt                                  */
+    DMA1_Channel0_IRQn           = 56,     /*!< DMA1 channel0 global interrupt                           */
+    DMA1_Channel1_IRQn           = 57,     /*!< DMA1 channel1 global interrupt                           */
+    DMA1_Channel2_IRQn           = 58,     /*!< DMA1 channel2 global interrupt                           */
+    DMA1_Channel3_Channel4_IRQn  = 59,     /*!< DMA1 channel3 and channel4 global Interrupt              */
+#endif /* GD32F10X_HD */
+
+#ifdef GD32F10X_XD
+    USBD_HP_CAN0_TX_IRQn         = 19,     /*!< CAN0 TX interrupts                                       */
+    USBD_LP_CAN0_RX0_IRQn        = 20,     /*!< CAN0 RX0 interrupts                                      */
+    CAN0_RX1_IRQn                = 21,     /*!< CAN0 RX1 interrupts                                      */
+    CAN0_EWMC_IRQn               = 22,     /*!< CAN0 EWMC interrupts                                     */
+    EXTI5_9_IRQn                 = 23,     /*!< EXTI[9:5] interrupts                                     */
+    TIMER0_BRK_TIMER8_IRQn       = 24,     /*!< TIMER0 break and TIMER8 interrupts                       */
+    TIMER0_UP_TIMER9_IRQn        = 25,     /*!< TIMER0 update and TIMER9 interrupts                      */
+    TIMER0_TRG_CMT_TIMER10_IRQn  = 26,     /*!< TIMER0 trigger and commutation and TIMER10 interrupts    */
+    TIMER0_Channel_IRQn          = 27,     /*!< TIMER0 channel capture compare interrupts                */
+    TIMER1_IRQn                  = 28,     /*!< TIMER1 interrupt                                         */
+    TIMER2_IRQn                  = 29,     /*!< TIMER2 interrupt                                         */
+    TIMER3_IRQn                  = 30,     /*!< TIMER3 interrupts                                        */
+    I2C0_EV_IRQn                 = 31,     /*!< I2C0 event interrupt                                     */
+    I2C0_ER_IRQn                 = 32,     /*!< I2C0 error interrupt                                     */
+    I2C1_EV_IRQn                 = 33,     /*!< I2C1 event interrupt                                     */
+    I2C1_ER_IRQn                 = 34,     /*!< I2C1 error interrupt                                     */
+    SPI0_IRQn                    = 35,     /*!< SPI0 interrupt                                           */
+    SPI1_IRQn                    = 36,     /*!< SPI1 interrupt                                           */
+    USART0_IRQn                  = 37,     /*!< USART0 interrupt                                         */
+    USART1_IRQn                  = 38,     /*!< USART1 interrupt                                         */
+    USART2_IRQn                  = 39,     /*!< USART2 interrupt                                         */
+    EXTI10_15_IRQn               = 40,     /*!< EXTI[15:10] interrupts                                   */
+    RTC_Alarm_IRQn               = 41,     /*!< RTC alarm interrupt                                      */
+    USBD_WKUP_IRQn               = 42,     /*!< USBD wakeup interrupt                                    */
+    TIMER7_BRK_TIMER11_IRQn      = 43,     /*!< TIMER7 break and TIMER11 interrupts                      */
+    TIMER7_UP_TIMER12_IRQn       = 44,     /*!< TIMER7 update and TIMER12 interrupts                     */
+    TIMER7_TRG_CMT_TIMER13_IRQn  = 45,     /*!< TIMER7 trigger and commutation and TIMER13 interrupts    */
+    TIMER7_Channel_IRQn          = 46,     /*!< TIMER7 channel capture compare interrupts                */
+    ADC2_IRQn                    = 47,     /*!< ADC2 global interrupt                                    */
+    EXMC_IRQn                    = 48,     /*!< EXMC global interrupt                                    */
+    SDIO_IRQn                    = 49,     /*!< SDIO global interrupt                                    */
+    TIMER4_IRQn                  = 50,     /*!< TIMER4 global interrupt                                  */
+    SPI2_IRQn                    = 51,     /*!< SPI2 global interrupt                                    */
+    UART3_IRQn                   = 52,     /*!< UART3 global interrupt                                   */
+    UART4_IRQn                   = 53,     /*!< UART4 global interrupt                                   */
+    TIMER5_IRQn                  = 54,     /*!< TIMER5 global interrupt                                  */
+    TIMER6_IRQn                  = 55,     /*!< TIMER6 global interrupt                                  */
+    DMA1_Channel0_IRQn           = 56,     /*!< DMA1 channel0 global interrupt                           */
+    DMA1_Channel1_IRQn           = 57,     /*!< DMA1 channel1 global interrupt                           */
+    DMA1_Channel2_IRQn           = 58,     /*!< DMA1 channel2 global interrupt                           */
+    DMA1_Channel3_Channel4_IRQn  = 59,     /*!< DMA1 channel3 and channel4 global interrupt              */
+#endif /* GD32F10X_XD */
+
+#ifdef GD32F10X_CL
+    CAN0_TX_IRQn                 = 19,     /*!< CAN0 TX interrupts                                       */
+    CAN0_RX0_IRQn                = 20,     /*!< CAN0 RX0 interrupts                                      */
+    CAN0_RX1_IRQn                = 21,     /*!< CAN0 RX1 interrupts                                      */
+    CAN0_EWMC_IRQn               = 22,     /*!< CAN0 EWMC interrupts                                     */
+    EXTI5_9_IRQn                 = 23,     /*!< EXTI[9:5] interrupts                                     */
+    TIMER0_BRK_IRQn              = 24,     /*!< TIMER0 break interrupts                                  */
+    TIMER0_UP_IRQn               = 25,     /*!< TIMER0 update interrupts                                 */
+    TIMER0_TRG_CMT_IRQn          = 26,     /*!< TIMER0 trigger and commutation interrupts                */
+    TIMER0_Channel_IRQn          = 27,     /*!< TIMER0 channel capture compare interrupts                */
+    TIMER1_IRQn                  = 28,     /*!< TIMER1 interrupt                                         */
+    TIMER2_IRQn                  = 29,     /*!< TIMER2 interrupt                                         */
+    TIMER3_IRQn                  = 30,     /*!< TIMER3 interrupts                                        */
+    I2C0_EV_IRQn                 = 31,     /*!< I2C0 event interrupt                                     */
+    I2C0_ER_IRQn                 = 32,     /*!< I2C0 error interrupt                                     */
+    I2C1_EV_IRQn                 = 33,     /*!< I2C1 event interrupt                                     */
+    I2C1_ER_IRQn                 = 34,     /*!< I2C1 error interrupt                                     */
+    SPI0_IRQn                    = 35,     /*!< SPI0 interrupt                                           */
+    SPI1_IRQn                    = 36,     /*!< SPI1 interrupt                                           */
+    USART0_IRQn                  = 37,     /*!< USART0 interrupt                                         */
+    USART1_IRQn                  = 38,     /*!< USART1 interrupt                                         */
+    USART2_IRQn                  = 39,     /*!< USART2 interrupt                                         */
+    EXTI10_15_IRQn               = 40,     /*!< EXTI[15:10] interrupts                                   */
+    RTC_Alarm_IRQn               = 41,     /*!< RTC alarm interrupt                                      */
+    USBFS_WKUP_IRQn              = 42,     /*!< USBFS wakeup interrupt                                   */
+    TIMER7_BRK_IRQn              = 43,     /*!< TIMER7 break interrupts                                  */
+    TIMER7_UP_IRQn               = 44,     /*!< TIMER7 update interrupts                                 */
+    TIMER7_TRG_CMT_IRQn          = 45,     /*!< TIMER7 trigger and commutation interrupts                */
+    TIMER7_Channel_IRQn          = 46,     /*!< TIMER7 channel capture compare interrupts                */
+    EXMC_IRQn                    = 48,     /*!< EXMC global interrupt                                    */
+    TIMER4_IRQn                  = 50,     /*!< TIMER4 global interrupt                                  */
+    SPI2_IRQn                    = 51,     /*!< SPI2 global interrupt                                    */
+    UART3_IRQn                   = 52,     /*!< UART3 global interrupt                                   */
+    UART4_IRQn                   = 53,     /*!< UART4 global interrupt                                   */
+    TIMER5_IRQn                  = 54,     /*!< TIMER5 global interrupt                                  */
+    TIMER6_IRQn                  = 55,     /*!< TIMER6 global interrupt                                  */
+    DMA1_Channel0_IRQn           = 56,     /*!< DMA1 channel0 global interrupt                           */
+    DMA1_Channel1_IRQn           = 57,     /*!< DMA1 channel1 global interrupt                           */
+    DMA1_Channel2_IRQn           = 58,     /*!< DMA1 channel2 global interrupt                           */
+    DMA1_Channel3_IRQn           = 59,     /*!< DMA1 channel3 global interrupt                           */
+    DMA1_Channel4_IRQn           = 60,     /*!< DMA1 channel3 global interrupt                           */
+    ENET_IRQn                    = 61,     /*!< ENET global interrupt                                    */
+    ENET_WKUP_IRQn               = 62,     /*!< ENET Wakeup interrupt                                    */
+    CAN1_TX_IRQn                 = 63,     /*!< CAN1 TX interrupt                                        */
+    CAN1_RX0_IRQn                = 64,     /*!< CAN1 RX0 interrupt                                       */
+    CAN1_RX1_IRQn                = 65,     /*!< CAN1 RX1 interrupt                                       */
+    CAN1_EWMC_IRQn               = 66,     /*!< CAN1 EWMC interrupt                                      */
+    USBFS_IRQn                   = 67,     /*!< USBFS global interrupt                                   */
+#endif /* GD32F10X_CL */
+
+} IRQn_Type;
+
+/* includes */
+#include "core_cm3.h"
+#include "system_gd32f10x.h"
+#include <stdint.h>
+
+/* enum definitions */
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus;
+typedef enum {FALSE = 0, TRUE = !FALSE} bool;
+typedef enum {RESET = 0, SET = !RESET} FlagStatus;
+typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus;
+
+/* bit operations */
+#define REG32(addr)                  (*(volatile uint32_t *)(uint32_t)(addr))
+#define REG16(addr)                  (*(volatile uint16_t *)(uint32_t)(addr))
+#define REG8(addr)                   (*(volatile uint8_t *)(uint32_t)(addr))
+#define BIT(x)                       ((uint32_t)((uint32_t)0x01U<<(x)))
+#define BITS(start, end)             ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) 
+#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start))
+
+/* main flash and SRAM memory map */
+#define FLASH_BASE            ((uint32_t)0x08000000U)        /*!< main FLASH base address          */
+#define SRAM_BASE             ((uint32_t)0x20000000U)        /*!< SRAM0 base address               */
+#define OB_BASE               ((uint32_t)0x1FFFF800U)        /*!< OB base address                  */
+#define DBG_BASE              ((uint32_t)0xE0042000U)        /*!< DBG base address                 */
+#define EXMC_BASE             ((uint32_t)0xA0000000U)        /*!< EXMC register base address       */
+
+/* peripheral memory map */
+#define APB1_BUS_BASE         ((uint32_t)0x40000000U)        /*!< apb1 base address                */
+#define APB2_BUS_BASE         ((uint32_t)0x40010000U)        /*!< apb2 base address                */
+#define AHB1_BUS_BASE         ((uint32_t)0x40018000U)        /*!< ahb1 base address                */
+#define AHB3_BUS_BASE         ((uint32_t)0x60000000U)        /*!< ahb3 base address                */
+
+/* advanced peripheral bus 1 memory map */
+#define TIMER_BASE            (APB1_BUS_BASE + 0x00000000U)  /*!< TIMER base address               */
+#define RTC_BASE              (APB1_BUS_BASE + 0x00002800U)  /*!< RTC base address                 */
+#define WWDGT_BASE            (APB1_BUS_BASE + 0x00002C00U)  /*!< WWDGT base address               */
+#define FWDGT_BASE            (APB1_BUS_BASE + 0x00003000U)  /*!< FWDGT base address               */
+#define SPI_BASE              (APB1_BUS_BASE + 0x00003800U)  /*!< SPI base address                 */
+#define USART_BASE            (APB1_BUS_BASE + 0x00004400U)  /*!< USART base address               */
+#define I2C_BASE              (APB1_BUS_BASE + 0x00005400U)  /*!< I2C base address                 */
+#define USBD_BASE             (APB1_BUS_BASE + 0x00005C00U)  /*!< USBD base address                */
+#define USBD_RAM_BASE         (APB1_BUS_BASE + 0x00006000U)  /*!< USBD RAM base address            */
+#define CAN_BASE              (APB1_BUS_BASE + 0x00006400U)  /*!< CAN base address                 */
+#define BKP_BASE              (APB1_BUS_BASE + 0x00006C00U)  /*!< BKP base address                 */
+#define PMU_BASE              (APB1_BUS_BASE + 0x00007000U)  /*!< PMU base address                 */
+#define DAC_BASE              (APB1_BUS_BASE + 0x00007400U)  /*!< DAC base address                 */
+
+/* advanced peripheral bus 2 memory map */
+#define AFIO_BASE             (APB2_BUS_BASE + 0x00000000U)  /*!< AFIO base address                */
+#define EXTI_BASE             (APB2_BUS_BASE + 0x00000400U)  /*!< EXTI base address                */
+#define GPIO_BASE             (APB2_BUS_BASE + 0x00000800U)  /*!< GPIO base address                */
+#define ADC_BASE              (APB2_BUS_BASE + 0x00002400U)  /*!< ADC base address                 */
+
+/* advanced high performance bus 1 memory map */
+#define SDIO_BASE             (AHB1_BUS_BASE + 0x00000000U)  /*!< SDIO base address                */
+#define DMA_BASE              (AHB1_BUS_BASE + 0x00008000U)  /*!< DMA base address                 */
+#define RCU_BASE              (AHB1_BUS_BASE + 0x00009000U)  /*!< RCU base address                 */
+#define FMC_BASE              (AHB1_BUS_BASE + 0x0000A000U)  /*!< FMC base address                 */
+#define CRC_BASE              (AHB1_BUS_BASE + 0x0000B000U)  /*!< CRC base address                 */
+#define ENET_BASE             (AHB1_BUS_BASE + 0x00010000U)  /*!< ENET base address                */
+#define USBFS_BASE            (AHB1_BUS_BASE + 0x0FFE8000U)  /*!< USBFS base address               */
+
+/* define marco USE_STDPERIPH_DRIVER */
+#if !defined  USE_STDPERIPH_DRIVER
+#define USE_STDPERIPH_DRIVER
+#endif 
+#ifdef USE_STDPERIPH_DRIVER
+#include "gd32f10x_libopt.h"
+#endif /* USE_STDPERIPH_DRIVER */
+
+#ifdef cplusplus
+}
+#endif
+#endif 

+ 1059 - 0
CMSIS/system_gd32f10x.c

@@ -0,0 +1,1059 @@
+/*!
+    \file    system_gd32f10x.c
+    \brief   CMSIS Cortex-M3 Device Peripheral Access Layer Source File for
+             GD32F10x Device Series
+*/
+
+/*
+    Copyright (c) 2012 ARM LIMITED
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
+
+#include "gd32f10x.h"
+
+/* system frequency define */
+#define __IRC8M           (IRC8M_VALUE)            /* internal 8 MHz RC oscillator frequency */
+#define __HXTAL           (HXTAL_VALUE)            /* high speed crystal oscillator frequency */
+#define __SYS_OSC_CLK     (__IRC8M)                /* main oscillator frequency */
+
+#define VECT_TAB_OFFSET  (uint32_t) 0x18000            /* vector table base offset */
+
+/* select a system clock by uncommenting the following line */
+/* use IRC8M */
+//#define __SYSTEM_CLOCK_48M_PLL_IRC8M            (uint32_t)(48000000)
+//#define __SYSTEM_CLOCK_72M_PLL_IRC8M            (uint32_t)(72000000)
+//#define __SYSTEM_CLOCK_108M_PLL_IRC8M           (uint32_t)(108000000)
+
+/* use HXTAL (XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */
+//#define __SYSTEM_CLOCK_HXTAL                    (uint32_t)(__HXTAL)
+//#define __SYSTEM_CLOCK_24M_PLL_HXTAL            (uint32_t)(24000000)
+//#define __SYSTEM_CLOCK_36M_PLL_HXTAL            (uint32_t)(36000000)
+//#define __SYSTEM_CLOCK_48M_PLL_HXTAL            (uint32_t)(48000000)
+//#define __SYSTEM_CLOCK_56M_PLL_HXTAL            (uint32_t)(56000000)
+#define __SYSTEM_CLOCK_72M_PLL_HXTAL            (uint32_t)(72000000)
+//#define __SYSTEM_CLOCK_96M_PLL_HXTAL            (uint32_t)(96000000)
+//#define __SYSTEM_CLOCK_108M_PLL_HXTAL           (uint32_t)(108000000)
+
+#define RCU_MODIFY(__delay)     do{                                     \
+                                    volatile uint32_t i;                \
+                                    if(0 != __delay){                   \
+                                        RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \
+                                        for(i=0; i<__delay; i++){       \
+                                        }                               \
+                                        RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; \
+                                        for(i=0; i<__delay; i++){       \
+                                        }                               \
+                                    }                                   \
+                                }while(0)
+
+#define SEL_IRC8M       0x00U
+#define SEL_HXTAL       0x01U
+#define SEL_PLL         0x02U
+
+/* set the system clock frequency and declare the system clock configuration function */
+#ifdef __SYSTEM_CLOCK_48M_PLL_IRC8M
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M;
+static void system_clock_48m_irc8m(void);
+#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
+static void system_clock_72m_irc8m(void);
+#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M;
+static void system_clock_108m_irc8m(void);
+
+#elif defined (__SYSTEM_CLOCK_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
+static void system_clock_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL;
+static void system_clock_24m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL;
+static void system_clock_36m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL;
+static void system_clock_48m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL;
+static void system_clock_56m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
+static void system_clock_72m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL;
+static void system_clock_96m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL;
+static void system_clock_108m_hxtal(void);
+#endif /* __SYSTEM_CLOCK_48M_PLL_IRC8M */
+
+/* configure the system clock */
+static void system_clock_config(void);
+
+/*!
+    \brief      configure the system clock
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_config(void)
+{
+#ifdef __SYSTEM_CLOCK_HXTAL
+    system_clock_hxtal();
+#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
+    system_clock_24m_hxtal();
+#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
+    system_clock_36m_hxtal();
+#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
+    system_clock_48m_hxtal();
+#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
+    system_clock_56m_hxtal();
+#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
+    system_clock_72m_hxtal();
+#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
+    system_clock_96m_hxtal();
+#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
+    system_clock_108m_hxtal();
+
+#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
+    system_clock_48m_irc8m();
+#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
+    system_clock_72m_irc8m();
+#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
+    system_clock_108m_irc8m();
+#endif /* __SYSTEM_CLOCK_HXTAL */
+}
+
+/*!
+    \brief      setup the microcontroller system, initialize the system
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void SystemInit(void)
+{
+    /* reset the RCC clock configuration to the default reset state */
+    /* enable IRC8M */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+    while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
+    }
+    RCU_MODIFY(0x50);
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    /* reset HXTALEN, CKMEN, PLLEN bits */
+    RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
+
+    /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */
+    RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
+                  RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL);
+
+    /* reset HXTALEN, CKMEN, PLLEN bits */
+    RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
+
+    /* Reset HXTALBPS bit */
+    RCU_CTL &= ~(RCU_CTL_HXTALBPS);
+
+    /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */
+    
+#ifdef GD32F10X_CL
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
+                  RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4);
+
+    RCU_CFG1 = 0x00000000U;
+#else
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF |
+                  RCU_CFG0_USBDPSC | RCU_CFG0_PLLMF_4);
+#endif /* GD32F10X_CL */
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* reset HXTALEN, CKMEN and PLLEN bits */
+    RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
+    /* disable all interrupts */
+    RCU_INT = 0x009F0000U;
+#elif defined(GD32F10X_CL)
+    /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
+    RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
+    /* disable all interrupts */
+    RCU_INT = 0x00FF0000U;
+#endif
+
+    /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
+    system_clock_config();
+    
+#ifdef VECT_TAB_SRAM
+    nvic_vector_table_set(NVIC_VECTTAB_RAM, VECT_TAB_OFFSET);
+#else
+    nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET);
+#endif
+}
+
+/*!
+    \brief      update the SystemCoreClock with current core clock retrieved from cpu registers
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void SystemCoreClockUpdate(void)
+{
+    uint32_t scss;
+    uint32_t pllsel, predv0sel, pllmf, ck_src, idx, clk_exp;
+#ifdef  GD32F10X_CL
+    uint32_t predv0, predv1, pll1mf;
+#endif /* GD32F10X_CL */
+    /* exponent of AHB, APB1 and APB2 clock divider */
+    const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+    scss = GET_BITS(RCU_CFG0, 2, 3);
+
+    switch (scss)
+    {
+        /* IRC8M is selected as CK_SYS */
+        case SEL_IRC8M:
+            SystemCoreClock = IRC8M_VALUE;
+            break;
+            
+        /* HXTAL is selected as CK_SYS */
+        case SEL_HXTAL:
+            SystemCoreClock = HXTAL_VALUE;
+            break;
+            
+        /* PLL is selected as CK_SYS */
+        case SEL_PLL:
+            /* PLL clock source selection, HXTAL or IRC8M/2 */
+            pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
+
+            if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){
+                /* PLL clock source is IRC8M/2 */
+                ck_src = IRC8M_VALUE / 2U;
+            }else{
+                /* PLL clock source is HXTAL */
+                ck_src = HXTAL_VALUE;
+            
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+                predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0);
+
+                /* PREDV0 input source clock divided by 2 */
+                if(RCU_CFG0_PREDV0 == predv0sel){
+                    ck_src = HXTAL_VALUE / 2U;
+                }
+#elif defined(GD32F10X_CL)
+                predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
+
+                /* source clock use PLL1 */
+                if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
+                    predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
+                    pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
+                    if(17U == pll1mf){
+                        pll1mf = 20U;
+                    }
+                    ck_src = (ck_src / predv1) * pll1mf;
+                }
+                predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
+                ck_src /= predv0;
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+            }
+
+            /* PLL multiplication factor */
+            pllmf = GET_BITS(RCU_CFG0, 18, 21);
+
+            if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
+                pllmf |= 0x10U;
+            }
+
+            if(pllmf >= 15U){
+                pllmf += 1U;
+            }else{
+                pllmf += 2U;
+            }
+
+            SystemCoreClock = ck_src * pllmf;
+
+#ifdef GD32F10X_CL
+            if(15U == pllmf){
+                /* PLL source clock multiply by 6.5 */
+                SystemCoreClock = ck_src * 6U + ck_src / 2U;
+            }
+#endif /* GD32F10X_CL */
+
+            break;
+
+        /* IRC8M is selected as CK_SYS */
+        default:
+            SystemCoreClock = IRC8M_VALUE;
+            break;
+    }
+    /* calculate AHB clock frequency */
+    idx = GET_BITS(RCU_CFG0, 4, 7);
+    clk_exp = ahb_exp[idx];
+    SystemCoreClock = SystemCoreClock >> clk_exp;
+}
+
+#ifdef __SYSTEM_CLOCK_HXTAL
+/*!
+    \brief      configure the system clock to HXTAL
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+    
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+    
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+    
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+    
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+    
+    /* select HXTAL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_HXTAL;
+    
+    /* wait until HXTAL is selected as system clock */
+    while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 24M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_24m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 6 = 24 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL6;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 36M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_36m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 9 = 36 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL9;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_48m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL12;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 56M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_56m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 14 = 56 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL14;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 14 = 56 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL14);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_72m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL18;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_96m_hxtal(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 24 = 96 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL24;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 108M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_108m_hxtal(void)
+{
+    uint32_t timeout   = 0U;
+    uint32_t stab_flag = 0U;
+
+    /* enable HXTAL */
+    RCU_CTL |= RCU_CTL_HXTALEN;
+
+    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
+    }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
+        while(1){
+        }
+    }
+
+    /* HXTAL is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL27;
+
+#elif defined(GD32F10X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
+
+    /* enable PLL1 */
+    RCU_CTL |= RCU_CTL_PLL1EN;
+    /* wait till PLL1 is ready */
+    while(0U == (RCU_CTL & RCU_CTL_PLL1STB)){
+    }
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
+/*!
+    \brief      configure the system clock to 48M by PLL which selects IRC8M as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_48m_irc8m(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+    
+    /* enable IRC8M */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+
+    /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
+    }
+    while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
+      while(1){
+      }
+    }
+
+    /* IRC8M is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+    /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL12;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
+/*!
+    \brief      configure the system clock to 72M by PLL which selects IRC8M as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_72m_irc8m(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+    
+    /* enable IRC8M */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+
+    /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
+    }
+    while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
+      while(1){
+      }
+    }
+
+    /* IRC8M is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+    /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL18;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
+/*!
+    \brief      configure the system clock to 108M by PLL which selects IRC8M as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_108m_irc8m(void)
+{
+    uint32_t timeout = 0U;
+    uint32_t stab_flag = 0U;
+    
+    /* enable IRC8M */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+
+    /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
+    do{
+        timeout++;
+        stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
+    }
+    while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
+
+    /* if fail */
+    if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
+      while(1){
+      }
+    }
+
+    /* IRC8M is stable */
+    /* AHB = SYSCLK */
+    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
+    /* APB2 = AHB/1 */
+    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
+    /* APB1 = AHB/2 */
+    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
+
+    /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    RCU_CFG0 |= RCU_PLL_MUL27;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* select PLL as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
+
+    /* wait until PLL is selected as system clock */
+    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
+    }
+}
+
+#endif

+ 60 - 0
CMSIS/system_gd32f10x.h

@@ -0,0 +1,60 @@
+/*!
+    \file    system_gd32f10x.h
+    \brief   CMSIS Cortex-M3 Device Peripheral Access Layer Header File for
+             GD32F10x Device Series
+*/
+
+/*
+    Copyright (c) 2012 ARM LIMITED
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
+
+#ifndef SYSTEM_GD32F10X_H
+#define SYSTEM_GD32F10X_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* system clock frequency (core clock) */
+extern uint32_t SystemCoreClock;
+
+/* function declarations */
+/* initialize the system and update the SystemCoreClock variable */
+extern void SystemInit(void);
+/* update the SystemCoreClock with current core clock retrieved from cpu registers */
+extern void SystemCoreClockUpdate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_GD32F10X_H */

BIN
HEAD.zip


+ 158 - 0
Hardware/I2C.c

@@ -0,0 +1,158 @@
+#include "I2C.h"
+#include "timeout.h"
+
+void delay_us(uint32_t nUs)
+{
+    uint32_t i=0,j=0;
+    for(i=0;i<nUs;i++){
+        for(j=0;j<9;j++){
+            ;
+        }
+    }
+}
+
+void delay_ms(uint16_t nms)
+{
+    delay_us(nms*1000);
+}
+
+/*-----------------------------------------------
+ *  I2C 初始化
+ * ----------------------------------------------*/
+void i2c_init(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOB);/* enable GPIO clock */
+    rcu_periph_clock_enable(RCU_GPIOD);/* enable GPIO clock */
+
+    gpio_bit_set(IIC_WP_PORT,IIC_WP_PIN); /* 写保护启用 */
+    gpio_init(IIC_WP_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, IIC_WP_PIN);/*写使能 PE15 */
+
+    gpio_bit_set(IIC_SCL_PORT,IIC_SCL_PIN); /* 时钟信号 置高 */
+    gpio_init(IIC_SCL_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, IIC_SCL_PIN);/* SCL 时钟信号 PB6 */
+
+    gpio_bit_set(IIC_SDA_PORT,IIC_SDA_PIN); /* 数据信号 置高 */
+    gpio_init(IIC_SDA_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, IIC_SDA_PIN);/* DA 数据信号 PB7 */
+}
+/*--------------------------------------------------
+ * I2C的起始信号
+ * -------------------------------------------------*/
+void i2c_start(void)
+{
+    SDA_OUT();
+    IIC_SDA(1);//IIC_SDA = 1;
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(4);
+    IIC_SDA(0);//IIC_SDA = 0;//START:when CLK is high,DATA change form high to low
+    delay_us(4);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+/*------------------------------------------------------
+ *  I2C的停止信号
+ * -----------------------------------------------------*/
+void i2c_stop(void)
+{
+    SDA_OUT();
+    IIC_SDA(0);//IIC_SDA = 0;
+    IIC_SCL(0);//IIC_SCL = 0;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+	  delay_us(4);
+    IIC_SDA(1);//IIC_SDA = 1;
+    delay_us(4);
+}
+/*-----------------------------------------------------
+ * I2C 等待信号应答
+ * 返回: 0:接收应答成功
+ *       1:接收应答失败
+ * ---------------------------------------------------*/
+uint8_t i2c_wait_ack(void)
+{
+    uint8_t ucErrTime=0;
+    SDA_IN();  // SDA 配置成输入
+    IIC_SDA(1);//IIC_SDA=1;
+    delay_us(1);
+    IIC_SCL(1);//IIC_SCL=1;
+    delay_us(1);
+    while(READ_SDA)
+    {
+        ucErrTime++;
+        if(ucErrTime>250)
+        {
+        i2c_stop();
+        return 1;
+        }
+    }
+    IIC_SCL(0);//IIC_SCL=0;
+    return 0;
+}
+/*-----------------------------------------------------
+ *  I2C 产生应答
+ * ---------------------------------------------------*/
+void i2c_Ack(void)
+{
+    IIC_SCL(0);//IIC_SCL = 0;
+    SDA_OUT();
+    IIC_SDA(0);//IIC_SDA = 0;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(2);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+/*-----------------------------------------------------
+ *  I2C 没有产生应答
+ * ---------------------------------------------------*/
+void i2c_NAck(void)
+{
+    IIC_SCL(0);//IIC_SCL = 0;
+    SDA_OUT();
+    IIC_SDA(1);//IIC_SDA = 1;
+    delay_us(4);
+    IIC_SCL(1);//IIC_SCL = 1;
+    delay_us(2);
+    IIC_SCL(0);//IIC_SCL = 0;
+}
+/*-----------------------------------------------------
+ *  IIC 发送一个字节
+ *  返回 1:有应答  0:无应答
+ * ---------------------------------------------------*/
+void i2c_send_byte(uint8_t txd)
+{
+  uint8_t t;
+  IIC_SCL(0);//IIC_SCL=0;// 电平置低,开始传输数据
+  SDA_OUT();
+  for(t=0;t<8;t++)
+  {
+   // IIC_SDA=(txd&0x80)>>7;
+    if((txd&0x80)>>7) IIC_SDA(1);
+    else IIC_SDA(0);
+    txd<<=1;
+    delay_us(4);   //
+    IIC_SCL(1);//IIC_SCL=1;
+    delay_us(2);
+    IIC_SCL(0);//IIC_SCL=0;
+    delay_us(2);
+
+  }
+}
+/*-------------------------------------------------
+ * 读1个字节,ack=1时,发送ACK,ack=0,发送nACK
+ * -------------------------------------------------*/
+uint8_t i2c_read_byte(uint8_t ack)
+{
+    uint8_t i,receive=0;
+    SDA_IN();//SDA设置为输入
+    for(i=0;i<8;i++ )
+    {
+        IIC_SCL(0);//IIC_SCL=0;
+        delay_us(4);
+        IIC_SCL(1);//IIC_SCL=1;
+        receive<<=1;
+        if(READ_SDA)receive++;
+        delay_us(1);
+    }
+    if(!ack)
+        i2c_NAck();//发送nACK
+    else
+        i2c_Ack(); //发送ACK
+    return receive;
+}

+ 60 - 0
Hardware/I2C.h

@@ -0,0 +1,60 @@
+#ifndef _I2C_H_
+#define _I2C_H_
+
+#include "../User/gd32f10x_it.h"
+#include <stdio.h>
+
+#define IIC_WP_PORT     GPIOD
+#define IIC_WP_PIN      GPIO_PIN_8 // 写使能
+
+#define IIC_SDA_PORT    GPIOB
+#define IIC_SDA_PIN	GPIO_PIN_11 // 数据线
+
+#define IIC_SCL_PORT	GPIOB
+#define IIC_SCL_PIN     GPIO_PIN_10 // 时钟线
+
+/*
+GPIO_CTL1(GPIOA) &= 0xfffff0ff;   //设置RX引脚浮空输入  PA10
+GPIO_CTL1(GPIOA) |= (0x00000004<<(4*2));
+GPIO_CTL1(GPIOA) &= 0xffffff0f;   //设置TX引脚复用推完输出  50M     PA9
+GPIO_CTL1(GPIOA) |= (0x0000000B<<(4*1));
+
+GPIO_BOP(GPIOC) = GPIO_PIN_2; // 置高电平
+GPIO_BC(GPIOC) = GPIO_PIN_2; // 置低电平
+*/
+
+#define SDA_IN()  {GPIO_CTL1(GPIOB) &= 0xFFFF0FFF;GPIO_CTL1(GPIOB) |= ((uint32_t)8<<(12));} //PB11 输入模式
+#define SDA_OUT() {GPIO_CTL1(GPIOB) &= 0xFFFF0FFF;GPIO_CTL1(GPIOB) |= ((uint32_t)3<<(12));} //PB11 输出模式
+
+//#define SDA_IN()  {GPIO_CTL0(GPIOB)&=~GPIO_MODE_MASK(7);GPIO_CTL0(GPIOB)|=GPIO_MODE_SET(7,0x8);}//PB7 输入
+//#define SDA_OUT() {GPIO_CTL0(GPIOB)&=~GPIO_MODE_MASK(7);GPIO_CTL0(GPIOB)|=GPIO_MODE_SET(7,0x3);}//PB7 输出
+
+
+
+
+//#define IIC_SCL(n)  (n?GPIO_BOP(GPIOB) = GPIO_PIN_10:GPIO_BC(GPIOB) = GPIO_PIN_10)            //SCL
+//#define IIC_SDA(n)  (n?GPIO_BOP(GPIOB) = GPIO_PIN_11:GPIO_BC(GPIOB) = GPIO_PIN_11) //SDA
+#define IIC_SCL(n) (n?gpio_bit_set(GPIOB, GPIO_PIN_10):gpio_bit_reset(GPIOB, GPIO_PIN_10))
+#define IIC_SDA(n) (n?gpio_bit_set(GPIOB, GPIO_PIN_11):gpio_bit_reset(GPIOB, GPIO_PIN_11))
+#define READ_SDA   (gpio_input_bit_get(GPIOB,GPIO_PIN_11)) // 输入SDA
+
+ /* 写保护 低电平允许写入  高电平 禁止写入 */
+#define IIC_WRITE_PROTECT_ON()   {GPIO_BOP(IIC_WP_PORT)=IIC_WP_PIN;} //
+#define IIC_WRITE_PROTECT_OFF()  {GPIO_BC(IIC_WP_PORT)=IIC_WP_PIN;} //
+
+
+extern void delay_us(uint32_t nUs);
+extern void delay_ms(uint16_t nms);
+
+
+extern void i2c_init(void);
+extern void i2c_start(void);
+extern void i2c_stop(void);
+extern uint8_t i2c_wait_ack(void);
+extern void i2c_Ack(void);
+extern void i2c_NAck(void);
+extern void i2c_send_byte(uint8_t txd);
+extern uint8_t i2c_read_byte(uint8_t ack);
+
+
+#endif

+ 267 - 0
Hardware/Timer.c

@@ -0,0 +1,267 @@
+#include "Timer.h"
+#include "boardinit.h"
+#include "../App/public.h"
+#include "../App/xspDataOpt.h"
+
+uint32_t g_iDelayfinish;
+volatile uint32_t gTimer_tickt = 0;
+ TimerInfo g_timeInfo;
+
+void TIMER5_IRQHandler(void)
+{ 
+    if(timer_flag_get(TIMER5,TIMER_FLAG_UP) != RESET){
+        g_iDelayfinish = 1;
+        timer_disable(TIMER5);
+        timer_flag_clear(TIMER5,TIMER_FLAG_UP);/* 定时器更新中断的标识位需要手动清除 */
+    }
+}
+void timer5_init(void)
+{
+    timer_parameter_struct timer_initpara;
+    rcu_periph_clock_enable(RCU_TIMER5);/* 使能TIMER5时钟 */
+
+    /* TIMER5 初始化配置 */
+    timer_deinit(TIMER5);
+    timer_initpara.prescaler         = 7200-1;/* 时钟预分频系数 10KHz*/
+    timer_initpara.period            = 1000-1;/* 自动重装载值 500-500us 1000-1ms */
+    timer_initpara.counterdirection  = TIMER_COUNTER_UP;	     /* 向上计数模式 */
+    timer_init(TIMER5,&timer_initpara);
+    timer_single_pulse_mode_config(TIMER5,TIMER_SP_MODE_SINGLE);
+    //timer_enable(TIMER5);
+    nvic_irq_enable(TIMER5_IRQn, 3, 3);/* TIMER5中断设置,抢占优先级3,子优先级3 */
+    //timer_interrupt_enable(TIMER5,TIMER_INT_UP);/* 使能更新中断 */
+    timer_flag_clear(TIMER5,TIMER_FLAG_UP);/* 定时器更新中断的标识位需要手动清除 */
+    timer_interrupt_disable(TIMER5,TIMER_INT_UP);
+    timer_counter_value_config(TIMER5,0);
+    timer_disable(TIMER5);
+}
+void start_delay_ms(uint32_t delayms)
+{
+    g_iDelayfinish = 0;
+    //timer_prescaler_config(TIMER5,10800-1);
+    timer_autoreload_value_config(TIMER5,delayms*10-1);
+    timer_counter_value_config(TIMER5,0);
+    timer_enable(TIMER5);
+    timer_interrupt_enable(TIMER5,TIMER_INT_UP);/* 使能更新中断 */
+}
+void stop_delay_ms(void)
+{
+    timer_disable(TIMER5);
+    timer_flag_clear(TIMER5,TIMER_FLAG_UP);/* 定时器更新中断的标识位需要手动清除 */
+}
+
+static void display_led_status(uint32_t tickt)
+{
+    static volatile uint8_t ledgreen = 0, ledred=0;
+    static volatile uint8_t num = 0;
+    if(0 == g_devMsg.ledgreen) { // 绿灯状态不亮
+        LED_GREEN_SET();// gpio_bit_set(GPIOC, GPIO_PIN_13);
+    }
+    else if(1 == g_devMsg.ledgreen){ // 绿灯慢闪
+        if(tickt%50000==0) {
+            if(ledgreen==0) LED_GREEN_SET();//gpio_bit_set(GPIOC, GPIO_PIN_13);
+            else    LED_GREEN_RESET();//gpio_bit_reset(GPIOC, GPIO_PIN_13);
+            ledgreen = !ledgreen;
+        }
+    }
+    else if(2 == g_devMsg.ledgreen) { // 绿灯快闪
+        if(tickt%20000==0) {
+            if(ledgreen==0) LED_GREEN_SET();//gpio_bit_set(GPIOC, GPIO_PIN_13);
+            else    LED_GREEN_RESET();//gpio_bit_reset(GPIOC, GPIO_PIN_13);
+            ledgreen = !ledgreen;
+        }
+    }
+    else if(3 == g_devMsg.ledgreen) { // 绿灯常亮
+        LED_GREEN_RESET();//gpio_bit_reset(GPIOC, GPIO_PIN_13);
+    }
+    else if((4 == g_devMsg.ledgreen) ||(5 == g_devMsg.ledgreen)){
+        if( g_devMsg.ledgreen == 5){
+            if((tickt%30002) == 0){
+                g_devMsg.ledgreen = 6;
+                return;
+            }
+        }
+        if(tickt%20000==0) {
+            if(ledgreen==0) {
+                LED_GREEN_SET();//gpio_bit_set(GPIOC, GPIO_PIN_13);
+                LED_RED_SET();//gpio_bit_set(GPIOA, GPIO_PIN_0);
+            }
+            else    {
+                LED_GREEN_RESET();//gpio_bit_reset(GPIOC, GPIO_PIN_13);
+                LED_RED_RESET();//gpio_bit_reset(GPIOA, GPIO_PIN_0);
+                num++;
+                if(num>g_devMsg.ledred){
+                    g_devMsg.ledgreen = 5;// 上电显示灯已经结束
+                    LED_GREEN_SET();//gpio_bit_set(GPIOC, GPIO_PIN_13);
+                    LED_RED_SET();//gpio_bit_set(GPIOA, GPIO_PIN_0);
+                    ledgreen = 1;
+                }
+            }
+
+            ledgreen = !ledgreen;
+        }
+        return;
+    }
+
+
+    if(0 == g_devMsg.ledred) { // 红灯状态不亮
+        LED_RED_SET();//gpio_bit_set(GPIOA, GPIO_PIN_0);
+    }
+    else if(1 == g_devMsg.ledred){ // 红灯慢闪
+        if(tickt%50000==0) {
+            if(ledred==0) LED_RED_SET();//gpio_bit_set(GPIOA, GPIO_PIN_0);
+            else    LED_RED_RESET();//gpio_bit_reset(GPIOA, GPIO_PIN_0);
+            ledred = !ledred;
+        }
+    }
+    else if(2 == g_devMsg.ledred) { // 红灯快闪
+        if(tickt%20000==0) {
+            if(ledred==0) LED_RED_SET();//gpio_bit_set(GPIOA, GPIO_PIN_0);
+            else    LED_RED_RESET();//gpio_bit_reset(GPIOA, GPIO_PIN_0);
+            ledred = !ledred;
+        }
+    }
+    else if(3 == g_devMsg.ledred) { // 红灯常亮
+        LED_RED_RESET();//gpio_bit_reset(GPIOA, GPIO_PIN_0);
+    }
+
+}
+void TIMER4_IRQHandler(void)
+{
+    volatile uint8_t status = 0,i = 0,j=0;
+    volatile uint16_t status1 = 0,daUp = 0,daDn = 0;
+    volatile uint8_t count = 0,flag = 0;
+    volatile static uint32_t lasttick = 0;
+    if(RESET != timer_flag_get(TIMER4,TIMER_FLAG_UP)){
+        gTimer_tickt++;
+        display_led_status(gTimer_tickt);
+        deal_gun_status(gTimer_tickt);
+#if (0) //(SEL_74CH165)
+//    if((g_timeInfo.bExit == 1) &&((gTimer_tickt-g_timeInfo.exitTick)>=g_timeInfo.delay) ){
+//        if((0 == g_timeInfo.bRead) && (RESET == gpio_input_bit_get(g_extimsg.csGroup,g_extimsg.extiPin))){
+//            //exti_interrupt_disable(g_extimsg.extiLine); // 关闭外部中断
+//            reset_port_pin(PLNALL,USE_PORT_ID);
+//            delay_ms(3);//延时
+//            set_port_pin(PLNALL,USE_PORT_ID);
+//            g_timeInfo.bExit = 0;
+//            g_timeInfo.bRead = 1;
+//        }
+//    }
+#else
+#if(NO_INIT_COLLECT)
+//    if(g_testCollDa.bTestCollDa == 0){
+//        if((g_timeInfo.bExit == 1) &&((gTimer_tickt-g_timeInfo.exitTick)>=g_timeInfo.delay) ){
+//            exti_interrupt_disable(g_extimsg.extiLine); // 关闭外部中断
+//            for(count = 0;count<COLLECT_NUM;count++){
+//                status = gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin);
+
+//                //status1 = (status == 1 ? 0xFFFF : 0x0000);
+//                if(status == 0x00) {
+//                    flag = 0;
+//                    set_all_cs_port_status(SET); // 所有的片选置高
+//                    for(j=0;j<20;j++);
+//                    for(i=0;i<CS_GROUP_NUM;i++){
+//                        gpio_bit_reset(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+//                        gpio_bit_reset(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+//                        for(j=0;j<20;j++);
+//                        daDn = (gpio_input_port_get(GPIOE));//(status1)^
+//                        daUp = (gpio_input_port_get(GPIOD));// (status1)^
+
+//                        g_timeInfo.testsrcDa[count][i] = (daDn>>8)&0xFF;
+//                        g_timeInfo.testsrcDa[count][i+CS_GROUP_NUM] = daUp&0xFF;
+
+//                        //g_timeInfo.srcDa[i] = (daDn>>8)&0xFF;
+//                        //g_timeInfo.srcDa[i+CS_GROUP_NUM] = daUp&0xFF;
+
+//                        gpio_bit_set(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+//                        gpio_bit_set(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+//                        for(j=0;j<20;j++);
+//                    }
+//                }
+//                else {
+//                    if((flag++) >3)
+//                        break;
+//                }
+//            }
+//            g_timeInfo.count = count -flag;
+//            //if(count >=COLLECT_NUM) {
+//                g_timeInfo.bExit = 0;
+//                g_timeInfo.bRead = 1;
+//            //    count = 0;
+//            //}
+//        }
+//    }
+//    else 
+      if((g_testCollDa.bTestCollDa == 1)&&(g_testCollDa.bdealDa == 0)){ // 测试采集数据的电平
+        if(((gTimer_tickt%g_testCollDa.collTime) == 0) && (gTimer_tickt != lasttick)) {
+            set_all_cs_port_status(SET); // 所有的片选置高
+            for(j=0;j<20;j++);
+            if(g_devMsg.bHYdev == 0x00){
+                for(i=0;i<CS_GROUP_NUM;i++){
+                    //if(i!=8) continue;
+                    gpio_bit_reset(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_reset(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+                    for(j=0;j<20;j++);
+                    daDn = (gpio_input_port_get(GPIOE));
+                    g_testCollDa.collDa[g_testCollDa.collNum][i] = (daDn>>8)&0xFF;
+
+                    daUp = (gpio_input_port_get(GPIOD));
+                    g_testCollDa.collDa[g_testCollDa.collNum][i+CS_GROUP_NUM] = daUp&0xFF;
+
+                    gpio_bit_set(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_set(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+
+                    for(j=0;j<20;j++);
+                }
+            }
+            else {
+                for(i=0;i<CS_GROUP_NUM;i++){
+                    //if(i!=8) continue;
+                    gpio_bit_reset(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_reset(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+                    for(j=0;j<5;j++);
+                    daDn = (gpio_input_port_get(GPIOE));
+                    g_testCollDa.collDa[g_testCollDa.collNum][i] = (daDn>>8)&0xFF;
+
+                    daUp = (gpio_input_port_get(GPIOD));
+                    g_testCollDa.collDa[g_testCollDa.collNum][i+CS_GROUP_NUM] = daUp&0xFF;
+
+                    gpio_bit_set(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_set(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+
+                    for(j=0;j<5;j++);
+                }
+            }
+            //g_testCollDa.timer[g_testCollDa.collNum] = gTimer_tickt;
+            g_testCollDa.collNum = (g_testCollDa.collNum+1)%TEST_COLL_DA_MAX_NUM;
+            if(g_testCollDa.collNum == 0) g_testCollDa.bdealDa = 1;
+            lasttick = gTimer_tickt;
+
+        }
+    }
+#endif
+#endif
+        timer_flag_clear(TIMER4,TIMER_FLAG_UP);/* 定时器更新中断的标识位需要手动清除 */
+    }
+}
+/*-------------------------------------------------------------------------
+ *  初始化定时器4
+ *  10us中断一次
+ * ------------------------------------------------------------------------*/
+void timer4_init(void)
+{
+    timer_parameter_struct timer_initpara;
+    rcu_periph_clock_enable(RCU_TIMER4);/* 使能TIMER5时钟 */
+
+    /* TIMER5 初始化配置 */
+    timer_deinit(TIMER4);
+    timer_initpara.prescaler         = 71;/* 时钟预分频系数 */
+    timer_initpara.period            = 9;/* 自动重装载值 500-500us 1000-1ms */
+    timer_init(TIMER4,&timer_initpara);
+
+    timer_enable(TIMER4);
+
+    nvic_irq_enable(TIMER4_IRQn, 3, 2);/* TIMER5中断设置,抢占优先级3,子优先级3 */
+    timer_interrupt_enable(TIMER4,TIMER_INT_UP);/* 使能更新中断 */
+}
+

+ 31 - 0
Hardware/Timer.h

@@ -0,0 +1,31 @@
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#include "../User/gd32f10x_it.h"
+#include <stdio.h>
+
+#define LED PCout(13)
+
+#define NO_INIT_COLLECT 1
+#define COLLECT_NUM 50
+
+extern volatile uint32_t gTimer_tickt;
+
+extern uint32_t g_iDelayfinish;
+typedef struct {
+	  volatile uint8_t count;
+    volatile uint8_t bExit; // PD5中断
+    volatile uint8_t bRead; // 数据读取完成
+    volatile uint8_t srcDa[29]; // 读取135个管脚的原始数据
+    volatile uint32_t delay; // 中断来后,延时时间后再读取管脚
+    volatile uint32_t exitTick; // 中断时的处理
+    volatile uint8_t testsrcDa[COLLECT_NUM][29];
+}TimerInfo;
+extern TimerInfo g_timeInfo;
+
+
+extern void timer5_init(void);
+extern void timer4_init(void);
+extern void start_delay_ms(uint32_t delayms);
+extern void stop_delay_ms(void);
+#endif

+ 237 - 0
Hardware/Uart.c

@@ -0,0 +1,237 @@
+#include "Uart.h"
+#include "fifo.h"
+
+uint8_t g_bPrintDebug = 0;
+
+
+void usart0_config(void)
+{
+    /* enable GPIO clock */
+    rcu_periph_clock_enable(RCU_GPIOA);
+
+    /* enable USART clock */
+    rcu_periph_clock_enable(RCU_USART0);
+
+    /* connect port to USARTx_Tx */
+    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
+
+    /* connect port to USARTx_Rx */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
+
+    /* USART configure */
+    usart_deinit(USART0);
+    usart_word_length_set(USART0, USART_WL_8BIT);
+    usart_stop_bit_set(USART0, USART_STB_1BIT);
+    usart_parity_config(USART0, USART_PM_NONE);
+    usart_baudrate_set(USART0, 115200U);
+    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
+    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
+    usart_enable(USART0);
+}
+
+/* retarget the C library printf function to the USART */
+int fputc(int ch, FILE *f)
+{
+    usart_data_transmit(USART0, (uint8_t)ch);
+    while(RESET == usart_flag_get(USART0, USART_FLAG_TC));
+    return ch;
+}
+/*测试串口输出4G接收到的数据*/
+void data_dump(const char *name, uint8_t *data, uint16_t length)
+{
+    int index = 0;
+    if(g_bPrintDebug == 0) return;
+    printf("%s Data Info: \r\n    ", name);
+
+    for(index = 0;index < length;index++) {
+        if((index%4 == 0)&&index) {
+            if((index%16 == 0)&&index) {
+                printf("\r\n    ");
+            } else {
+                printf(" ");
+            }
+        }
+        printf("%02x ", *(data + index));
+    }
+    printf("\r\n");
+}
+
+void data_dump_00(const char *name, uint8_t *data, uint16_t length)
+{
+    int index = 0;
+    printf("%s Data Info: \r\n    ", name);
+
+    for(index = 0;index < length;index++) {
+        if((index%4 == 0)&&index) {
+            if((index%16 == 0)&&index) {
+                printf("\r\n    ");
+            } else {
+                printf(" ");
+            }
+        }
+        printf("%02x ", *(data + index));
+    }
+    printf("\r\n");
+}
+
+
+/*------------------------------------------485----------------------------------------*/
+void USART1_IRQHandler(void)
+{
+    volatile uint8_t len = 0;
+    if((RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)) \
+        && (RESET != usart_flag_get(USART1, USART_FLAG_IDLEF)))
+    {
+        usart_interrupt_flag_clear(USART1, USART_INT_FLAG_IDLE);//
+        usart_flag_clear(USART1, USART_FLAG_IDLEF);
+        dma_channel_disable(DMA0, DMA_CH5);
+        usart_data_receive(USART1);
+        len = USART3_RX_SIZE - dma_transfer_number_get(DMA0,DMA_CH5);
+        if(len>12)
+            fifo_write(&g_rxfifo,usart485RX_Buffer,len);
+        dma_memory_address_config(DMA0, DMA_CH5,(uint32_t)usart485RX_Buffer);
+        dma_transfer_number_config(DMA0, DMA_CH5, USART3_RX_SIZE);/* reset DMA_Channel CNT */
+        dma_channel_enable(DMA0, DMA_CH5);/* enable USART1_RX DMA_Channel */
+        g_uart485.bRcv = 1;
+
+    }
+    else if(RESET != usart_interrupt_flag_get(USART1,USART_INT_FLAG_TC)) { // 发送完成中断
+        usart_interrupt_flag_clear(USART1, USART_INT_FLAG_TC);//
+        usart_flag_clear(USART1, USART_FLAG_TC);
+        g_uart485.bSdFinish = 1;
+        gpio_bit_reset(GPIOA,  GPIO_PIN_4);
+    }
+}
+
+void DMA0_Channel6_IRQHandler(void)
+{
+    if(dma_interrupt_flag_get(DMA0, DMA_CH6, DMA_INT_FLAG_FTF)){
+        dma_interrupt_flag_clear(DMA0, DMA_CH6, DMA_INT_FLAG_G);
+        //g_uart485.bSdFinish = 1;
+        //gpio_bit_reset(GPIOC,  GPIO_PIN_12);
+        usart_interrupt_enable(USART1, USART_INT_TC); // 全能接收完成中断
+    }
+}
+
+
+
+
+uint8_t usart485TX_Buffer[USART3_TX_SIZE] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
+uint8_t usart485RX_Buffer[USART3_RX_SIZE] = {0};
+uart485Info_t g_uart485;
+
+void dam_init_uart_485(void)
+{
+    dma_parameter_struct dma_init_Usart1_TX;
+    dma_parameter_struct dma_init_Usart1_RX;
+
+    rcu_periph_clock_enable(RCU_DMA0);
+
+    dma_deinit(DMA0, DMA_CH5); // RX
+    dma_deinit(DMA0, DMA_CH6); // TX
+
+    /* initialize DMA0 channel4(USART1_TX) */
+    dma_init_Usart1_TX.direction = DMA_MEMORY_TO_PERIPHERAL;
+    dma_init_Usart1_TX.memory_addr = (uint32_t)usart485TX_Buffer;
+    dma_init_Usart1_TX.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
+    dma_init_Usart1_TX.memory_width = DMA_MEMORY_WIDTH_8BIT;
+    dma_init_Usart1_TX.number = (uint32_t)USART3_TX_SIZE;
+    dma_init_Usart1_TX.periph_addr = (uint32_t)(&USART_DATA(USART1));
+    dma_init_Usart1_TX.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
+    dma_init_Usart1_TX.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
+    dma_init_Usart1_TX.priority = DMA_PRIORITY_LOW;
+    dma_init(DMA0, DMA_CH6, &dma_init_Usart1_TX);
+    dma_circulation_disable(DMA0, DMA_CH6);
+
+    /* initialize DMA0 channel2(USART1_RX) */
+    dma_init_Usart1_RX.direction = DMA_PERIPHERAL_TO_MEMORY;
+    dma_init_Usart1_RX.memory_addr = (uint32_t)usart485RX_Buffer;
+    dma_init_Usart1_RX.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
+    dma_init_Usart1_RX.memory_width = DMA_MEMORY_WIDTH_8BIT;
+    dma_init_Usart1_RX.number = (uint32_t)USART3_RX_SIZE;
+    dma_init_Usart1_RX.periph_addr = (uint32_t)(&USART_DATA(USART1));
+    dma_init_Usart1_RX.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
+    dma_init_Usart1_RX.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
+    dma_init_Usart1_RX.priority = DMA_PRIORITY_LOW;
+    dma_init(DMA0, DMA_CH5, &dma_init_Usart1_RX);
+    dma_circulation_disable(DMA0, DMA_CH5);//circulate or not makes no difference
+
+    dma_memory_to_memory_disable(DMA0,DMA_CH5);
+    dma_memory_to_memory_disable(DMA0,DMA_CH6);
+
+    /* enable all DMA channels you need */
+    dma_channel_enable(DMA0,DMA_CH5);
+    dma_channel_disable(DMA0,DMA_CH6);
+}
+/*------------------------------------------------------------------------------------
+ *  485初始化 USART1
+ * -----------------------------------------------------------------------------------*/
+void usart_485_dma_init(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOA);/* enable GPIO clock */
+    rcu_periph_clock_enable(RCU_AF);
+
+    rcu_periph_clock_enable(RCU_USART1);/* enable USART clock */
+
+    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);/* connect port to USARTx_Tx */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);/* connect port to USARTx_Rx */
+
+    //设置rs485芯片,收发模式控制引脚 PA4,低电平接收,高电平发送,初始化为接收模式
+    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
+    gpio_bit_reset(GPIOA,  GPIO_PIN_4);
+
+
+    /* USART configure */
+    usart_deinit(USART1);
+    usart_word_length_set(USART1, USART_WL_8BIT);
+    usart_stop_bit_set(USART1, USART_STB_1BIT);
+    usart_parity_config(USART1, USART_PM_NONE);
+    usart_baudrate_set(USART1, 115200U);
+    usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
+    usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
+    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
+    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
+    usart_enable(USART1);
+
+    /* config USARTx_TX transmit by DMA */
+    usart_dma_transmit_config(USART1,USART_DENT_ENABLE);
+    usart_dma_receive_config(USART1,USART_DENR_ENABLE);
+
+    /* USART1 IRQ set */
+    nvic_irq_enable(USART1_IRQn, 4, 0);
+    usart_interrupt_enable(USART1, USART_INT_FLAG_IDLE);
+
+    dma_interrupt_enable(DMA0,DMA_CH6,DMA_INT_FTF); /* 使能DAM发送完成中断 */
+    dma_channel_enable(DMA0, DMA_CH6);
+    nvic_irq_enable(DMA0_Channel6_IRQn, 4, 1);
+    g_uart485.bSdFinish = 1;
+    g_rxfifo.flag = FALSE;
+    g_rxfifo.front = 0;
+    g_rxfifo.rear = 0;
+
+}
+
+void usart_tx_dma_send(uint32_t usart_periph,uint8_t* data_buffer,uint8_t length)
+{
+    volatile uint32_t i = 0;
+    if(usart_periph==USART1)
+    {
+        /* Channel disable */
+        gpio_bit_set(GPIOA,  GPIO_PIN_4);
+        dma_interrupt_flag_clear(DMA0, DMA_CH6, DMA_INT_FLAG_FTF);
+        usart_interrupt_flag_clear(USART1,USART_INT_FLAG_TC);
+        usart_flag_clear(USART1,USART_FLAG_TC);
+        for(i=0;i<0xFF;i++);
+//        if(dma_flag_get(DMA0,DMA_FLAG_FTF)!=RESET){
+
+//        }
+        dma_channel_disable(DMA0, DMA_CH6);
+        dma_memory_address_config(DMA0, DMA_CH6,(uint32_t)data_buffer);
+        dma_transfer_number_config(DMA0,DMA_CH6,length);
+        /* enable DMA channel to start send */
+        dma_channel_enable(DMA0, DMA_CH6);
+        usart_dma_transmit_config(USART1,USART_DENT_ENABLE);
+        g_uart485.bRcv = 0;
+        g_uart485.bSdFinish = 0;
+    }
+}

+ 32 - 0
Hardware/Uart.h

@@ -0,0 +1,32 @@
+#ifndef _UART_H_
+#define _UART_H_
+
+#include "gd32f10x.h"
+#include <stdio.h>
+#include <string.h>
+#include "timeout.h"
+
+
+extern uint8_t g_bPrintDebug;
+
+extern void usart0_config(void);
+extern void data_dump(const char *name, uint8_t *data, uint16_t length);
+extern void data_dump_00(const char *name, uint8_t *data, uint16_t length);
+
+
+#define USART3_TX_SIZE	256
+#define USART3_RX_SIZE	256
+extern uint8_t usart485TX_Buffer[USART3_TX_SIZE];
+extern uint8_t usart485RX_Buffer[USART3_RX_SIZE];
+typedef struct _uart_485_info_{
+    uint8_t bSdFinish; //
+    uint8_t bRcv;
+    timeout_t time; // 发送的时候启动  收到数据时结束
+}__attribute__((packed))uart485Info_t;
+extern uart485Info_t g_uart485;
+
+extern void dam_init_uart_485(void);
+extern void usart_485_dma_init(void);
+
+extern void usart_tx_dma_send(uint32_t usart_periph,uint8_t* data_buffer,uint8_t length);
+#endif

+ 497 - 0
Hardware/boardinit.c

@@ -0,0 +1,497 @@
+#include "boardinit.h"
+#include "../App/public.h"
+#include  "../App/xspDataOpt.h"
+
+TestInitConut testcount;
+extiMsg_t g_extimsg; // 中断信息
+Identity g_iDentity; // 身份信息 主或从
+DevResetMsg g_devResetMsg;
+DevPtMsg g_devPtMsg;
+GunStatus01 g_gunSta;
+
+PortMsg g_portMsg[4] = {
+    {GPIOD,GPIO_PIN_5, GPIO_PIN_1, GPIO_PIN_3, GPIO_PIN_2},
+    {GPIOE,GPIO_PIN_5, GPIO_PIN_1, GPIO_PIN_3, GPIO_PIN_2},
+    {GPIOD,GPIO_PIN_13,GPIO_PIN_9, GPIO_PIN_11,GPIO_PIN_10},
+    {GPIOE,GPIO_PIN_14,GPIO_PIN_10,GPIO_PIN_12,GPIO_PIN_11},
+};
+/*  CS_D_0:PB15   CS_D_1:PB14  CS_D_2:PB13   CS_D_3:PB12
+*  CS_D_4:PE7    CS_D_5:PB1   CS_D_6:PB0    CS_D_7:PC5
+*  CS_D_8:PC4    CS_D_9:PA7   CS_D_10:PA6   CS_D_11:PA5
+*
+*  CS_U_0:PE1    CS_U_1:PE0   CS_U_2:PB9    CS_U_3:PB8
+*  CS_U_4:PB7    CS_U_5:PB6   CS_U_6:PB5    CS_U_7:PC11
+*  CS_U_8:PC10   CS_U_9:PA15  CS_U_10:PA12  CS_U_11:PA11
+*/
+CSPortMsg g_csPortMsg[24] = {
+    {GPIOB,GPIO_PIN_15},    //CS_D_00--PB15
+    {GPIOB,GPIO_PIN_14},    //CS_D_01--PB14
+    {GPIOB,GPIO_PIN_13},    //CS_D_02--PB13
+    {GPIOB,GPIO_PIN_12},    //CS_D_03--PB12
+    {GPIOE,GPIO_PIN_7},     //CS_D_04--PE7
+    {GPIOB,GPIO_PIN_1},     //CS_D_05--PB1
+    {GPIOB,GPIO_PIN_0},     //CS_D_06--PB0
+    {GPIOC,GPIO_PIN_5},     //CS_D_07--PC5
+    {GPIOC,GPIO_PIN_4},     //CS_D_08--PC4
+    {GPIOA,GPIO_PIN_7},     //CS_D_09--PA7
+    {GPIOA,GPIO_PIN_6},     //CS_D_10--PA6
+    {GPIOA,GPIO_PIN_5},     //CS_D_11--PA5
+    {GPIOE,GPIO_PIN_1},     //CS_U_00--PE1
+    {GPIOE,GPIO_PIN_0},     //CS_U_01--PE0
+    {GPIOB,GPIO_PIN_9},     //CS_U_02--PB9
+    {GPIOB,GPIO_PIN_8},     //CS_U_03--PB8
+    {GPIOB,GPIO_PIN_7},     //CS_U_04--PB7
+    {GPIOB,GPIO_PIN_6},     //CS_U_05--PB6
+    {GPIOB,GPIO_PIN_5},     //CS_U_06--PB5
+    {GPIOC,GPIO_PIN_12},    //CS_U_07--PC12
+    {GPIOC,GPIO_PIN_11},    //CS_U_08--PC11
+    {GPIOC,GPIO_PIN_10},    //CS_U_09--PC10
+    {GPIOA,GPIO_PIN_12},    //CS_U_10--PA12
+    {GPIOA,GPIO_PIN_11},    //CS_U_11--PA11
+
+};
+void exti_irq_fuction(void)
+{
+    volatile uint8_t status = 0;
+    volatile uint8_t i = 0,j=0,daUp,daDn;
+    volatile uint32_t count = 0;
+//    if(RESET == gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin)){ //
+//        if(testcount.btestStart==1){
+//            status = gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin);
+//            testcount.exittest[testcount.count].tick = gTimer_tickt;
+//            testcount.exittest[testcount.count].status = status;
+//            testcount.count++;
+//            if(testcount.count >=24) testcount.count = 0;
+//        }
+#if (NO_INIT_COLLECT)
+//        else {
+//            g_timeInfo.bExit = 1;
+//            g_timeInfo.exitTick = gTimer_tickt;
+ //       }
+#else
+        else {
+            g_timeInfo.bExit = 1;
+            g_timeInfo.bRead = 0;
+            //exti_interrupt_disable(g_extimsg.extiLine); // 关闭外部中断
+            for(count=0;count<0x7FFF;count++)
+
+            status = gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin);
+            if(status == RESET) { // COM端为电平时取数
+                set_all_cs_port_status(SET); // 所有的片选置高
+                for(j=0;j<20;j++);
+                for(i=0;i<CS_GROUP_NUM;i++){
+                    gpio_bit_reset(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_reset(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+                    for(j=0;j<20;j++);
+                    daDn = (gpio_input_port_get(GPIOE));//(status1)^ 因为是高电平取数据,所以要取反
+                    daUp = (gpio_input_port_get(GPIOD));// (status1)^
+
+                    g_timeInfo.srcDa[i] = (daDn>>8)&0xFF;
+                    g_timeInfo.srcDa[i+CS_GROUP_NUM] = daUp&0xFF;
+
+                    gpio_bit_set(g_csPortMsg[i].csPort,g_csPortMsg[i].csPin);
+                    gpio_bit_set(g_csPortMsg[i+12].csPort,g_csPortMsg[i+12].csPin);
+                    for(j=0;j<20;j++);
+                }
+            }
+            g_timeInfo.bExit = 0;
+            g_timeInfo.bRead = 1;
+        }
+#endif
+//    }
+//    else if(SET == gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin)){
+//        if(testcount.btestStart==1){
+//            status = gpio_input_bit_get(g_extimsg.extiPort,g_extimsg.extiPin);
+//            testcount.exittest[testcount.count].tick = gTimer_tickt;
+//            testcount.exittest[testcount.count].status = status;
+//            testcount.count++;
+//            if(testcount.count >=24) testcount.count = 0;
+//        }
+
+
+
+//    }
+}
+
+void EXTI5_9_IRQHandler(void)
+{
+
+    volatile static uint8_t gunLevel = 0;
+
+//    if(RESET != exti_interrupt_flag_get(g_extimsg.extiLine)){ //
+//        exti_irq_fuction();
+//        //if(g_extimsg.extiLine != EXTI_8)
+//            exti_interrupt_flag_clear(g_extimsg.extiLine);
+//    }
+
+}
+
+void EXTI10_15_IRQHandler(void)
+{
+//    if(RESET != exti_interrupt_flag_get(g_extimsg.extiLine)){ //
+//        exti_irq_fuction();
+//        exti_interrupt_flag_clear(g_extimsg.extiLine);
+//    }
+}
+void EXTI0_IRQHandler(void)
+{
+//    if(RESET != exti_interrupt_flag_get(g_extimsg.extiLine)){ //
+//        exti_irq_fuction();
+//        exti_interrupt_flag_clear(g_extimsg.extiLine);
+//    }
+}
+void EXTI1_IRQHandler(void)
+{
+//    if(RESET != exti_interrupt_flag_get(g_extimsg.extiLine)){ //
+//        exti_irq_fuction();
+//        exti_interrupt_flag_clear(g_extimsg.extiLine);
+//    }
+}
+
+#if(0)
+void set_port_pin(uint8_t cmd,uint8_t index)
+{
+    switch(cmd){
+    case CEN:
+        gpio_bit_set(g_portMsg[index].group, g_portMsg[index].cePin);
+        break;
+    case CLK:
+        gpio_bit_set(g_portMsg[index].group, g_portMsg[index].cpPin);
+        break;
+    case PLN:
+        gpio_bit_set(g_portMsg[index].group, g_portMsg[index].plPin);
+        break;
+    }
+}
+void set_port_all_pin(uint8_t cmd,uint8_t index)//0x01 02 04 08
+{
+    uint8_t i=0;
+    for(i=0;i<4;i++){
+        if(0x00 ==((index>>i)&0x01)) continue;
+        set_port_pin(cmd,i);
+    }
+}
+void reset_port_pin(uint8_t cmd,uint8_t index)
+{
+    switch(cmd){
+    case CEN:
+        gpio_bit_reset(g_portMsg[index].group, g_portMsg[index].cePin);
+        break;
+    case CLK:
+        gpio_bit_reset(g_portMsg[index].group, g_portMsg[index].cpPin);
+        break;
+    case PLN:
+        gpio_bit_reset(g_portMsg[index].group, g_portMsg[index].plPin);
+        break;
+    }
+}
+
+void reset_port_all_pin(uint8_t cmd,uint8_t index)//0x01 02 04 08
+{
+    uint8_t i=0;
+    for(i=0;i<4;i++){
+        if(0x00 ==((index>>i)&0x01)) continue;
+        reset_port_pin(cmd,i);
+    }
+}
+
+uint8_t read_daout_pin(uint8_t index)
+{
+    uint8_t ret;
+    ret = gpio_input_bit_get(g_portMsg[index].group, g_portMsg[index].doutPin);
+
+    return ret;
+}
+#endif
+/*------------------------------------------------------------------
+ *  根据配置表,初始化片选 以及外部中断
+ *  Port1: CS0-PD0, CS6-PD6
+ *  Port2: AD0-PE0, AD6-PE6
+ *  Port3: CS15-PD8 CS9-PD14
+ *  Port4: AD9-PE9  AD15-PE15
+ * -----------------------------------------------------------------*/
+void exti_msg_init(void)
+{
+//    uint8_t port = 0;
+
+    epprom_read_com_config();
+
+//    exti_interrupt_flag_clear(g_extimsg.extiLine); /* 清除中断 */
+//    exti_interrupt_disable(g_extimsg.extiLine);
+    /*----start  cs--cs_u_1--PE0  exit--ad_u_5--PD5------*/
+    /*g_extimsg.csGroup = GPIOB;
+    g_extimsg.csPin   = GPIO_PIN_9;
+    g_extimsg.extiPin  = GPIO_PIN_6;
+    g_extimsg.extiPort  = GPIOD;
+    g_extimsg.extiIRQn = EXTI5_9_IRQn;
+    g_extimsg.extiLine = EXTI_6;
+    g_extimsg.extiPinSource = GPIO_PIN_SOURCE_6;
+    g_extimsg.outputPort = GPIO_PORT_SOURCE_GPIOD;*///3;
+    /*------------------end start---------------*/
+    return;
+//    switch (port){
+//    case 0: // CS6
+//        g_extimsg.csGroup = GPIOD;
+//        g_extimsg.csPin   = GPIO_PIN_6;
+//        g_extimsg.extiIRQn = EXTI5_9_IRQn;
+//        g_extimsg.extiLine = EXTI_6;
+//        g_extimsg.extiPinSource = GPIO_PIN_SOURCE_6;
+//        g_extimsg.extiPin  = GPIO_PIN_6;
+//        g_extimsg.outputPort = 3;
+//        break;
+//    case 1:
+
+//        break;
+//    case 2: // AD6
+//        g_extimsg.csGroup = GPIOE;
+//        g_extimsg.csPin   = GPIO_PIN_6;
+//        g_extimsg.extiIRQn = EXTI5_9_IRQn;
+//        g_extimsg.extiLine = EXTI_6;
+//        g_extimsg.extiPinSource = GPIO_PIN_SOURCE_6;
+//        g_extimsg.extiPin  = GPIO_PIN_6;
+//        g_extimsg.outputPort = 4;
+//        break;
+//    case 3: // CS15--PD8
+//        g_extimsg.csGroup = GPIOD;
+//        g_extimsg.csPin   = GPIO_PIN_8;
+//        g_extimsg.extiIRQn = EXTI5_9_IRQn;
+//        g_extimsg.extiLine = EXTI_8;
+//        g_extimsg.extiPinSource = GPIO_PIN_SOURCE_8;
+//        g_extimsg.extiPin  = GPIO_PIN_8;
+//        g_extimsg.outputPort = 3;
+//        break;
+//    default:
+
+//        break;
+//    }
+}
+
+/*-----------------------------------------------------------------
+ *  初始化GPIO管脚
+ * 版选模式:
+ *  CS_ALL : PE2
+ *  CS片选,设置为输出:
+ *  CS_D_0:PB15   CS_D_1:PB14  CS_D_2:PB13   CS_D_3:PB12
+ *  CS_D_4:PE7    CS_D_5:PB1   CS_D_6:PB0    CS_D_7:PC5
+ *  CS_D_8:PC4    CS_D_9:PA7   CS_D_10:PA6   CS_D_11:PA5
+ *
+ *  CS_U_0:PE1    CS_U_1:PE0   CS_U_2:PB9    CS_U_3:PB8
+ *  CS_U_4:PB7    CS_U_5:PB6   CS_U_6:PB5    CS_U_7:PC12
+ *  CS_U_8:PC11   CS_U_9:PC10  CS_U_10:PA12  CS_U_11:PA11
+ *
+ *  DATA信号,设置为输入:PE8~PE15(0xFF00):AD_D0~AD_D7; PD0~PD7(0x00FF):AD_U0~AD_U7
+ *  PE8:设置为外部中断, 上升沿下降沿中断 ,在片选CS8(PD15)上
+ * 串转并模式:
+ *  PD0 PD1 PD6 PD8 PD9 PD14 设置为输入 (PD1 PD9为DOUT,其它为COM端) 0x4343
+ *  PE0 PE1 PE6 PE9 PE10 PE15 设置为输入 (PE1 PE10为DOUT,其它为COM端)0x8643
+ *  其它的PE、PD端口都设置为输出 PD:0xBCBC PE:0x79BC
+ * ----------------------------------------------------------------*/
+void exti_gpio_init(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOE);
+    gpio_init(GPIOE, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ,0xFF00);// PE8~PE15设置为输入
+    gpio_bit_set(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7);// PE0/PE1/PE7 设置为输出
+    gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7);
+
+    gpio_bit_reset(GPIOE, GPIO_PIN_2);// CS_ALL
+    gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_2);
+
+    rcu_periph_clock_enable(RCU_GPIOD);//
+    gpio_init(GPIOD, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ,0x00FF);// PD0~PD7设置为输入
+
+    gpio_bit_reset(GPIOD, GPIO_PIN_9);// PD9 设置为输出 CS_ALL
+    gpio_init(GPIOD, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_9);
+
+    rcu_periph_clock_enable(RCU_GPIOC);// PC设置为输出 PC4/PC5/PC10/PC11/PC12
+    gpio_bit_set(GPIOC, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);
+    gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);
+
+
+    rcu_periph_clock_enable(RCU_GPIOB);// PB设置为输出 PB0~PB1/PB5~PB9/PB12~PB15
+    gpio_bit_set(GPIOB, 0xF3E3);
+    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,0xF3E3);
+
+    //rcu_periph_clock_enable(RCU_AF); // 必须要用这句,才能使用下面的remap;
+    rcu_periph_clock_enable(RCU_GPIOA);// PA设置为输出 PA5~PA7/PA11~PA12
+    //gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP,ENABLE); // 将PA15做为普通IO口,PA13 PA14为SWD
+    gpio_bit_set(GPIOA, 0x18E0);
+    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,0x18E0);
+
+    rcu_periph_clock_enable(RCU_AF); /* AFIO时钟使能 */
+
+//    for(i=0;i<4;i++){
+//        printf("csport = %d, cspin= %d,extipt = %d, extipin=%d\r\n",g_extimsg.csGroup[i],\
+//        g_extimsg.csPin[i],g_extimsg.extiPort[i],g_extimsg.extiPin[i]);
+//    }
+    //exti_deinit();
+    /* enable and set key EXTI interrupt priority */
+    //nvic_irq_enable(g_extimsg.extiIRQn, 2U, 0U); /* 设置优先级 */
+    /* connect key EXTI line to key GPIO pin */
+    //gpio_exti_source_select(g_extimsg.outputPort,g_extimsg.extiPinSource); /* 设置EXTI的触发源 */
+
+    //exti_init(g_extimsg.extiLine, EXTI_INTERRUPT, EXTI_TRIG_BOTH); /*触发方式:上升沿 下降沿触发*/
+    //exti_interrupt_flag_clear(g_extimsg.extiLine); /* 清除中断 */
+   // exti_interrupt_enable(g_extimsg.extiLine);
+#if (0) //SEL_74CH165
+
+    rcu_periph_clock_enable(RCU_GPIOD);// PD
+    rcu_periph_clock_enable(RCU_GPIOE); // PE
+
+    gpio_bit_set(GPIOD, 0xBCBC);
+    gpio_init(GPIOD, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,0xBCBC); // 设置输出
+
+    gpio_bit_set(GPIOE, 0x79BC);
+    gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,0x79BC); // PE 设置输出
+
+    gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ,0x4343);
+    gpio_init(GPIOE, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ,0x8643);
+    rcu_periph_clock_enable(RCU_AF); /* AFIO时钟使能 */
+
+    nvic_irq_enable(g_extimsg.extiIRQn, 2U, 0U); /* 设置优先级 */
+    /* connect key EXTI line to key GPIO pin */
+
+    gpio_exti_source_select(g_extimsg.outputPort,g_extimsg.extiPinSource); /* 设置EXTI的触发源 */
+    exti_deinit();
+    exti_init(g_extimsg.extiLine, EXTI_INTERRUPT, EXTI_TRIG_FALLING); /*触发方式:上升沿 下降沿触发*/
+    exti_interrupt_flag_clear(g_extimsg.extiLine); /* 清除中断 */
+    exti_interrupt_enable(g_extimsg.extiLine);
+#endif
+}
+/*------------------------------------------------------------------
+ *  所有的片选置高或是低
+ * ------------------------------------------------------------------*/
+void set_all_cs_port_status(FlagStatus status)
+{
+    uint8_t i = 0;
+    CSPortMsg *csMsg = NULL;
+    if(status == SET){
+        for(i=0;i<CS_GROUP_NUM;i++){
+            csMsg = &g_csPortMsg[i];
+            gpio_bit_set(csMsg->csPort,csMsg->csPin);
+            csMsg = &g_csPortMsg[i+12];
+            gpio_bit_set(csMsg->csPort,csMsg->csPin);
+        }
+    }
+    else {
+        for(i=0;i<CS_GROUP_NUM;i++){
+            csMsg = &g_csPortMsg[i];
+            gpio_bit_reset(csMsg->csPort,csMsg->csPin);
+            csMsg = &g_csPortMsg[i+12];
+            gpio_bit_reset(csMsg->csPort,csMsg->csPin);
+        }
+    }
+}
+/*----------------------------------------------------------------
+ *  抬枪信号的初始化
+ *  PC8
+ * ----------------------------------------------------------------*/
+void gun_single_init(void)
+{
+    //初始化抬枪信号
+    rcu_periph_clock_enable(RCU_GPIOC);
+
+    gpio_init(TQ_PORT, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,TQ_PIN); //PC8 IN1 抬枪信号1
+    rcu_periph_clock_enable(RCU_AF); /* AFIO时钟使能 */
+
+    nvic_irq_enable(EXTI5_9_IRQn, 3U, 2U); /* 设置优先级 */
+    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOC,GPIO_PIN_SOURCE_8); /* 设置EXTI的触发源 */
+    exti_init(EXTI_8, EXTI_INTERRUPT, EXTI_TRIG_BOTH); /*触发方式:上升沿 下降沿触发*/
+    exti_interrupt_flag_clear(EXTI_8); /* 清除中断 */
+    exti_interrupt_enable(EXTI_8);
+}
+
+/*----------------------------------------------------------------
+ *  初始化板级控制管脚
+ *  PD14 : led_green  PD15:leg_red
+ *  PE2: cs_en_all 所有片选使能
+ * ---------------------------------------------------------------*/
+void board_gpio_init(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOC);
+    rcu_periph_clock_enable(RCU_GPIOD);
+    rcu_periph_clock_enable(RCU_GPIOE);
+
+    gpio_bit_set(GPIOD, GPIO_PIN_15|GPIO_PIN_14);
+    gpio_init(GPIOD, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_14|GPIO_PIN_15); //初始化LED管脚 PC13
+
+    gpio_bit_reset(GPIOE, GPIO_PIN_2);
+    gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_2); //cs_all 使能
+
+
+    // 初始化抬枪信号
+    gpio_init(TQ_PORT, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,TQ_PIN); //PC8 IN1 抬枪信号1
+    gpio_init(BM_PORT, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,BM_PIN); //PC9 编码器
+
+
+
+}
+void init_fwdgt_timer(void)
+{
+//    fwdgt_counter_reload();
+}
+
+void fwdgt_feed(uint32_t tickt)
+{
+    if((tickt%2000)==0)
+    fwdgt_counter_reload();
+
+}
+
+void board_init(void)
+{
+    board_gpio_init();
+    i2c_init();
+    rct_init();
+    init_flash();
+
+    usart0_config();
+
+    exti_msg_init();
+    exti_gpio_init();
+    init_gun_status();
+    timer4_init();
+    timer5_init();
+    key_init();
+
+
+    g_iDentity = IDENTITY_SLAVE; // 从
+    g_devMsg.bHave4G = B4G_NOHAVE; // 无4G模块
+
+}
+/*--------------------------------------------------------------------------------
+ *  上电时读取复位类型
+ * -------------------------------------------------------------------------------*/
+uint32_t power_up_system_resettype(void)
+{
+    uint32_t RestFlag = 0;
+    if(RESET != rcu_flag_get(RCU_FLAG_EPRST)){ // 复位引脚复位 external PIN reset flag
+        RestFlag |= RESET_PINRST;
+    }
+    if(RESET != rcu_flag_get(RCU_FLAG_PORRST)){ // 掉电复位 : power reset flag
+        RestFlag |= RESET_PORRSTF;
+    }
+    if(RESET != rcu_flag_get(RCU_FLAG_SWRST)) { // 软件复位 : software reset flag
+        RestFlag |= RESET_SFTRSTF;
+    }
+    if(RESET != rcu_flag_get(RCU_FLAG_FWDGTRST)){// 独立看门狗复位 : free watchdog timer reset flag
+         RestFlag |= RESET_IWDGRSTF;//
+    }
+    if(RESET != rcu_flag_get(RCU_FLAG_WWDGTRST)) { //窗口看门狗复位 : window watchdog timer reset flag
+        RestFlag |= RESET_IWDGRSTF;//
+    }
+    if(RESET != rcu_flag_get(RCU_FLAG_LPRST)){     // 低功耗复位: low-power reset flag
+        RestFlag |= RESET_LPWRRSTF;//
+    }
+    rcu_all_reset_flag_clear();
+
+    printf("复位类型 : %x\r\n",RestFlag);
+    //存储复位 类型
+    return RestFlag;
+}
+
+
+void uart_init(void)
+{
+    dam_init_uart_485();
+    usart_485_dma_init();
+}

+ 153 - 0
Hardware/boardinit.h

@@ -0,0 +1,153 @@
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+
+#include "Uart.h"
+#include "Timer.h"
+#include "flash.h"
+#include "fifo.h"
+#include "timeout.h"
+#include "I2C.h"
+#include "epprom.h"
+#include "rtc.h"
+#include "key.h"
+
+
+#define TQ_PORT GPIOC  // 抬枪信号端口
+#define TQ_PIN  GPIO_PIN_8 // 抬枪信号管脚
+#define BM_PORT GPIOC  // 编码器信号端口
+#define BM_PIN  GPIO_PIN_9 // 编码器信号管脚
+
+#define LED_GREEN_SET()  gpio_bit_set(GPIOD, GPIO_PIN_14)    //
+#define LED_GREEN_RESET()  gpio_bit_reset(GPIOD, GPIO_PIN_14)
+#define LED_RED_SET()    gpio_bit_set(GPIOD, GPIO_PIN_15)   //
+#define LED_RED_RESET()    gpio_bit_reset(GPIOD, GPIO_PIN_15)
+
+
+#define PORT_MAX_NUM 64
+#define SEL_74CH165 0
+#define USE_PORT_ID 0
+enum {
+    CEN = 0x01,
+    CLK = 0x02,
+    PLN = 0x03,
+};
+enum {
+    PORT_00 = 0x01,
+    PORT_01 = 0x02,
+    PORT_02 = 0x04,
+    PORT_03 = 0x08,
+    PORT_ALL = 0x0F,
+};
+typedef struct port_msg_{
+    uint32_t group;
+    uint32_t cePin;
+    uint32_t doutPin;
+    uint32_t cpPin;
+    uint32_t plPin;
+}PortMsg;
+extern PortMsg g_portMsg[4];
+
+typedef struct cs_port_msg_{
+    uint32_t csPort;
+    uint32_t csPin;
+}CSPortMsg;
+#define CS_GROUP_NUM 12  // CS片选组数 上面12组,下面12组,共24组
+extern CSPortMsg g_csPortMsg[24];
+enum _RESET_FLAG_{
+    RESET_PINRST = 0x01, // NRST 引脚复位
+    RESET_PORRSTF = 0x02, // 上电掉电复位
+    RESET_SFTRSTF = 0x04, // 软件复位
+    RESET_IWDGRSTF = 0x08, //独立看门狗复位
+    RESET_WWDGRSTF = 0x10, // 窗口看门狗复位
+    RESET_LPWRRSTF    = 0x20, // 低功耗复位
+};
+
+typedef struct {
+    uint32_t tick;
+    uint8_t status;
+}ExitTest;
+typedef struct {
+    ExitTest exittest[25];
+    uint32_t count;
+    uint8_t btestStart;
+    uint32_t width[22]; //
+    uint8_t wCount; //
+}TestInitConut;
+extern TestInitConut testcount;
+
+typedef struct gun_status{
+    uint8_t bGunUp; // 抬枪
+    uint8_t bGunDn; // 挂枪
+    uint8_t bgun; //
+    timeout_t guntime; // 时间
+    timeout_t taigunTime; // 抬枪时间
+}__attribute__((packed))GunStatus01;
+extern GunStatus01 g_gunSta;
+typedef struct gpio_exti_{
+    uint8_t groupNum; // 现在的组数
+    uint32_t csGroup[4];          // 片选组GPIOD GPIOC GPIOB
+    uint32_t csPin[4];            // 具体的管脚
+    //exti_line_enum extiLine;   // 中断标志脚 comm
+    //uint32_t extiPort;         // 中断端口
+    //uint32_t extiPin;          // 中断管脚 comm
+    //uint8_t extiPinSource;     //
+    //uint8_t extiIRQn;          // 中断源
+   // uint8_t outputPort;
+    uint8_t comPort[4];
+    uint8_t comPin[4];
+}__attribute__((packed))extiMsg_t;
+extern extiMsg_t g_extimsg; // 中断信息
+
+
+typedef enum {
+    IDENTITY_SLAVE  = 0x01, // 从设备
+    IDENTITY_MASTER = 0x02, // 主设备
+}Identity;
+extern Identity g_iDentity; // 身份信息 主或从
+
+typedef struct _dev_reset_msg_{
+    uint8_t resetflag;
+    uint32_t resetNum;
+}__attribute__((packed))DevResetMsg;
+extern DevResetMsg g_devResetMsg;
+typedef struct _dev_pt_msg_{
+    uint16_t firstPowerUp;      // 是否为第一次上电 0x5A5A 说明已经上过电
+    uint8_t  eepromVer;         // eeprom 的版本
+    uint8_t  binit;             // 是否初始化
+    uint32_t devSn;             // 设备SN
+    uint16_t devType1;          // 设备类型
+    uint16_t  devfactory;        // 设备厂家信息
+    uint16_t seqNo ; // 生产批次号
+    uint32_t data; // 生产日期
+    uint8_t pcbVersion; // 硬件(PCB)版本
+    uint32_t sqare; //备用
+}__attribute__((packed))DevPtMsg;
+extern DevPtMsg g_devPtMsg;
+typedef struct _dev_app_version_{
+    uint32_t bootVer;
+    uint32_t ptVer;
+    uint32_t app1Ver;
+    uint32_t app2Ver;
+    uint32_t app3Ver;
+}__attribute__((packed))DevAppVersion;
+extern DevAppVersion g_devAppVer;
+extern void set_port_pin(uint8_t cmd,uint8_t index);
+extern void set_port_all_pin(uint8_t cmd,uint8_t index);
+extern void reset_port_pin(uint8_t cmd,uint8_t index);
+extern void reset_port_all_pin(uint8_t cmd,uint8_t index);//0x01 02 04 08
+extern uint8_t read_daout_pin(uint8_t index);
+
+extern void set_all_cs_port_status(FlagStatus status);
+extern void exti_gpio_init(void);
+
+
+extern void init_fwdgt_timer(void);
+extern void fwdgt_feed(uint32_t tickt);
+
+extern void board_init(void);
+extern void uart_init(void);
+extern uint32_t power_up_system_resettype(void);
+
+extern void gun_single_init(void);
+#endif

+ 156 - 0
Hardware/epprom.c

@@ -0,0 +1,156 @@
+/*--------------------------------------------------
+ *  用的芯片是AT24C128
+ *  一共256页,每页64个字节
+ * -------------------------------------------------*/
+#include "epprom.h"
+#include "I2C.h"
+#include "timeout.h"
+/*--------------------------------------------------------
+ * 在AT24CXX里面的指定地址开始读出指定个数的数据
+ * ReadAddr :开始读出的地址 对24c02为0~255
+ *pBuffer  :数据数组首地址
+ *NumToRead:要读出数据的个数
+ * --------------------------------------------------------*/
+void epprom_read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
+{
+    uint8_t addrH,addrL;
+    uint16_t lentmp,lentow,lens;
+    uint8_t tmp;
+
+    if(NumToRead==0) return;
+
+   // i2c_init();
+    __set_PRIMASK(1);//关总中断
+    delay_ms(100);//两次写操作,必须加间隔,否则写不进去
+    //fwdgt_feed();
+
+    lentmp=NumToRead;
+    while(lentmp)
+    {
+        tmp=ReadAddr%PAGE_SIZE_EPPROM;
+        tmp=PAGE_SIZE_EPPROM-tmp;
+        if(tmp>=lentmp)//当页剩余空间大于要写入的长度
+        {
+            lentow=lentmp;
+        }
+        else
+        {
+            lentow=tmp;//写入长度只能是剩余空间长度
+        }
+        lentmp=lentmp-lentow;//计算要在下一页写入的长度
+        lens=lentow;
+        addrH=ReadAddr>>8;
+        addrL=ReadAddr&0xff;
+
+        i2c_start();
+        i2c_send_byte(0xa0);//写
+        i2c_wait_ack();
+        i2c_send_byte(addrH);   //发送高地址
+        i2c_wait_ack();
+        i2c_send_byte(addrL);   //发送低地址
+        i2c_wait_ack();
+
+        delay_us(4);
+        i2c_start();
+        i2c_send_byte(0xa1);  //读       //进入接收模式
+        i2c_wait_ack();
+
+        while(lentow)
+        {
+            *pBuffer=i2c_read_byte(1);
+            pBuffer++;
+            //ReadAddr++;
+            lentow--;
+        }
+        i2c_read_byte(0);
+        i2c_stop();//产生一个停止条件
+
+        delay_us(4);
+        //printf("at24 read %d %d\r\n", ReadAddr, lens);
+        ReadAddr=ReadAddr+lens;//下一页的地址
+    }
+    //IIC_WRITE_PROTECT_ON(); // 写保护打开
+     __set_PRIMASK(0);//开总中断
+
+}
+/*---------------------------------------------------------
+ * 在AT24CXX里面的指定地址开始写入指定个数的数据
+ * WriteAddr :开始写入的地址 对24c02为0~255
+ * pBuffer   :数据数组首地址
+ * NumToWrite:要写入数据的个数
+ * 每64bytes为一个page,
+ * --------------------------------------------------------*/
+void epprom_write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
+{
+    uint8_t addrH,addrL;
+    uint16_t lentmp,lentow,lens;
+    uint8_t tmp;
+//    rt_err_t err;
+
+    if(NumToWrite==0) return;
+ //   i2c_init();
+    IIC_WRITE_PROTECT_OFF(); // 写保护关闭
+    __set_PRIMASK(1);//关总中断
+    delay_ms(10);//两次写操作,必须加间隔,否则写不进去
+    //fwdgt_feed();
+
+    lentmp=NumToWrite;
+    while(lentmp)
+    {
+        tmp=WriteAddr%PAGE_SIZE_EPPROM;
+        tmp=PAGE_SIZE_EPPROM-tmp;
+        if(tmp>=lentmp)//当页剩余空间大于要写入的长度
+        {
+            lentow=lentmp;
+        }
+        else
+        {
+            lentow=tmp;//写入长度只能是剩余空间长度
+        }
+        lentmp=lentmp-lentow;//计算要在下一页写入的长度
+        lens=lentow;
+
+        addrH=WriteAddr>>8;
+        addrL=WriteAddr&0xff;
+
+        i2c_start();
+
+        i2c_send_byte(0xa0);
+
+        i2c_wait_ack();
+        i2c_send_byte(addrH);   //发送高地址
+        i2c_wait_ack();
+        i2c_send_byte(addrL);   //发送低地址
+        i2c_wait_ack();
+
+        while(lentow--)
+        {
+            i2c_send_byte(*pBuffer);
+            i2c_wait_ack();
+            pBuffer++;
+        }
+        i2c_stop();//产生一个停止条件
+        delay_ms(10);
+        WriteAddr=WriteAddr+lens;//下一页的地址
+    }
+
+
+    delay_ms(10);//两次写操作,必须加间隔,否则写不进去
+    IIC_WRITE_PROTECT_ON(); // 写保护使能打开
+    __set_PRIMASK(0);//开总中断
+
+}
+void epprom_test(void)
+{
+    uint8_t i = 0,vale=0;
+    for(i=1;i<128;i++){
+        epprom_write(640+i,&i,1);
+    }
+    for(i=1;i<128;i++){
+        vale = 0;
+        epprom_read(640+i,&vale,1);
+        printf("i = %d,val = %d\r\n",i,vale);
+    }
+}
+
+

+ 20 - 0
Hardware/epprom.h

@@ -0,0 +1,20 @@
+#ifndef _EPPROM_H_
+#define _EPPROM_H_
+
+#include "../User/gd32f10x_it.h"
+#include <stdio.h>
+
+#define PAGE_SIZE_EPPROM	64
+
+#define DEV_APP_VER (4*64) // 1页
+#define DEV_READ_MQTT_MSG (19*64) // mqtt信息
+#define DEV_RESET_NUM (5*64) // 1 页
+#define CONFIGTABLE_ADDR (25*64) // 配置路由表的首地址,3页
+#define COMM_CONFIG_ADDR (28*64) // com端的配置文件  2页
+#define PIN_CONFIG_ADDR  (30*64) // 针脚的配置文件   10页
+
+extern void epprom_read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead);
+extern void epprom_write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite);
+
+extern void epprom_test(void);
+#endif

+ 84 - 0
Hardware/fifo.c

@@ -0,0 +1,84 @@
+#include "fifo.h"
+#include "Uart.h"
+
+FIFO_T g_rxfifo;
+FIFO_T g_txfifo;
+/*-----------------------------------------------------------------
+ *  初始化fifo
+ * ----------------------------------------------------------------*/
+void init_fifo(FIFO_T *fifo)
+{
+    uint8_t i = 0;
+    for(i=0;i<8;i++){
+        memset(fifo->memory[i].da,0,256);
+        fifo->memory[i].len = 0;
+    }
+    fifo->flag = FALSE;
+    fifo->front = fifo->rear = 0;
+    printf("循环队列已经创建完毕\n");
+    return ;
+}
+/*-----------------------------------------------------------------
+ *  判断fifo是否已满
+ *  满返回1 否则返回0
+ * -----------------------------------------------------------------*/
+bool fifo_is_full(FIFO_T *fifo)
+{
+    if ((fifo->front == fifo->rear) && fifo->flag)
+    {
+        printf("循环队列已满!-fifo\n");
+        return TRUE;
+    }
+    return FALSE;
+}
+/*------------------------------------------------------------------
+ * 判断fio是否已空
+ *  空返回 1: 否则返回0
+ * -----------------------------------------------------------------*/
+bool fifo_is_empty(FIFO_T *fifo)
+{
+    if ((fifo->front == fifo->rear) && !(fifo->flag))  // 判断队空 flag 为false
+        return TRUE;
+    return FALSE;
+}
+/*------------------------------------------------------------------
+ *  写入数据到fifo
+ *  1:写入 0: 操作失败
+ * -----------------------------------------------------------------*/
+uint8_t fifo_write(FIFO_T *fifo,uint8_t *data,uint8_t len)
+{
+    if ((fifo->front == fifo->rear) && fifo->flag)
+    {
+      //  printf("循环队列已满!-write front=%d,flag = %d\n",fifo->front,fifo->flag);
+        return 0;
+    }
+
+    memcpy(fifo->memory[fifo->rear].da,data,len);
+    fifo->memory[fifo->rear].len = len;
+    ++(fifo->rear);
+    fifo->rear %= MAXSIZE;
+    if (fifo->rear == fifo->front) // 设置队列已满
+        fifo->flag = TRUE;
+    return 1;
+}
+/*------------------------------------------------------------------
+ *  从fifo中读取数据
+ * -----------------------------------------------------------------*/
+uint8_t fifo_read(FIFO_T *fifo,uint8_t *data)
+{
+    uint8_t len;
+    if ((fifo->front == fifo->rear) && !(fifo->flag))  // 判断队空
+    {
+        printf("队列为空!不能进行删除操作\n");
+        return 0;
+    }
+    len = fifo->memory[fifo->front].len;
+    memcpy(data,fifo->memory[fifo->front].da,len);
+    //memset(fifo->memory[fifo->front].da,0,256);
+    fifo->memory[fifo->front].len = 0;
+    fifo->front++;
+    fifo->front %= MAXSIZE;
+    if (fifo->front == fifo->rear) // 设置队列为空
+        fifo->flag = FALSE;
+    return len;
+}

+ 27 - 0
Hardware/fifo.h

@@ -0,0 +1,27 @@
+#ifndef _FIFO_H_
+#define _FIFO_H_
+
+#include "../User/gd32f10x_it.h"
+
+#define MAXSIZE 8
+typedef struct _fifo_data_{
+    uint8_t da[256];
+    uint8_t len;
+}__attribute__((packed))fifoDa;
+
+typedef struct _fifo_{
+    fifoDa memory[8];
+    uint8_t front;
+    uint8_t rear;
+    bool flag;
+}__attribute__((packed)) FIFO_T;
+extern FIFO_T g_rxfifo;
+extern FIFO_T g_txfifo;
+
+
+extern void init_fifo(FIFO_T *fifo);
+extern bool fifo_is_full(FIFO_T *fifo);
+extern bool fifo_is_empty(FIFO_T *fifo);
+extern uint8_t fifo_write(FIFO_T *fifo,uint8_t *data,uint8_t len);
+extern uint8_t fifo_read(FIFO_T *fifo,uint8_t *data);
+#endif

+ 205 - 0
Hardware/flash.c

@@ -0,0 +1,205 @@
+#include "Flash.h"
+#include "Uart.h"
+
+/********************************
+  * @brief  OTA参数初始化
+  * @retval FLASH_COMPLETE初始成功
+  ********************************/
+uint8_t Flash_RangeErase(uint32_t FlashAddress, uint32_t Size)
+{
+    uint8_t flag = 1;
+    uint32_t msize=0;
+    fmc_state_enum FlashStatus = FMC_READY;
+
+    while(Size > msize) {
+        fmc_unlock();/* 解锁flash */
+        fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+        FlashStatus = fmc_page_erase(FlashAddress+msize);//擦除指定的页,参数页地址
+        fmc_lock();/* flash加锁,禁止编程 */
+
+        /* If erase operation was failed, a Flash error code is returned */
+        if (FlashStatus != FMC_READY) {
+                flag = 0;
+                break;
+        }
+        msize += FLASH_PAGE_SIZE;
+    }
+
+    return flag;
+}
+
+uint8_t Flash_PageErase(uint8_t _PageNumber)
+{
+    uint8_t flag = 0;
+
+    if(_PageNumber > 127)
+            return 0;
+
+    fmc_unlock();/* 解锁flash */
+    fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+
+    if(	fmc_page_erase(FLASH_USER_START_ADDR + (FLASH_PAGE_SIZE * _PageNumber)) == FMC_READY	)
+    {
+        flag = 1;
+    }
+    fmc_lock();/* flash加锁,禁止编程 */ // Lock the Flash to disable the flash control register access
+
+    return flag;
+}
+
+uint8_t Flash_BufferWrite(uint32_t address, uint32_t *p_buffer, uint32_t len)
+{
+    uint8_t  flag = 1;
+    uint32_t EndAddr = 0;
+    //uint32_t *p_buffer = (uint32_t *)buffer;
+
+    if(address%4||len%4) {
+        return 0;
+    }
+    fmc_unlock();/* 解锁flash */
+    fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+    EndAddr = address + len;
+
+    while (address < EndAddr) {
+        if (fmc_word_program(address, *p_buffer) == FMC_READY) {
+            p_buffer++;
+            address += 4;
+        } else {
+            flag = 0;// Error occurred while writing data in Flash memory.
+            break;
+        }
+    }
+
+    fmc_lock();/* flash加锁,禁止编程 */
+    return flag;
+}
+uint8_t Flash_BufferWrite_uint16(uint32_t address, uint16_t *p_buffer, uint32_t len)
+{
+    uint8_t  flag = 1;
+    uint32_t EndAddr = 0;
+
+    fmc_unlock();/* 解锁flash */
+    fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+    EndAddr = address + len;
+
+    while (address < EndAddr) {
+        if (fmc_halfword_program(address, *p_buffer) == FMC_READY) {
+            p_buffer++;
+            address += 2;
+        } else {
+            flag = 0;// Error occurred while writing data in Flash memory.
+            break;
+        }
+    }
+
+    fmc_lock();/* flash加锁,禁止编程 */
+    return flag;
+}
+
+void Flash_BufferRead(uint32_t address, uint8_t *buffer, uint32_t len)
+{
+    uint32_t EndAddr = 0;
+    uint8_t *p_buffer = (uint8_t *)buffer;
+
+//    if(address%4||len%4) {
+//        return ;
+//    }
+    fmc_unlock();/* 解锁flash */
+    fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+    EndAddr = address + len;
+
+    while (address < EndAddr) {
+        *p_buffer++ = *(__IO uint8_t *)address;
+        address += 1;
+    }
+
+    fmc_lock();/* flash加锁,禁止编程 */
+}
+void Flash_BufferRead_btye4(uint32_t address, uint8_t *buffer, uint32_t len)
+{
+        uint32_t EndAddr = 0;
+        uint32_t *p_buffer = (uint32_t *)buffer;
+
+        if(address%4||len%4) {
+                return ;
+        }
+        fmc_unlock();/* 解锁flash */
+        fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+        EndAddr = address + len;
+
+        while (address < EndAddr) {
+                *p_buffer++ = *(__IO uint32_t *)address;
+                address += 4;
+        }
+
+        fmc_lock();/* flash加锁,禁止编程 */
+}
+
+//读取flash中有效数据的长度
+uint32_t Flash_DatalenRead(uint32_t address,uint32_t len)
+{
+    uint32_t BeginAddr = 0;
+    uint32_t addrlen = 0;
+    uint32_t data;
+    if(address%4||len%4) {
+        return addrlen;
+    }
+
+    fmc_unlock();/* 解锁flash */
+    fmc_flag_clear(FMC_FLAG_BANK0_END);//清除操作结束标志
+    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清除擦除/错误标志
+    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);//清楚页编程错误标志
+
+    BeginAddr = address + len - 4;
+    while(address < BeginAddr)
+    {
+        data = *(__IO uint32_t *)BeginAddr;
+        if(data != 0xFFFFFFFF)
+                break;
+        BeginAddr -= 4;
+    }
+    fmc_lock();/* flash加锁,禁止编程 */
+
+    if(address <= BeginAddr)
+    {
+        addrlen = (BeginAddr+4) - address;
+    }
+    return addrlen;
+}
+void flash_test(void)
+{
+    uint8_t data[8] = {11,22,33,45,100,23,67,89};
+    uint8_t i = 0,outda[8] = {0};
+
+    printf("eraser flash one page  0x8018000\r\n");
+    Flash_RangeErase(0x8018000,2048);
+
+    printf("write flash 0x8018000\r\n");
+    Flash_BufferWrite(0x8018000,(uint32_t*)data,8);//正常的flash 写入
+
+    printf("read flash 0x8018000\r\n");
+    Flash_BufferRead(0x8018000,outda,8);//数据存入到outda中
+    for(i=0;i<8;i++){
+        printf("%d, ",outda[i]);
+    }
+    printf("\r\n");
+    Flash_RangeErase(0x8018000,2048);
+    printf("eraser flash and test finish\r\n");
+}

+ 25 - 0
Hardware/flash.h

@@ -0,0 +1,25 @@
+/*
+ * @Description: 
+ * @Version: 2.0
+ * @Author: Seven
+ * @Date: 2022-02-24 10:49:04
+ * @LastEditors: Seven
+ * @LastEditTime: 2022-02-24 17:23:19
+ */
+#ifndef _FLASH_H
+#define _FLASH_H
+
+#include "gd32f10x.h"
+
+#define  FLASH_PAGE_SIZE	     		((uint32_t)0x00000800)   /* FLASH Page Size */
+#define  FLASH_USER_START_ADDR			((uint32_t)0x08000000)   /* Start @ of user Flash area */
+
+extern uint8_t Flash_RangeErase(uint32_t FlashAddress, uint32_t Size);
+extern uint8_t Flash_PageErase(uint8_t _PageNumber);
+extern uint8_t Flash_BufferWrite(uint32_t address, uint32_t *p_buffer, uint32_t len);
+extern void Flash_BufferRead(uint32_t address, uint8_t *buffer, uint32_t len);
+extern uint32_t Flash_DatalenRead(uint32_t address,uint32_t len);
+extern uint8_t Flash_BufferWrite_uint16(uint32_t address, uint16_t *p_buffer, uint32_t len);
+extern void Flash_BufferRead_btye4(uint32_t address, uint8_t *buffer, uint32_t len);
+extern void flash_test(void);
+#endif

+ 96 - 0
Hardware/key.c

@@ -0,0 +1,96 @@
+#include "key.h"
+#include "../App/ota_update.h"
+#include "../App/xspDataOpt.h"
+#include "../App/taskOpt.h"
+KeyInfo g_keyinfo;
+
+void key_delay(uint32_t time)
+{
+    volatile uint32_t idly=0;
+    for(idly=20*time; idly>0; idly--);
+}
+
+/*-----------------------------------------------------------------------
+ *  初始化按键
+ *  key2
+ *  *PE3
+ * -----------------------------------------------------------------------*/
+void key_init(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOE);
+    gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,GPIO_PIN_3); //
+    timeout_setValue(&g_keyinfo.timer,5000);
+    g_keyinfo.keyVal = 0;
+    g_keyinfo.count = 0;
+    g_keyinfo.keyPress = 0x00;
+}
+static void set_key_value(uint8_t keyval)
+{
+    if((0!=g_keyinfo.keyVal) && (keyval != g_keyinfo.keyVal) ){
+        g_keyinfo.count = 0;
+        g_keyinfo.keyPress = 0;
+        timeout_stop(&g_keyinfo.timer);
+    }
+    g_keyinfo.keyVal = keyval;
+    if(0==g_keyinfo.count){
+        timeout_start(&g_keyinfo.timer);
+    }
+    if(0 == g_keyinfo.keyPress){
+        g_keyinfo.count++;
+        g_keyinfo.keyPress = 1;
+    }
+}
+/*-----------------------------------------------------------------------
+ *  检测按键的输入
+ * ----------------------------------------------------------------------*/
+uint8_t key_scan(void)
+{
+    if(KEY2_DOWN()){ // 按键按下
+        key_delay(20); // 消抖
+        if(KEY2_DOWN()) { // 确定按键按下
+            set_key_value(KEY2_VAL);
+        }
+    }
+    else {
+        g_keyinfo.keyPress = 0x00;
+        if((g_keyinfo.keyVal !=0) && (g_keyinfo.count>0) ){
+            if(timeout_isOut(&g_keyinfo.timer))
+                return 1;
+            else return 0;
+        }
+    }
+
+    return 0;
+}
+/*---------------------------------------------------------------------------------
+ *  按键的处理
+ * --------------------------------------------------------------------------------*/
+void key_opteration(void)
+{
+    if(KEY2_VAL == g_keyinfo.keyVal ){
+        switch (g_keyinfo.count){
+        case 1:break; // 按键按一次
+        case 2:break; // 按键按二次
+        case 3: // 按键按三次
+            ota_start_offline_update();
+            break;
+        default:
+            break;
+        }
+    }
+    else if(KEY4_VAL == g_keyinfo.keyVal) {
+        switch(g_keyinfo.count){
+        case 1:
+            break;
+        case 2: break;
+        case 3:
+//            if(IDENTITY_MASTER == g_iDentity) {
+//                g_taskRunDa.keyReadcurData = 1;
+//                g_taskRunDa.keySaveMasterDa = 1;
+//                printf("按键读取显示屏的值 \r\n");
+//            }
+            break;
+        default: break;
+        }
+    }
+}

+ 27 - 0
Hardware/key.h

@@ -0,0 +1,27 @@
+#ifndef _KEY_H_
+#define _KEY_H_
+
+#include "../User/gd32f10x_it.h"
+#include "timeout.h"
+
+#define KEY2_DOWN() (gpio_input_bit_get(GPIOE,GPIO_PIN_3) == RESET) // 按键按下
+#define KEY2_UP()   (gpio_input_bit_get(GPIOE,GPIO_PIN_3) == SET)   // 按键抬起
+
+enum {
+    KEY2_VAL = 0x11,
+    KEY3_VAL = 0x12,
+    KEY4_VAL = 0x13,
+};
+typedef struct _key_init_{
+    uint8_t keyVal;   // 键值
+    uint8_t keyPress; // 按下  抬起 无操作
+    uint8_t count;    // 时间内按下的次数
+    timeout_t timer;  // 时间
+
+}__attribute__((packed))KeyInfo;
+extern KeyInfo g_keyinfo;
+
+extern void key_init(void);
+extern uint8_t key_scan(void);
+extern void key_opteration(void);
+#endif

+ 67 - 0
Hardware/rtc.c

@@ -0,0 +1,67 @@
+#include "rtc.h"
+#include "Uart.h"
+
+void rtc_configuration(void)
+{
+
+     rcu_periph_clock_enable(RCU_BKPI);/* enable PMU and BKPI clocks */
+     rcu_periph_clock_enable(RCU_PMU);
+
+     pmu_backup_write_enable();/* allow access to BKP domain */
+
+     bkp_deinit();/* reset backup domain */
+
+     rcu_osci_on(RCU_LXTAL);/* enable LXTAL */
+     rcu_osci_stab_wait(RCU_LXTAL);/* wait till LXTAL is ready */
+     rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);/* select RCU_LXTAL as RTC clock source */
+     rcu_periph_clock_enable(RCU_RTC);/* enable RTC Clock */
+     rtc_register_sync_wait();/* wait for RTC registers synchronization */
+     rtc_lwoff_wait();/* wait until last write operation on RTC registers has finished */
+     //rtc_interrupt_enable(RTC_INT_SECOND);/* enable the RTC second interrupt*/
+     rtc_lwoff_wait();/* wait until last write operation on RTC registers has finished */
+     rtc_prescaler_set(32767);/* set RTC prescaler: set RTC period to 1s */
+     rtc_lwoff_wait();/* wait until last write operation on RTC registers has finished */
+}
+void set_time(uint32_t time)
+{
+
+    /* wait until last write operation on RTC registers has finished */
+    rtc_lwoff_wait();
+    /* change the current time */
+    rtc_counter_set(time);
+    /* wait until last write operation on RTC registers has finished */
+    rtc_lwoff_wait();
+
+}
+void rct_init(void)
+{
+    if (bkp_data_read(BKP_DATA_0) != 0xA5A5){
+
+        printf("\r\nThis is a RTC demo!\r\n");
+        printf("\r\n\n RTC not yet configured....");
+        rtc_configuration();/* RTC configuration */
+        printf("\r\n RTC configured....");
+
+        /* adjust time by values entred by the user on the hyperterminal */
+        set_time(1684302671);
+
+        bkp_data_write(BKP_DATA_0, 0xA5A5);
+    }else{
+
+        if (rcu_flag_get(RCU_FLAG_PORRST) != RESET){/* check if the power on reset flag is set */
+            printf("\r\n\n Power On Reset occurred....");
+        }
+        else if (rcu_flag_get(RCU_FLAG_SWRST) != RESET){
+            printf("\r\n\n External Reset occurred....");/* check if the pin reset flag is set */
+        }
+        rcu_periph_clock_enable(RCU_PMU);/* allow access to BKP domain */
+        pmu_backup_write_enable();
+        printf("\r\n No need to configure RTC....");
+        rtc_register_sync_wait();/* wait for RTC registers synchronization */
+        rtc_lwoff_wait();/* wait until last write operation on RTC registers has finished */
+    }
+
+    //rcu_all_reset_flag_clear();/* clear reset flags */
+}
+
+

+ 8 - 0
Hardware/rtc.h

@@ -0,0 +1,8 @@
+#ifndef _RTC_H_
+#define _RTC_H_
+
+#include "../User/gd32f10x_it.h"
+
+extern void rct_init(void);
+extern void set_time(uint32_t time);
+#endif

+ 53 - 0
Hardware/timeout.c

@@ -0,0 +1,53 @@
+#include "timeout.h"
+
+
+/*----------------------------------------------------------------------------
+  * 设置定时器
+  * tt:定时器指针
+  * val,延时ms
+  *---------------------------------------------------------------------------*/
+void timeout_setValue(timeout_t *tt,uint32_t val){
+  tt->counter = Get_SysTick();
+  tt->timeout = val;
+}
+/*----------------------------------------------------------------------------
+ * 启动定时器
+ * tt :定时器指针
+ *---------------------------------------------------------------------------*/
+void timeout_start(timeout_t *tt){
+    tt->counter = Get_SysTick();
+    tt->flag = 1;
+    tt->endMode = 1;
+
+}
+/*----------------------------------------------------------------------------
+ * 停止定时器
+ * tt: 定时器指针
+ *---------------------------------------------------------------------------*/
+void timeout_stop(timeout_t *tt){
+  tt->flag = 0;
+  tt->endMode = 2;
+}
+/*----------------------------------------------------------------------------
+ * 返回定时器是否超时
+ * tt:定时器指针
+ * 返回值 1:超时 0:未超时
+ *---------------------------------------------------------------------------*/
+uint8_t timeout_isOut(timeout_t *tt){
+  if(tt->flag){
+    if((Get_SysTick() - tt->counter) > tt->timeout){
+      tt->counter = Get_SysTick();
+      if(tt->flag == 1){
+        tt->flag = 0;
+      }
+      tt->endMode = 0x03;
+      return 1;
+    }
+    else{
+      return 0;
+    }
+  }
+  else{
+    return 1;
+  }
+}

+ 19 - 0
Hardware/timeout.h

@@ -0,0 +1,19 @@
+#ifndef _TIMEOUT_H_
+#define _TIMEOUT_H_
+
+#include "../User/gd32f10x_it.h"
+
+typedef struct
+{
+  uint8_t flag;
+  uint8_t endMode; // 1:start 2: endNormal
+  uint32_t counter;
+  uint32_t timeout;
+}__attribute__((packed)) timeout_t;
+
+extern void timeout_setValue(timeout_t *tt,uint32_t val);
+extern void timeout_start(timeout_t *tt);
+extern void timeout_stop(timeout_t *tt);
+extern uint8_t timeout_isOut(timeout_t *tt);
+
+#endif

+ 367 - 0
Library/Include/gd32f10x_adc.h

@@ -0,0 +1,367 @@
+/*!
+    \file    gd32f10x_adc.h
+    \brief   definitions for the ADC
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10x_ADC_H
+#define GD32F10x_ADC_H
+
+#include "gd32f10x.h"
+
+/* ADC definitions */
+#define ADC0                            ADC_BASE
+#define ADC1                            (ADC_BASE + 0x400U)
+#define ADC2                            (ADC_BASE + 0x1800U)
+
+/* registers definitions */
+#define ADC_STAT(adcx)                  REG32((adcx) + 0x00U)            /*!< ADC status register */
+#define ADC_CTL0(adcx)                  REG32((adcx) + 0x04U)            /*!< ADC control register 0 */
+#define ADC_CTL1(adcx)                  REG32((adcx) + 0x08U)            /*!< ADC control register 1 */
+#define ADC_SAMPT0(adcx)                REG32((adcx) + 0x0CU)            /*!< ADC sampling time register 0 */
+#define ADC_SAMPT1(adcx)                REG32((adcx) + 0x10U)            /*!< ADC sampling time register 1 */
+#define ADC_IOFF0(adcx)                 REG32((adcx) + 0x14U)            /*!< ADC inserted channel data offset register 0 */
+#define ADC_IOFF1(adcx)                 REG32((adcx) + 0x18U)            /*!< ADC inserted channel data offset register 1 */
+#define ADC_IOFF2(adcx)                 REG32((adcx) + 0x1CU)            /*!< ADC inserted channel data offset register 2 */
+#define ADC_IOFF3(adcx)                 REG32((adcx) + 0x20U)            /*!< ADC inserted channel data offset register 3 */
+#define ADC_WDHT(adcx)                  REG32((adcx) + 0x24U)            /*!< ADC watchdog high threshold register */
+#define ADC_WDLT(adcx)                  REG32((adcx) + 0x28U)            /*!< ADC watchdog low threshold register */
+#define ADC_RSQ0(adcx)                  REG32((adcx) + 0x2CU)            /*!< ADC regular sequence register 0 */
+#define ADC_RSQ1(adcx)                  REG32((adcx) + 0x30U)            /*!< ADC regular sequence register 1 */
+#define ADC_RSQ2(adcx)                  REG32((adcx) + 0x34U)            /*!< ADC regular sequence register 2 */
+#define ADC_ISQ(adcx)                   REG32((adcx) + 0x38U)            /*!< ADC inserted sequence register */
+#define ADC_IDATA0(adcx)                REG32((adcx) + 0x3CU)            /*!< ADC inserted data register 0 */
+#define ADC_IDATA1(adcx)                REG32((adcx) + 0x40U)            /*!< ADC inserted data register 1 */
+#define ADC_IDATA2(adcx)                REG32((adcx) + 0x44U)            /*!< ADC inserted data register 2 */
+#define ADC_IDATA3(adcx)                REG32((adcx) + 0x48U)            /*!< ADC inserted data register 3 */
+#define ADC_RDATA(adcx)                 REG32((adcx) + 0x4CU)            /*!< ADC regular data register */
+
+/* bits definitions */
+/* ADC_STAT */
+#define ADC_STAT_WDE                    BIT(0)                           /*!< analog watchdog event flag */
+#define ADC_STAT_EOC                    BIT(1)                           /*!< end of conversion */
+#define ADC_STAT_EOIC                   BIT(2)                           /*!< inserted channel end of conversion */
+#define ADC_STAT_STIC                   BIT(3)                           /*!< inserted channel start flag */
+#define ADC_STAT_STRC                   BIT(4)                           /*!< regular channel start flag */
+
+/* ADC_CTL0 */
+#define ADC_CTL0_WDCHSEL                BITS(0,4)                        /*!< analog watchdog channel select bits */
+#define ADC_CTL0_EOCIE                  BIT(5)                           /*!< interrupt enable for EOC */
+#define ADC_CTL0_WDEIE                  BIT(6)                           /*!< analog watchdog interrupt enable */
+#define ADC_CTL0_EOICIE                 BIT(7)                           /*!< interrupt enable for inserted channels */
+#define ADC_CTL0_SM                     BIT(8)                           /*!< scan mode */
+#define ADC_CTL0_WDSC                   BIT(9)                           /*!< when in scan mode, analog watchdog is effective on a single channel */
+#define ADC_CTL0_ICA                    BIT(10)                          /*!< automatic inserted group conversion */
+#define ADC_CTL0_DISRC                  BIT(11)                          /*!< discontinuous mode on regular channels */
+#define ADC_CTL0_DISIC                  BIT(12)                          /*!< discontinuous mode on inserted channels */
+#define ADC_CTL0_DISNUM                 BITS(13,15)                      /*!< discontinuous mode channel count */
+#define ADC_CTL0_SYNCM                  BITS(16,19)                      /*!< sync mode selection */
+#define ADC_CTL0_IWDEN                  BIT(22)                          /*!< analog watchdog enable on inserted channels */
+#define ADC_CTL0_RWDEN                  BIT(23)                          /*!< analog watchdog enable on regular channels */
+#define ADC_CTL0_DRES                   BITS(24,25)                      /*!< ADC data resolution */
+
+/* ADC_CTL1 */
+#define ADC_CTL1_ADCON                  BIT(0)                           /*!< ADC converter on */
+#define ADC_CTL1_CTN                    BIT(1)                           /*!< continuous conversion */
+#define ADC_CTL1_CLB                    BIT(2)                           /*!< ADC calibration */
+#define ADC_CTL1_RSTCLB                 BIT(3)                           /*!< reset calibration */
+#define ADC_CTL1_DMA                    BIT(8)                           /*!< direct memory access mode */
+#define ADC_CTL1_DAL                    BIT(11)                          /*!< data alignment */
+#define ADC_CTL1_ETSIC                  BITS(12,14)                      /*!< external trigger select for inserted channel */
+#define ADC_CTL1_ETEIC                  BIT(15)                          /*!< external trigger enable for inserted channel */
+#define ADC_CTL1_ETSRC                  BITS(17,19)                      /*!< external trigger select for regular channel */
+#define ADC_CTL1_ETERC                  BIT(20)                          /*!< external trigger conversion mode for inserted channels */
+#define ADC_CTL1_SWICST                 BIT(21)                          /*!< start on inserted channel */
+#define ADC_CTL1_SWRCST                 BIT(22)                          /*!< start on regular channel */
+#define ADC_CTL1_TSVREN                 BIT(23)                          /*!< channel 16 and 17 enable of ADC0 */
+
+/* ADC_SAMPTx x=0..1 */
+#define ADC_SAMPTX_SPTN                 BITS(0,2)                        /*!< channel n sample time selection */
+
+/* ADC_IOFFx x=0..3 */
+#define ADC_IOFFX_IOFF                  BITS(0,11)                       /*!< data offset for inserted channel x */
+
+/* ADC_WDHT */
+#define ADC_WDHT_WDHT                   BITS(0,11)                       /*!< analog watchdog high threshold */
+
+/* ADC_WDLT */
+#define ADC_WDLT_WDLT                   BITS(0,11)                       /*!< analog watchdog low threshold */
+
+/* ADC_RSQx x=0..2 */
+#define ADC_RSQX_RSQN                   BITS(0,4)                        /*!< nth conversion in regular sequence */
+#define ADC_RSQ0_RL                     BITS(20,23)                      /*!< regular channel sequence length */
+
+/* ADC_ISQ */
+#define ADC_ISQ_ISQN                    BITS(0,4)                        /*!< nth conversion in inserted sequence */
+#define ADC_ISQ_IL                      BITS(20,21)                      /*!< inserted sequence length */
+
+/* ADC_IDATAx x=0..3*/
+#define ADC_IDATAX_IDATAN               BITS(0,15)                       /*!< inserted data n */
+
+/* ADC_RDATA */
+#define ADC_RDATA_RDATA                 BITS(0,15)                       /*!< regular data */
+#define ADC_RDATA_ADC1RDTR              BITS(16,31)                      /*!< ADC1 regular channel data */
+
+/* constants definitions */
+/* adc_stat register value */
+#define ADC_FLAG_WDE                    ADC_STAT_WDE                                 /*!< analog watchdog event flag */
+#define ADC_FLAG_EOC                    ADC_STAT_EOC                                 /*!< end of conversion */
+#define ADC_FLAG_EOIC                   ADC_STAT_EOIC                                /*!< inserted channel end of conversion */
+#define ADC_FLAG_STIC                   ADC_STAT_STIC                                /*!< inserted channel start flag */
+#define ADC_FLAG_STRC                   ADC_STAT_STRC                                /*!< regular channel start flag */
+
+/* adc_ctl0 register value */
+#define CTL0_DISNUM(regval)             (BITS(13,15) & ((uint32_t)(regval) << 13))   /*!< write value to ADC_CTL0_DISNUM bit field */
+
+/* scan mode */
+#define ADC_SCAN_MODE                   ADC_CTL0_SM                                  /*!< scan mode */
+
+/* inserted channel group convert automatically */
+#define ADC_INSERTED_CHANNEL_AUTO       ADC_CTL0_ICA                                 /*!< inserted channel group convert automatically */
+
+/* ADC sync mode */
+#define CTL0_SYNCM(regval)              (BITS(16,19) & ((uint32_t)(regval) << 16))   /*!< write value to ADC_CTL0_SYNCM bit field */
+#define ADC_MODE_FREE                                        CTL0_SYNCM(0)           /*!< all the ADCs work independently */
+#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL          CTL0_SYNCM(1)           /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */
+#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION          CTL0_SYNCM(2)           /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */
+#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST     CTL0_SYNCM(3)           /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */
+#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW     CTL0_SYNCM(4)           /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */
+#define ADC_DAUL_INSERTED_PARALLEL                           CTL0_SYNCM(5)           /*!< ADC0 and ADC1 work in inserted parallel mode only */
+#define ADC_DAUL_REGULAL_PARALLEL                            CTL0_SYNCM(6)           /*!< ADC0 and ADC1 work in regular parallel mode only */
+#define ADC_DAUL_REGULAL_FOLLOWUP_FAST                       CTL0_SYNCM(7)           /*!< ADC0 and ADC1 work in follow-up fast mode only */
+#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW                       CTL0_SYNCM(8)           /*!< ADC0 and ADC1 work in follow-up slow mode only */
+#define ADC_DAUL_INSERTED_TRIGGER_ROTATION                   CTL0_SYNCM(9)           /*!< ADC0 and ADC1 work in trigger rotation mode only */
+
+/* adc_ctl1 register value */
+#define ADC_DATAALIGN_RIGHT              ((uint32_t)0x00000000U)                     /*!< LSB alignment */
+#define ADC_DATAALIGN_LEFT               ADC_CTL1_DAL                                /*!< MSB alignment */
+
+/* continuous mode */
+#define ADC_CONTINUOUS_MODE              ADC_CTL1_CTN                                /*!< continuous mode */
+
+/* external trigger select for regular channel */
+#define CTL1_ETSRC(regval)               (BITS(17,19) & ((uint32_t)(regval) << 17))  /*!< write value to ADC_CTL1_ETSRC bit field */
+/* for ADC0 and ADC1 regular channel */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH0    CTL1_ETSRC(0)                               /*!< TIMER0 CH0 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH1    CTL1_ETSRC(1)                               /*!< TIMER0 CH1 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH2    CTL1_ETSRC(2)                               /*!< TIMER0 CH2 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T1_CH1    CTL1_ETSRC(3)                               /*!< TIMER1 CH1 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO   CTL1_ETSRC(4)                               /*!< TIMER2 TRGO event select */
+#define ADC0_1_EXTTRIG_REGULAR_T3_CH3    CTL1_ETSRC(5)                               /*!< TIMER3 CH3 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO   CTL1_ETSRC(6)                               /*!< TIMER7 TRGO event select */
+#define ADC0_1_EXTTRIG_REGULAR_EXTI_11   CTL1_ETSRC(6)                               /*!< external interrupt line 11 */
+#define ADC0_1_2_EXTTRIG_REGULAR_NONE    CTL1_ETSRC(7)                               /*!< software trigger */
+/* for ADC2 regular channel */
+#define ADC2_EXTTRIG_REGULAR_T2_CH0      CTL1_ETSRC(0)                               /*!< TIMER2 CH0 event select */
+#define ADC2_EXTTRIG_REGULAR_T1_CH2      CTL1_ETSRC(1)                               /*!< TIMER1 CH2 event select */
+#define ADC2_EXTTRIG_REGULAR_T0_CH2      CTL1_ETSRC(2)                               /*!< TIMER0 CH2 event select */
+#define ADC2_EXTTRIG_REGULAR_T7_CH0      CTL1_ETSRC(3)                               /*!< TIMER7 CH0 event select */
+#define ADC2_EXTTRIG_REGULAR_T7_TRGO     CTL1_ETSRC(4)                               /*!< TIMER7 TRGO event select */
+#define ADC2_EXTTRIG_REGULAR_T4_CH0      CTL1_ETSRC(5)                               /*!< TIMER4 CH0 event select */
+#define ADC2_EXTTRIG_REGULAR_T4_CH2      CTL1_ETSRC(6)                               /*!< TIMER4 CH2 event select */
+
+/* external trigger mode for inserted channel */
+#define CTL1_ETSIC(regval)               (BITS(12,14) & ((uint32_t)(regval) << 12))  /*!< write value to ADC_CTL1_ETSIC bit field */
+/* for ADC0 and ADC1 inserted channel */
+#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO  CTL1_ETSIC(0)                               /*!< TIMER0 TRGO event select */
+#define ADC0_1_EXTTRIG_INSERTED_T0_CH3   CTL1_ETSIC(1)                               /*!< TIMER0 CH3 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO  CTL1_ETSIC(2)                               /*!< TIMER1 TRGO event select */
+#define ADC0_1_EXTTRIG_INSERTED_T1_CH0   CTL1_ETSIC(3)                               /*!< TIMER1 CH0 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T2_CH3   CTL1_ETSIC(4)                               /*!< TIMER2 CH3 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO  CTL1_ETSIC(5)                               /*!< TIMER3 TRGO event select */
+#define ADC0_1_EXTTRIG_INSERTED_EXTI_15  CTL1_ETSIC(6)                               /*!< external interrupt line 15 */
+#define ADC0_1_EXTTRIG_INSERTED_T7_CH3   CTL1_ETSIC(6)                               /*!< TIMER7 CH3 event select */
+#define ADC0_1_2_EXTTRIG_INSERTED_NONE   CTL1_ETSIC(7)                               /*!< software trigger */
+/* for ADC2 inserted channel */
+#define ADC2_EXTTRIG_INSERTED_T0_TRGO    CTL1_ETSIC(0)                               /*!< TIMER0 TRGO event select */
+#define ADC2_EXTTRIG_INSERTED_T0_CH3     CTL1_ETSIC(1)                               /*!< TIMER0 CH3 event select */
+#define ADC2_EXTTRIG_INSERTED_T3_CH2     CTL1_ETSIC(2)                               /*!< TIMER3 CH2 event select */
+#define ADC2_EXTTRIG_INSERTED_T7_CH1     CTL1_ETSIC(3)                               /*!< TIMER7 CH1 event select */
+#define ADC2_EXTTRIG_INSERTED_T7_CH3     CTL1_ETSIC(4)                               /*!< TIMER7 CH3 event select */
+#define ADC2_EXTTRIG_INSERTED_T4_TRGO    CTL1_ETSIC(5)                               /*!< TIMER4 TRGO event select */
+#define ADC2_EXTTRIG_INSERTED_T4_CH3     CTL1_ETSIC(6)                               /*!< TIMER4 CH3 event select */
+
+/* adc_samptx register value */
+#define SAMPTX_SPT(regval)               (BITS(0,2) & ((uint32_t)(regval) << 0))     /*!< write value to ADC_SAMPTX_SPT bit field */
+#define ADC_SAMPLETIME_1POINT5           SAMPTX_SPT(0)                               /*!< 1.5 sampling cycles */
+#define ADC_SAMPLETIME_7POINT5           SAMPTX_SPT(1)                               /*!< 7.5 sampling cycles */
+#define ADC_SAMPLETIME_13POINT5          SAMPTX_SPT(2)                               /*!< 13.5 sampling cycles */
+#define ADC_SAMPLETIME_28POINT5          SAMPTX_SPT(3)                               /*!< 28.5 sampling cycles */
+#define ADC_SAMPLETIME_41POINT5          SAMPTX_SPT(4)                               /*!< 41.5 sampling cycles */
+#define ADC_SAMPLETIME_55POINT5          SAMPTX_SPT(5)                               /*!< 55.5 sampling cycles */
+#define ADC_SAMPLETIME_71POINT5          SAMPTX_SPT(6)                               /*!< 71.5 sampling cycles */
+#define ADC_SAMPLETIME_239POINT5         SAMPTX_SPT(7)                               /*!< 239.5 sampling cycles */
+
+/* adc_ioffx register value */
+#define IOFFX_IOFF(regval)               (BITS(0,11) & ((uint32_t)(regval) << 0))    /*!< write value to ADC_IOFFX_IOFF bit field */
+
+/* adc_wdht register value */
+#define WDHT_WDHT(regval)                (BITS(0,11) & ((uint32_t)(regval) << 0))    /*!< write value to ADC_WDHT_WDHT bit field */
+
+/* adc_wdlt register value */
+#define WDLT_WDLT(regval)                (BITS(0,11) & ((uint32_t)(regval) << 0))    /*!< write value to ADC_WDLT_WDLT bit field */
+
+/* adc_rsqx register value */
+#define RSQ0_RL(regval)                  (BITS(20,23) & ((uint32_t)(regval) << 20))  /*!< write value to ADC_RSQ0_RL bit field */
+
+/* adc_isq register value */
+#define ISQ_IL(regval)                   (BITS(20,21) & ((uint32_t)(regval) << 20))  /*!< write value to ADC_ISQ_IL bit field */
+
+/* ADC channel group definitions */
+#define ADC_REGULAR_CHANNEL              ((uint8_t)0x01U)                            /*!< adc regular channel group */
+#define ADC_INSERTED_CHANNEL             ((uint8_t)0x02U)                            /*!< adc inserted channel group */
+#define ADC_REGULAR_INSERTED_CHANNEL     ((uint8_t)0x03U)                            /*!< both regular and inserted channel group */
+
+#define ADC_CHANNEL_DISCON_DISABLE       ((uint8_t)0x04U)                            /*!< disable discontinuous mode of regular & inserted channel */
+
+/* ADC inserted channel definitions */
+#define ADC_INSERTED_CHANNEL_0           ((uint8_t)0x00U)                            /*!< adc inserted channel 0 */
+#define ADC_INSERTED_CHANNEL_1           ((uint8_t)0x01U)                            /*!< adc inserted channel 1 */
+#define ADC_INSERTED_CHANNEL_2           ((uint8_t)0x02U)                            /*!< adc inserted channel 2 */
+#define ADC_INSERTED_CHANNEL_3           ((uint8_t)0x03U)                            /*!< adc inserted channel 3 */
+
+/* ADC channel definitions */
+#define ADC_CHANNEL_0                    ((uint8_t)0x00U)                            /*!< ADC channel 0 */
+#define ADC_CHANNEL_1                    ((uint8_t)0x01U)                            /*!< ADC channel 1 */
+#define ADC_CHANNEL_2                    ((uint8_t)0x02U)                            /*!< ADC channel 2 */
+#define ADC_CHANNEL_3                    ((uint8_t)0x03U)                            /*!< ADC channel 3 */
+#define ADC_CHANNEL_4                    ((uint8_t)0x04U)                            /*!< ADC channel 4 */
+#define ADC_CHANNEL_5                    ((uint8_t)0x05U)                            /*!< ADC channel 5 */
+#define ADC_CHANNEL_6                    ((uint8_t)0x06U)                            /*!< ADC channel 6 */
+#define ADC_CHANNEL_7                    ((uint8_t)0x07U)                            /*!< ADC channel 7 */
+#define ADC_CHANNEL_8                    ((uint8_t)0x08U)                            /*!< ADC channel 8 */
+#define ADC_CHANNEL_9                    ((uint8_t)0x09U)                            /*!< ADC channel 9 */
+#define ADC_CHANNEL_10                   ((uint8_t)0x0AU)                            /*!< ADC channel 10 */
+#define ADC_CHANNEL_11                   ((uint8_t)0x0BU)                            /*!< ADC channel 11 */
+#define ADC_CHANNEL_12                   ((uint8_t)0x0CU)                            /*!< ADC channel 12 */
+#define ADC_CHANNEL_13                   ((uint8_t)0x0DU)                            /*!< ADC channel 13 */
+#define ADC_CHANNEL_14                   ((uint8_t)0x0EU)                            /*!< ADC channel 14 */
+#define ADC_CHANNEL_15                   ((uint8_t)0x0FU)                            /*!< ADC channel 15 */
+#define ADC_CHANNEL_16                   ((uint8_t)0x10U)                            /*!< ADC channel 16 */
+#define ADC_CHANNEL_17                   ((uint8_t)0x11U)                            /*!< ADC channel 17 */
+
+/* ADC interrupt */
+#define ADC_INT_WDE                      ADC_STAT_WDE                                /*!< analog watchdog event interrupt */
+#define ADC_INT_EOC                      ADC_STAT_EOC                                /*!< end of group conversion interrupt */
+#define ADC_INT_EOIC                     ADC_STAT_EOIC                               /*!< end of inserted group conversion interrupt */
+
+/* ADC interrupt flag */
+#define ADC_INT_FLAG_WDE                 ADC_STAT_WDE                                /*!< analog watchdog event interrupt flag */
+#define ADC_INT_FLAG_EOC                 ADC_STAT_EOC                                /*!< end of group conversion interrupt flag */
+#define ADC_INT_FLAG_EOIC                ADC_STAT_EOIC                               /*!< end of inserted group conversion interrupt flag */
+
+/* function declarations */
+/* initialization config */
+/* reset ADC */
+void adc_deinit(uint32_t adc_periph);
+/* configure the ADC sync mode */
+void adc_mode_config(uint32_t mode);
+/* enable or disable ADC special function */
+void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue);
+/* configure ADC data alignment */
+void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment);
+/* enable ADC interface */
+void adc_enable(uint32_t adc_periph);
+/* disable ADC interface */
+void adc_disable(uint32_t adc_periph);
+/* ADC calibration and reset calibration */
+void adc_calibration_enable(uint32_t adc_periph);
+/* enable the temperature sensor and Vrefint channel */
+void adc_tempsensor_vrefint_enable(void);
+/* disable the temperature sensor and Vrefint channel */
+void adc_tempsensor_vrefint_disable(void);
+
+/* DMA config */
+/* enable DMA request */
+void adc_dma_mode_enable(uint32_t adc_periph);
+/* disable DMA request */
+void adc_dma_mode_disable(uint32_t adc_periph);
+
+/* regular group and inserted group config */
+/* configure ADC discontinuous mode */
+void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length);
+
+/* configure the length of regular channel group or inserted channel group */
+void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length);
+/* configure ADC regular channel */
+void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time);
+/* configure ADC inserted channel */
+void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time);
+/* configure ADC inserted channel offset */
+void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset);
+
+/* configure ADC external trigger source */
+void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source);
+/* configure ADC external trigger */
+void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue);
+/* enable ADC software trigger */
+void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group);
+
+/* get channel data */
+/* read ADC regular group data register */
+uint16_t adc_regular_data_read(uint32_t adc_periph);
+/* read ADC inserted group data register */
+uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel);
+/* read the last ADC0 and ADC1 conversion result data in sync mode */
+uint32_t adc_sync_mode_convert_value_read(void);
+
+/* watchdog config */
+/* configure ADC analog watchdog single channel */
+void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel);
+/* configure ADC analog watchdog group channel */
+void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group);
+/* disable ADC analog watchdog */
+void adc_watchdog_disable(uint32_t adc_periph);
+/* configure ADC analog watchdog threshold */
+void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold);
+
+/* interrupt & flag functions */
+/* get the ADC flag bits */
+FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag);
+/* clear the ADC flag bits */
+void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag);
+/* get the bit state of ADCx software start conversion */
+FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph);
+/* get the bit state of ADCx software inserted channel start conversion */
+FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph);
+/* get the ADC interrupt bits */
+FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt);
+/* clear the ADC flag */
+void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt);
+/* enable ADC interrupt */
+void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt);
+/* disable ADC interrupt */
+void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt);
+
+#endif /* GD32F10x_ADC_H */

+ 229 - 0
Library/Include/gd32f10x_bkp.h

@@ -0,0 +1,229 @@
+/*!
+    \file    gd32f10x_bkp.h
+    \brief   definitions for the BKP
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_BKP_H
+#define GD32F10X_BKP_H
+
+#include "gd32f10x.h"
+
+/* BKP definitions */
+#define BKP                             BKP_BASE                 /*!< BKP base address */
+
+/* registers definitions */
+#define BKP_DATA0                       REG16((BKP) + 0x04U)     /*!< BKP data register 0 */
+#define BKP_DATA1                       REG16((BKP) + 0x08U)     /*!< BKP data register 1 */
+#define BKP_DATA2                       REG16((BKP) + 0x0CU)     /*!< BKP data register 2 */
+#define BKP_DATA3                       REG16((BKP) + 0x10U)     /*!< BKP data register 3 */
+#define BKP_DATA4                       REG16((BKP) + 0x14U)     /*!< BKP data register 4 */
+#define BKP_DATA5                       REG16((BKP) + 0x18U)     /*!< BKP data register 5 */
+#define BKP_DATA6                       REG16((BKP) + 0x1CU)     /*!< BKP data register 6 */
+#define BKP_DATA7                       REG16((BKP) + 0x20U)     /*!< BKP data register 7 */
+#define BKP_DATA8                       REG16((BKP) + 0x24U)     /*!< BKP data register 8 */
+#define BKP_DATA9                       REG16((BKP) + 0x28U)     /*!< BKP data register 9 */
+#define BKP_DATA10                      REG16((BKP) + 0x40U)     /*!< BKP data register 10 */
+#define BKP_DATA11                      REG16((BKP) + 0x44U)     /*!< BKP data register 11 */
+#define BKP_DATA12                      REG16((BKP) + 0x48U)     /*!< BKP data register 12 */
+#define BKP_DATA13                      REG16((BKP) + 0x4CU)     /*!< BKP data register 13 */
+#define BKP_DATA14                      REG16((BKP) + 0x50U)     /*!< BKP data register 14 */
+#define BKP_DATA15                      REG16((BKP) + 0x54U)     /*!< BKP data register 15 */
+#define BKP_DATA16                      REG16((BKP) + 0x58U)     /*!< BKP data register 16 */
+#define BKP_DATA17                      REG16((BKP) + 0x5CU)     /*!< BKP data register 17 */
+#define BKP_DATA18                      REG16((BKP) + 0x60U)     /*!< BKP data register 18 */
+#define BKP_DATA19                      REG16((BKP) + 0x64U)     /*!< BKP data register 19 */
+#define BKP_DATA20                      REG16((BKP) + 0x68U)     /*!< BKP data register 20 */
+#define BKP_DATA21                      REG16((BKP) + 0x6CU)     /*!< BKP data register 21 */
+#define BKP_DATA22                      REG16((BKP) + 0x70U)     /*!< BKP data register 22 */
+#define BKP_DATA23                      REG16((BKP) + 0x74U)     /*!< BKP data register 23 */
+#define BKP_DATA24                      REG16((BKP) + 0x78U)     /*!< BKP data register 24 */
+#define BKP_DATA25                      REG16((BKP) + 0x7CU)     /*!< BKP data register 25 */
+#define BKP_DATA26                      REG16((BKP) + 0x80U)     /*!< BKP data register 26 */
+#define BKP_DATA27                      REG16((BKP) + 0x84U)     /*!< BKP data register 27 */
+#define BKP_DATA28                      REG16((BKP) + 0x88U)     /*!< BKP data register 28 */
+#define BKP_DATA29                      REG16((BKP) + 0x8CU)     /*!< BKP data register 29 */
+#define BKP_DATA30                      REG16((BKP) + 0x90U)     /*!< BKP data register 30 */
+#define BKP_DATA31                      REG16((BKP) + 0x94U)     /*!< BKP data register 31 */
+#define BKP_DATA32                      REG16((BKP) + 0x98U)     /*!< BKP data register 32 */
+#define BKP_DATA33                      REG16((BKP) + 0x9CU)     /*!< BKP data register 33 */
+#define BKP_DATA34                      REG16((BKP) + 0xA0U)     /*!< BKP data register 34 */
+#define BKP_DATA35                      REG16((BKP) + 0xA4U)     /*!< BKP data register 35 */
+#define BKP_DATA36                      REG16((BKP) + 0xA8U)     /*!< BKP data register 36 */
+#define BKP_DATA37                      REG16((BKP) + 0xACU)     /*!< BKP data register 37 */
+#define BKP_DATA38                      REG16((BKP) + 0xB0U)     /*!< BKP data register 38 */
+#define BKP_DATA39                      REG16((BKP) + 0xB4U)     /*!< BKP data register 39 */
+#define BKP_DATA40                      REG16((BKP) + 0xB8U)     /*!< BKP data register 40 */
+#define BKP_DATA41                      REG16((BKP) + 0xBCU)     /*!< BKP data register 41 */
+#define BKP_OCTL                        REG16((BKP) + 0x2CU)     /*!< RTC signal output control register */
+#define BKP_TPCTL                       REG16((BKP) + 0x30U)     /*!< tamper pin control register */
+#define BKP_TPCS                        REG16((BKP) + 0x34U)     /*!< tamper control and status register */
+
+/* bits definitions */
+/* BKP_DATA */
+#define BKP_DATA                        BITS(0,15)               /*!< backup data */
+
+/* BKP_OCTL */
+#define BKP_OCTL_RCCV                   BITS(0,6)                /*!< RTC clock calibration value */
+#define BKP_OCTL_COEN                   BIT(7)                   /*!< RTC clock calibration output enable */
+#define BKP_OCTL_ASOEN                  BIT(8)                   /*!< RTC alarm or second signal output enable */
+#define BKP_OCTL_ROSEL                  BIT(9)                   /*!< RTC output selection */
+
+/* BKP_TPCTL */
+#define BKP_TPCTL_TPEN                  BIT(0)                   /*!< tamper detection enable */
+#define BKP_TPCTL_TPAL                  BIT(1)                   /*!< tamper pin active level */
+
+/* BKP_TPCS */
+#define BKP_TPCS_TER                    BIT(0)                   /*!< tamper event reset */
+#define BKP_TPCS_TIR                    BIT(1)                   /*!< tamper interrupt reset */
+#define BKP_TPCS_TPIE                   BIT(2)                   /*!< tamper interrupt enable */
+#define BKP_TPCS_TEF                    BIT(8)                   /*!< tamper event flag */
+#define BKP_TPCS_TIF                    BIT(9)                   /*!< tamper interrupt flag */
+
+/* constants definitions */
+/* BKP data register number */
+typedef enum 
+{
+    BKP_DATA_0 = 1,                                              /*!< BKP data register 0 */
+    BKP_DATA_1,                                                  /*!< BKP data register 1 */
+    BKP_DATA_2,                                                  /*!< BKP data register 2 */
+    BKP_DATA_3,                                                  /*!< BKP data register 3 */
+    BKP_DATA_4,                                                  /*!< BKP data register 4 */
+    BKP_DATA_5,                                                  /*!< BKP data register 5 */
+    BKP_DATA_6,                                                  /*!< BKP data register 6 */
+    BKP_DATA_7,                                                  /*!< BKP data register 7 */
+    BKP_DATA_8,                                                  /*!< BKP data register 8 */
+    BKP_DATA_9,                                                  /*!< BKP data register 9 */
+    BKP_DATA_10,                                                 /*!< BKP data register 10 */
+    BKP_DATA_11,                                                 /*!< BKP data register 11 */
+    BKP_DATA_12,                                                 /*!< BKP data register 12 */
+    BKP_DATA_13,                                                 /*!< BKP data register 13 */
+    BKP_DATA_14,                                                 /*!< BKP data register 14 */
+    BKP_DATA_15,                                                 /*!< BKP data register 15 */
+    BKP_DATA_16,                                                 /*!< BKP data register 16 */
+    BKP_DATA_17,                                                 /*!< BKP data register 17 */
+    BKP_DATA_18,                                                 /*!< BKP data register 18 */
+    BKP_DATA_19,                                                 /*!< BKP data register 19 */
+    BKP_DATA_20,                                                 /*!< BKP data register 20 */
+    BKP_DATA_21,                                                 /*!< BKP data register 21 */
+    BKP_DATA_22,                                                 /*!< BKP data register 22 */
+    BKP_DATA_23,                                                 /*!< BKP data register 23 */
+    BKP_DATA_24,                                                 /*!< BKP data register 24 */
+    BKP_DATA_25,                                                 /*!< BKP data register 25 */
+    BKP_DATA_26,                                                 /*!< BKP data register 26 */
+    BKP_DATA_27,                                                 /*!< BKP data register 27 */
+    BKP_DATA_28,                                                 /*!< BKP data register 28 */
+    BKP_DATA_29,                                                 /*!< BKP data register 29 */
+    BKP_DATA_30,                                                 /*!< BKP data register 30 */
+    BKP_DATA_31,                                                 /*!< BKP data register 31 */
+    BKP_DATA_32,                                                 /*!< BKP data register 32 */
+    BKP_DATA_33,                                                 /*!< BKP data register 33 */
+    BKP_DATA_34,                                                 /*!< BKP data register 34 */
+    BKP_DATA_35,                                                 /*!< BKP data register 35 */
+    BKP_DATA_36,                                                 /*!< BKP data register 36 */
+    BKP_DATA_37,                                                 /*!< BKP data register 37 */
+    BKP_DATA_38,                                                 /*!< BKP data register 38 */
+    BKP_DATA_39,                                                 /*!< BKP data register 39 */
+    BKP_DATA_40,                                                 /*!< BKP data register 40 */
+    BKP_DATA_41,                                                 /*!< BKP data register 41 */
+}bkp_data_register_enum;
+
+/* BKP register */
+#define BKP_DATA0_9(number)             REG16((BKP) + 0x04U + (number) * 0x04U)
+#define BKP_DATA10_41(number)           REG16((BKP) + 0x40U + ((number)-10U) * 0x04U)
+
+/* get data of BKP data register */
+#define BKP_DATA_GET(regval)            GET_BITS((uint32_t)(regval), 0, 15)
+
+/* RTC clock calibration value */
+#define OCTL_RCCV(regval)               (BITS(0,6) & ((uint32_t)(regval) << 0))
+
+/* RTC output selection */
+#define RTC_OUTPUT_ALARM_PULSE          ((uint16_t)0x0000U)      /*!< RTC alarm pulse is selected as the RTC output */
+#define RTC_OUTPUT_SECOND_PULSE         ((uint16_t)0x0200U)      /*!< RTC second pulse is selected as the RTC output */
+
+/* tamper pin active level */
+#define TAMPER_PIN_ACTIVE_HIGH          ((uint16_t)0x0000U)      /*!< the tamper pin is active high */
+#define TAMPER_PIN_ACTIVE_LOW           ((uint16_t)0x0002U)      /*!< the tamper pin is active low */
+
+/* tamper flag */
+#define BKP_FLAG_TAMPER                 BKP_TPCS_TEF             /*!< tamper event flag */
+
+/* tamper interrupt flag */
+#define BKP_INT_FLAG_TAMPER             BKP_TPCS_TIF             /*!< tamper interrupt flag */
+/* function declarations */
+/* reset BKP registers */
+void bkp_deinit(void);
+/* write BKP data register */
+void bkp_data_write(bkp_data_register_enum register_number, uint16_t data);
+/* read BKP data register */
+uint16_t bkp_data_read(bkp_data_register_enum register_number);
+
+/* RTC related functions */
+/* enable RTC clock calibration output */
+void bkp_rtc_calibration_output_enable(void);
+/* disable RTC clock calibration output */
+void bkp_rtc_calibration_output_disable(void);
+/* enable RTC alarm or second signal output */
+void bkp_rtc_signal_output_enable(void);
+/* disable RTC alarm or second signal output */
+void bkp_rtc_signal_output_disable(void);
+/* select RTC output */
+void bkp_rtc_output_select(uint16_t outputsel);
+/* set RTC clock calibration value */
+void bkp_rtc_calibration_value_set(uint8_t value);
+
+/* tamper pin related functions */
+/* enable tamper pin detection */
+void bkp_tamper_detection_enable(void);
+/* disable tamper pin detection */
+void bkp_tamper_detection_disable(void);
+/* set tamper pin active level */
+void bkp_tamper_active_level_set(uint16_t level);
+
+/* interrupt & flag functions */
+/* enable tamper interrupt */
+void bkp_interrupt_enable(void);
+/* disable tamper interrupt */
+void bkp_interrupt_disable(void);
+/* get tamper flag state */
+FlagStatus bkp_flag_get(void);
+/* clear tamper flag state */
+void bkp_flag_clear(void);
+/* get tamper interrupt flag state */
+FlagStatus bkp_interrupt_flag_get(void);
+/* clear tamper interrupt flag state */
+void bkp_interrupt_flag_clear(void);
+
+#endif /* GD32F10X_BKP_H */

+ 759 - 0
Library/Include/gd32f10x_can.h

@@ -0,0 +1,759 @@
+/*!
+    \file    gd32f10x_can.h
+    \brief   definitions for the CAN
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-11-27, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+    \version 2021-07-21, V2.2.1, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10x_CAN_H
+#define GD32F10x_CAN_H
+
+#include "gd32f10x.h"
+
+/* CAN definitions */
+#define CAN0                               CAN_BASE                      /*!< CAN0 base address */
+#define CAN1                               (CAN0 + 0x00000400U)          /*!< CAN1 base address */
+
+/* registers definitions */
+#define CAN_CTL(canx)                      REG32((canx) + 0x00U)         /*!< CAN control register */
+#define CAN_STAT(canx)                     REG32((canx) + 0x04U)         /*!< CAN status register */
+#define CAN_TSTAT(canx)                    REG32((canx) + 0x08U)         /*!< CAN transmit status register*/
+#define CAN_RFIFO0(canx)                   REG32((canx) + 0x0CU)         /*!< CAN receive FIFO0 register */
+#define CAN_RFIFO1(canx)                   REG32((canx) + 0x10U)         /*!< CAN receive FIFO1 register */
+#define CAN_INTEN(canx)                    REG32((canx) + 0x14U)         /*!< CAN interrupt enable register */
+#define CAN_ERR(canx)                      REG32((canx) + 0x18U)         /*!< CAN error register */
+#define CAN_BT(canx)                       REG32((canx) + 0x1CU)         /*!< CAN bit timing register */
+#define CAN_TMI0(canx)                     REG32((canx) + 0x180U)        /*!< CAN transmit mailbox0 identifier register */
+#define CAN_TMP0(canx)                     REG32((canx) + 0x184U)        /*!< CAN transmit mailbox0 property register */
+#define CAN_TMDATA00(canx)                 REG32((canx) + 0x188U)        /*!< CAN transmit mailbox0 data0 register */
+#define CAN_TMDATA10(canx)                 REG32((canx) + 0x18CU)        /*!< CAN transmit mailbox0 data1 register */
+#define CAN_TMI1(canx)                     REG32((canx) + 0x190U)        /*!< CAN transmit mailbox1 identifier register */
+#define CAN_TMP1(canx)                     REG32((canx) + 0x194U)        /*!< CAN transmit mailbox1 property register */
+#define CAN_TMDATA01(canx)                 REG32((canx) + 0x198U)        /*!< CAN transmit mailbox1 data0 register */
+#define CAN_TMDATA11(canx)                 REG32((canx) + 0x19CU)        /*!< CAN transmit mailbox1 data1 register */
+#define CAN_TMI2(canx)                     REG32((canx) + 0x1A0U)        /*!< CAN transmit mailbox2 identifier register */
+#define CAN_TMP2(canx)                     REG32((canx) + 0x1A4U)        /*!< CAN transmit mailbox2 property register */
+#define CAN_TMDATA02(canx)                 REG32((canx) + 0x1A8U)        /*!< CAN transmit mailbox2 data0 register */
+#define CAN_TMDATA12(canx)                 REG32((canx) + 0x1ACU)        /*!< CAN transmit mailbox2 data1 register */
+#define CAN_RFIFOMI0(canx)                 REG32((canx) + 0x1B0U)        /*!< CAN receive FIFO0 mailbox identifier register */
+#define CAN_RFIFOMP0(canx)                 REG32((canx) + 0x1B4U)        /*!< CAN receive FIFO0 mailbox property register */
+#define CAN_RFIFOMDATA00(canx)             REG32((canx) + 0x1B8U)        /*!< CAN receive FIFO0 mailbox data0 register */
+#define CAN_RFIFOMDATA10(canx)             REG32((canx) + 0x1BCU)        /*!< CAN receive FIFO0 mailbox data1 register */
+#define CAN_RFIFOMI1(canx)                 REG32((canx) + 0x1C0U)        /*!< CAN receive FIFO1 mailbox identifier register */
+#define CAN_RFIFOMP1(canx)                 REG32((canx) + 0x1C4U)        /*!< CAN receive FIFO1 mailbox property register */
+#define CAN_RFIFOMDATA01(canx)             REG32((canx) + 0x1C8U)        /*!< CAN receive FIFO1 mailbox data0 register */
+#define CAN_RFIFOMDATA11(canx)             REG32((canx) + 0x1CCU)        /*!< CAN receive FIFO1 mailbox data1 register */
+#define CAN_FCTL(canx)                     REG32((canx) + 0x200U)        /*!< CAN filter control register */
+#define CAN_FMCFG(canx)                    REG32((canx) + 0x204U)        /*!< CAN filter mode register */
+#define CAN_FSCFG(canx)                    REG32((canx) + 0x20CU)        /*!< CAN filter scale register */
+#define CAN_FAFIFO(canx)                   REG32((canx) + 0x214U)        /*!< CAN filter associated FIFO register */
+#define CAN_FW(canx)                       REG32((canx) + 0x21CU)        /*!< CAN filter working register */
+#define CAN_F0DATA0(canx)                  REG32((canx) + 0x240U)        /*!< CAN filter 0 data 0 register */
+#define CAN_F1DATA0(canx)                  REG32((canx) + 0x248U)        /*!< CAN filter 1 data 0 register */
+#define CAN_F2DATA0(canx)                  REG32((canx) + 0x250U)        /*!< CAN filter 2 data 0 register */
+#define CAN_F3DATA0(canx)                  REG32((canx) + 0x258U)        /*!< CAN filter 3 data 0 register */
+#define CAN_F4DATA0(canx)                  REG32((canx) + 0x260U)        /*!< CAN filter 4 data 0 register */
+#define CAN_F5DATA0(canx)                  REG32((canx) + 0x268U)        /*!< CAN filter 5 data 0 register */
+#define CAN_F6DATA0(canx)                  REG32((canx) + 0x270U)        /*!< CAN filter 6 data 0 register */
+#define CAN_F7DATA0(canx)                  REG32((canx) + 0x278U)        /*!< CAN filter 7 data 0 register */
+#define CAN_F8DATA0(canx)                  REG32((canx) + 0x280U)        /*!< CAN filter 8 data 0 register */
+#define CAN_F9DATA0(canx)                  REG32((canx) + 0x288U)        /*!< CAN filter 9 data 0 register */
+#define CAN_F10DATA0(canx)                 REG32((canx) + 0x290U)        /*!< CAN filter 10 data 0 register */
+#define CAN_F11DATA0(canx)                 REG32((canx) + 0x298U)        /*!< CAN filter 11 data 0 register */
+#define CAN_F12DATA0(canx)                 REG32((canx) + 0x2A0U)        /*!< CAN filter 12 data 0 register */
+#define CAN_F13DATA0(canx)                 REG32((canx) + 0x2A8U)        /*!< CAN filter 13 data 0 register */
+#define CAN_F14DATA0(canx)                 REG32((canx) + 0x2B0U)        /*!< CAN filter 14 data 0 register */
+#define CAN_F15DATA0(canx)                 REG32((canx) + 0x2B8U)        /*!< CAN filter 15 data 0 register */
+#define CAN_F16DATA0(canx)                 REG32((canx) + 0x2C0U)        /*!< CAN filter 16 data 0 register */
+#define CAN_F17DATA0(canx)                 REG32((canx) + 0x2C8U)        /*!< CAN filter 17 data 0 register */
+#define CAN_F18DATA0(canx)                 REG32((canx) + 0x2D0U)        /*!< CAN filter 18 data 0 register */
+#define CAN_F19DATA0(canx)                 REG32((canx) + 0x2D8U)        /*!< CAN filter 19 data 0 register */
+#define CAN_F20DATA0(canx)                 REG32((canx) + 0x2E0U)        /*!< CAN filter 20 data 0 register */
+#define CAN_F21DATA0(canx)                 REG32((canx) + 0x2E8U)        /*!< CAN filter 21 data 0 register */
+#define CAN_F22DATA0(canx)                 REG32((canx) + 0x2F0U)        /*!< CAN filter 22 data 0 register */
+#define CAN_F23DATA0(canx)                 REG32((canx) + 0x3F8U)        /*!< CAN filter 23 data 0 register */
+#define CAN_F24DATA0(canx)                 REG32((canx) + 0x300U)        /*!< CAN filter 24 data 0 register */
+#define CAN_F25DATA0(canx)                 REG32((canx) + 0x308U)        /*!< CAN filter 25 data 0 register */
+#define CAN_F26DATA0(canx)                 REG32((canx) + 0x310U)        /*!< CAN filter 26 data 0 register */
+#define CAN_F27DATA0(canx)                 REG32((canx) + 0x318U)        /*!< CAN filter 27 data 0 register */
+#define CAN_F0DATA1(canx)                  REG32((canx) + 0x244U)        /*!< CAN filter 0 data 1 register */
+#define CAN_F1DATA1(canx)                  REG32((canx) + 0x24CU)        /*!< CAN filter 1 data 1 register */
+#define CAN_F2DATA1(canx)                  REG32((canx) + 0x254U)        /*!< CAN filter 2 data 1 register */
+#define CAN_F3DATA1(canx)                  REG32((canx) + 0x25CU)        /*!< CAN filter 3 data 1 register */
+#define CAN_F4DATA1(canx)                  REG32((canx) + 0x264U)        /*!< CAN filter 4 data 1 register */
+#define CAN_F5DATA1(canx)                  REG32((canx) + 0x26CU)        /*!< CAN filter 5 data 1 register */
+#define CAN_F6DATA1(canx)                  REG32((canx) + 0x274U)        /*!< CAN filter 6 data 1 register */
+#define CAN_F7DATA1(canx)                  REG32((canx) + 0x27CU)        /*!< CAN filter 7 data 1 register */
+#define CAN_F8DATA1(canx)                  REG32((canx) + 0x284U)        /*!< CAN filter 8 data 1 register */
+#define CAN_F9DATA1(canx)                  REG32((canx) + 0x28CU)        /*!< CAN filter 9 data 1 register */
+#define CAN_F10DATA1(canx)                 REG32((canx) + 0x294U)        /*!< CAN filter 10 data 1 register */
+#define CAN_F11DATA1(canx)                 REG32((canx) + 0x29CU)        /*!< CAN filter 11 data 1 register */
+#define CAN_F12DATA1(canx)                 REG32((canx) + 0x2A4U)        /*!< CAN filter 12 data 1 register */
+#define CAN_F13DATA1(canx)                 REG32((canx) + 0x2ACU)        /*!< CAN filter 13 data 1 register */
+#define CAN_F14DATA1(canx)                 REG32((canx) + 0x2B4U)        /*!< CAN filter 14 data 1 register */
+#define CAN_F15DATA1(canx)                 REG32((canx) + 0x2BCU)        /*!< CAN filter 15 data 1 register */
+#define CAN_F16DATA1(canx)                 REG32((canx) + 0x2C4U)        /*!< CAN filter 16 data 1 register */
+#define CAN_F17DATA1(canx)                 REG32((canx) + 0x24CU)        /*!< CAN filter 17 data 1 register */
+#define CAN_F18DATA1(canx)                 REG32((canx) + 0x2D4U)        /*!< CAN filter 18 data 1 register */
+#define CAN_F19DATA1(canx)                 REG32((canx) + 0x2DCU)        /*!< CAN filter 19 data 1 register */
+#define CAN_F20DATA1(canx)                 REG32((canx) + 0x2E4U)        /*!< CAN filter 20 data 1 register */
+#define CAN_F21DATA1(canx)                 REG32((canx) + 0x2ECU)        /*!< CAN filter 21 data 1 register */
+#define CAN_F22DATA1(canx)                 REG32((canx) + 0x2F4U)        /*!< CAN filter 22 data 1 register */
+#define CAN_F23DATA1(canx)                 REG32((canx) + 0x2FCU)        /*!< CAN filter 23 data 1 register */
+#define CAN_F24DATA1(canx)                 REG32((canx) + 0x304U)        /*!< CAN filter 24 data 1 register */
+#define CAN_F25DATA1(canx)                 REG32((canx) + 0x30CU)        /*!< CAN filter 25 data 1 register */
+#define CAN_F26DATA1(canx)                 REG32((canx) + 0x314U)        /*!< CAN filter 26 data 1 register */
+#define CAN_F27DATA1(canx)                 REG32((canx) + 0x31CU)        /*!< CAN filter 27 data 1 register */
+
+/* CAN transmit mailbox bank */
+#define CAN_TMI(canx, bank)                REG32((canx) + 0x180U + ((bank) * 0x10U))        /*!< CAN transmit mailbox identifier register */
+#define CAN_TMP(canx, bank)                REG32((canx) + 0x184U + ((bank) * 0x10U))        /*!< CAN transmit mailbox property register */
+#define CAN_TMDATA0(canx, bank)            REG32((canx) + 0x188U + ((bank) * 0x10U))        /*!< CAN transmit mailbox data0 register */
+#define CAN_TMDATA1(canx, bank)            REG32((canx) + 0x18CU + ((bank) * 0x10U))        /*!< CAN transmit mailbox data1 register */
+
+/* CAN filter bank */
+#define CAN_FDATA0(canx, bank)             REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U)  /*!< CAN filter data 0 register */
+#define CAN_FDATA1(canx, bank)             REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U)  /*!< CAN filter data 1 register */
+
+/* CAN receive fifo mailbox bank */
+#define CAN_RFIFOMI(canx, bank)            REG32((canx) + 0x1B0U + ((bank) * 0x10U))        /*!< CAN receive FIFO mailbox identifier register */
+#define CAN_RFIFOMP(canx, bank)            REG32((canx) + 0x1B4U + ((bank) * 0x10U))        /*!< CAN receive FIFO mailbox property register */
+#define CAN_RFIFOMDATA0(canx, bank)        REG32((canx) + 0x1B8U + ((bank) * 0x10U))        /*!< CAN receive FIFO mailbox data0 register */
+#define CAN_RFIFOMDATA1(canx, bank)        REG32((canx) + 0x1BCU + ((bank) * 0x10U))        /*!< CAN receive FIFO mailbox data1 register */
+
+/* bits definitions */
+/* CAN_CTL */
+#define CAN_CTL_IWMOD                      BIT(0)                       /*!< initial working mode */
+#define CAN_CTL_SLPWMOD                    BIT(1)                       /*!< sleep working mode */
+#define CAN_CTL_TFO                        BIT(2)                       /*!< transmit FIFO order */
+#define CAN_CTL_RFOD                       BIT(3)                       /*!< receive FIFO overwrite disable */
+#define CAN_CTL_ARD                        BIT(4)                       /*!< automatic retransmission disable */
+#define CAN_CTL_AWU                        BIT(5)                       /*!< automatic wakeup */
+#define CAN_CTL_ABOR                       BIT(6)                       /*!< automatic bus-off recovery */
+#define CAN_CTL_TTC                        BIT(7)                       /*!< time triggered communication */
+#define CAN_CTL_SWRST                      BIT(15)                      /*!< CAN software reset */
+#define CAN_CTL_DFZ                        BIT(16)                      /*!< CAN debug freeze */
+
+/* CAN_STAT */
+#define CAN_STAT_IWS                       BIT(0)                       /*!< initial working state */
+#define CAN_STAT_SLPWS                     BIT(1)                       /*!< sleep working state */
+#define CAN_STAT_ERRIF                     BIT(2)                       /*!< error interrupt flag*/
+#define CAN_STAT_WUIF                      BIT(3)                       /*!< status change interrupt flag of wakeup from sleep working mode */
+#define CAN_STAT_SLPIF                     BIT(4)                       /*!< status change interrupt flag of sleep working mode entering */
+#define CAN_STAT_TS                        BIT(8)                       /*!< transmitting state */
+#define CAN_STAT_RS                        BIT(9)                       /*!< receiving state */
+#define CAN_STAT_LASTRX                    BIT(10)                      /*!< last sample value of rx pin */
+#define CAN_STAT_RXL                       BIT(11)                      /*!< CAN rx signal */
+
+/* CAN_TSTAT */
+#define CAN_TSTAT_MTF0                     BIT(0)                       /*!< mailbox0 transmit finished */
+#define CAN_TSTAT_MTFNERR0                 BIT(1)                       /*!< mailbox0 transmit finished and no error */
+#define CAN_TSTAT_MAL0                     BIT(2)                       /*!< mailbox0 arbitration lost */
+#define CAN_TSTAT_MTE0                     BIT(3)                       /*!< mailbox0 transmit error */
+#define CAN_TSTAT_MST0                     BIT(7)                       /*!< mailbox0 stop transmitting */
+#define CAN_TSTAT_MTF1                     BIT(8)                       /*!< mailbox1 transmit finished */
+#define CAN_TSTAT_MTFNERR1                 BIT(9)                       /*!< mailbox1 transmit finished and no error */
+#define CAN_TSTAT_MAL1                     BIT(10)                      /*!< mailbox1 arbitration lost */
+#define CAN_TSTAT_MTE1                     BIT(11)                      /*!< mailbox1 transmit error */
+#define CAN_TSTAT_MST1                     BIT(15)                      /*!< mailbox1 stop transmitting */
+#define CAN_TSTAT_MTF2                     BIT(16)                      /*!< mailbox2 transmit finished */
+#define CAN_TSTAT_MTFNERR2                 BIT(17)                      /*!< mailbox2 transmit finished and no error */
+#define CAN_TSTAT_MAL2                     BIT(18)                      /*!< mailbox2 arbitration lost */
+#define CAN_TSTAT_MTE2                     BIT(19)                      /*!< mailbox2 transmit error */
+#define CAN_TSTAT_MST2                     BIT(23)                      /*!< mailbox2 stop transmitting */
+#define CAN_TSTAT_NUM                      BITS(24,25)                  /*!< mailbox number */
+#define CAN_TSTAT_TME0                     BIT(26)                      /*!< transmit mailbox0 empty */
+#define CAN_TSTAT_TME1                     BIT(27)                      /*!< transmit mailbox1 empty */
+#define CAN_TSTAT_TME2                     BIT(28)                      /*!< transmit mailbox2 empty */
+#define CAN_TSTAT_TMLS0                    BIT(29)                      /*!< last sending priority flag for mailbox0 */
+#define CAN_TSTAT_TMLS1                    BIT(30)                      /*!< last sending priority flag for mailbox1 */
+#define CAN_TSTAT_TMLS2                    BIT(31)                      /*!< last sending priority flag for mailbox2 */
+
+/* CAN_RFIFO0 */
+#define CAN_RFIFO0_RFL0                    BITS(0,1)                    /*!< receive FIFO0 length */
+#define CAN_RFIFO0_RFF0                    BIT(3)                       /*!< receive FIFO0 full */
+#define CAN_RFIFO0_RFO0                    BIT(4)                       /*!< receive FIFO0 overfull */
+#define CAN_RFIFO0_RFD0                    BIT(5)                       /*!< receive FIFO0 dequeue */
+
+/* CAN_RFIFO1 */
+#define CAN_RFIFO1_RFL1                    BITS(0,1)                    /*!< receive FIFO1 length */
+#define CAN_RFIFO1_RFF1                    BIT(3)                       /*!< receive FIFO1 full */
+#define CAN_RFIFO1_RFO1                    BIT(4)                       /*!< receive FIFO1 overfull */
+#define CAN_RFIFO1_RFD1                    BIT(5)                       /*!< receive FIFO1 dequeue */
+
+/* CAN_INTEN */
+#define CAN_INTEN_TMEIE                    BIT(0)                       /*!< transmit mailbox empty interrupt enable */
+#define CAN_INTEN_RFNEIE0                  BIT(1)                       /*!< receive FIFO0 not empty interrupt enable */
+#define CAN_INTEN_RFFIE0                   BIT(2)                       /*!< receive FIFO0 full interrupt enable */
+#define CAN_INTEN_RFOIE0                   BIT(3)                       /*!< receive FIFO0 overfull interrupt enable */
+#define CAN_INTEN_RFNEIE1                  BIT(4)                       /*!< receive FIFO1 not empty interrupt enable */
+#define CAN_INTEN_RFFIE1                   BIT(5)                       /*!< receive FIFO1 full interrupt enable */
+#define CAN_INTEN_RFOIE1                   BIT(6)                       /*!< receive FIFO1 overfull interrupt enable */
+#define CAN_INTEN_WERRIE                   BIT(8)                       /*!< warning error interrupt enable */
+#define CAN_INTEN_PERRIE                   BIT(9)                       /*!< passive error interrupt enable */
+#define CAN_INTEN_BOIE                     BIT(10)                      /*!< bus-off interrupt enable */
+#define CAN_INTEN_ERRNIE                   BIT(11)                      /*!< error number interrupt enable */
+#define CAN_INTEN_ERRIE                    BIT(15)                      /*!< error interrupt enable */
+#define CAN_INTEN_WIE                      BIT(16)                      /*!< wakeup interrupt enable */
+#define CAN_INTEN_SLPWIE                   BIT(17)                      /*!< sleep working interrupt enable */
+
+/* CAN_ERR */
+#define CAN_ERR_WERR                       BIT(0)                       /*!< warning error */
+#define CAN_ERR_PERR                       BIT(1)                       /*!< passive error */
+#define CAN_ERR_BOERR                      BIT(2)                       /*!< bus-off error */
+#define CAN_ERR_ERRN                       BITS(4,6)                    /*!< error number */
+#define CAN_ERR_TECNT                      BITS(16,23)                  /*!< transmit error count */
+#define CAN_ERR_RECNT                      BITS(24,31)                  /*!< receive error count */
+
+/* CAN_BT */
+#define CAN_BT_BAUDPSC                     BITS(0,9)                    /*!< baudrate prescaler */
+#define CAN_BT_BS1                         BITS(16,19)                  /*!< bit segment 1 */
+#define CAN_BT_BS2                         BITS(20,22)                  /*!< bit segment 2 */
+#define CAN_BT_SJW                         BITS(24,25)                  /*!< resynchronization jump width */
+#define CAN_BT_LCMOD                       BIT(30)                      /*!< loopback communication mode */
+#define CAN_BT_SCMOD                       BIT(31)                      /*!< silent communication mode */
+
+/* CAN_TMIx */
+#define CAN_TMI_TEN                        BIT(0)                       /*!< transmit enable */
+#define CAN_TMI_FT                         BIT(1)                       /*!< frame type */
+#define CAN_TMI_FF                         BIT(2)                       /*!< frame format */
+#define CAN_TMI_EFID                       BITS(3,31)                   /*!< the frame identifier */
+#define CAN_TMI_SFID                       BITS(21,31)                  /*!< the frame identifier */
+
+/* CAN_TMPx */
+#define CAN_TMP_DLENC                      BITS(0,3)                    /*!< data length code */
+#define CAN_TMP_TSEN                       BIT(8)                       /*!< time stamp enable */
+#define CAN_TMP_TS                         BITS(16,31)                  /*!< time stamp */
+
+/* CAN_TMDATA0x */
+#define CAN_TMDATA0_DB0                    BITS(0,7)                    /*!< transmit data byte 0 */
+#define CAN_TMDATA0_DB1                    BITS(8,15)                   /*!< transmit data byte 1 */
+#define CAN_TMDATA0_DB2                    BITS(16,23)                  /*!< transmit data byte 2 */
+#define CAN_TMDATA0_DB3                    BITS(24,31)                  /*!< transmit data byte 3 */
+
+/* CAN_TMDATA1x */
+#define CAN_TMDATA1_DB4                    BITS(0,7)                    /*!< transmit data byte 4 */
+#define CAN_TMDATA1_DB5                    BITS(8,15)                   /*!< transmit data byte 5 */
+#define CAN_TMDATA1_DB6                    BITS(16,23)                  /*!< transmit data byte 6 */
+#define CAN_TMDATA1_DB7                    BITS(24,31)                  /*!< transmit data byte 7 */
+
+/* CAN_RFIFOMIx */
+#define CAN_RFIFOMI_FT                     BIT(1)                       /*!< frame type */
+#define CAN_RFIFOMI_FF                     BIT(2)                       /*!< frame format */
+#define CAN_RFIFOMI_EFID                   BITS(3,31)                   /*!< the frame identifier */
+#define CAN_RFIFOMI_SFID                   BITS(21,31)                  /*!< the frame identifier */
+
+/* CAN_RFIFOMPx */
+#define CAN_RFIFOMP_DLENC                  BITS(0,3)                    /*!< receive data length code */
+#define CAN_RFIFOMP_FI                     BITS(8,15)                   /*!< filter index */
+#define CAN_RFIFOMP_TS                     BITS(16,31)                  /*!< time stamp */
+
+/* CAN_RFIFOMDATA0x */
+#define CAN_RFIFOMDATA0_DB0                BITS(0,7)                    /*!< receive data byte 0 */
+#define CAN_RFIFOMDATA0_DB1                BITS(8,15)                   /*!< receive data byte 1 */
+#define CAN_RFIFOMDATA0_DB2                BITS(16,23)                  /*!< receive data byte 2 */
+#define CAN_RFIFOMDATA0_DB3                BITS(24,31)                  /*!< receive data byte 3 */
+
+/* CAN_RFIFOMDATA1x */
+#define CAN_RFIFOMDATA1_DB4                BITS(0,7)                    /*!< receive data byte 4 */
+#define CAN_RFIFOMDATA1_DB5                BITS(8,15)                   /*!< receive data byte 5 */
+#define CAN_RFIFOMDATA1_DB6                BITS(16,23)                  /*!< receive data byte 6 */
+#define CAN_RFIFOMDATA1_DB7                BITS(24,31)                  /*!< receive data byte 7 */
+
+/* CAN_FCTL */
+#define CAN_FCTL_FLD                       BIT(0)                       /*!< filter lock disable */
+#define CAN_FCTL_HBC1F                     BITS(8,13)                   /*!< header bank of CAN1 filter */
+
+/* CAN_FMCFG */
+#define CAN_FMCFG_FMOD(regval)             BIT(regval)                  /*!< filter mode, list or mask*/
+
+/* CAN_FSCFG */
+#define CAN_FSCFG_FS(regval)               BIT(regval)                  /*!< filter scale, 32 bits or 16 bits*/
+
+/* CAN_FAFIFO */
+#define CAN_FAFIFOR_FAF(regval)            BIT(regval)                  /*!< filter associated with FIFO */
+
+/* CAN_FW */
+#define CAN_FW_FW(regval)                  BIT(regval)                  /*!< filter working */
+
+/* CAN_FxDATAy */
+#define CAN_FDATA_FD(regval)               BIT(regval)                  /*!< filter data */
+
+/* constants definitions */
+/* define the CAN bit position and its register index offset */
+#define CAN_REGIDX_BIT(regidx, bitpos)              (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define CAN_REG_VAL(canx, offset)                   (REG32((canx) + ((uint32_t)(offset) >> 6)))
+#define CAN_BIT_POS(val)                            ((uint32_t)(val) & 0x1FU)
+
+#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1)   (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1))
+#define CAN_REG_VALS(canx, offset)                  (REG32((canx) + ((uint32_t)(offset) >> 12)))
+#define CAN_BIT_POS0(val)                           (((uint32_t)(val) >> 6) & 0x1FU)
+#define CAN_BIT_POS1(val)                           ((uint32_t)(val) & 0x1FU)
+
+/* register offset */
+#define STAT_REG_OFFSET                    ((uint8_t)0x04U)             /*!< STAT register offset */
+#define TSTAT_REG_OFFSET                   ((uint8_t)0x08U)             /*!< TSTAT register offset */
+#define RFIFO0_REG_OFFSET                  ((uint8_t)0x0CU)             /*!< RFIFO0 register offset */
+#define RFIFO1_REG_OFFSET                  ((uint8_t)0x10U)             /*!< RFIFO1 register offset */
+#define ERR_REG_OFFSET                     ((uint8_t)0x18U)             /*!< ERR register offset */
+
+/* CAN flags */
+typedef enum
+{
+    /* flags in STAT register */
+    CAN_FLAG_RXL      = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U),           /*!< RX level */ 
+    CAN_FLAG_LASTRX   = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U),           /*!< last sample value of RX pin */ 
+    CAN_FLAG_RS       = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U),            /*!< receiving state */ 
+    CAN_FLAG_TS       = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U),            /*!< transmitting state */ 
+    CAN_FLAG_SLPIF    = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U),            /*!< status change flag of entering sleep working mode */ 
+    CAN_FLAG_WUIF     = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U),            /*!< status change flag of wakeup from sleep working mode */ 
+    CAN_FLAG_ERRIF    = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U),            /*!< error flag */ 
+    CAN_FLAG_SLPWS    = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U),            /*!< sleep working state */ 
+    CAN_FLAG_IWS      = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U),            /*!< initial working state */ 
+    /* flags in TSTAT register */
+    CAN_FLAG_TMLS2    = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U),          /*!< transmit mailbox 2 last sending in Tx FIFO */ 
+    CAN_FLAG_TMLS1    = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U),          /*!< transmit mailbox 1 last sending in Tx FIFO */ 
+    CAN_FLAG_TMLS0    = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U),          /*!< transmit mailbox 0 last sending in Tx FIFO */ 
+    CAN_FLAG_TME2     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U),          /*!< transmit mailbox 2 empty */ 
+    CAN_FLAG_TME1     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U),          /*!< transmit mailbox 1 empty */ 
+    CAN_FLAG_TME0     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U),          /*!< transmit mailbox 0 empty */ 
+    CAN_FLAG_MTE2     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U),          /*!< mailbox 2 transmit error */ 
+    CAN_FLAG_MTE1     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U),          /*!< mailbox 1 transmit error */ 
+    CAN_FLAG_MTE0     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U),           /*!< mailbox 0 transmit error */ 
+    CAN_FLAG_MAL2     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U),          /*!< mailbox 2 arbitration lost */ 
+    CAN_FLAG_MAL1     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U),          /*!< mailbox 1 arbitration lost */ 
+    CAN_FLAG_MAL0     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U),           /*!< mailbox 0 arbitration lost */ 
+    CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U),          /*!< mailbox 2 transmit finished with no error */ 
+    CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U),           /*!< mailbox 1 transmit finished with no error */ 
+    CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U),           /*!< mailbox 0 transmit finished with no error */ 
+    CAN_FLAG_MTF2     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U),          /*!< mailbox 2 transmit finished */ 
+    CAN_FLAG_MTF1     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U),           /*!< mailbox 1 transmit finished */ 
+    CAN_FLAG_MTF0     = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U),           /*!< mailbox 0 transmit finished */ 
+    /* flags in RFIFO0 register */
+    CAN_FLAG_RFO0     = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U),          /*!< receive FIFO0 overfull */ 
+    CAN_FLAG_RFF0     = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U),          /*!< receive FIFO0 full */ 
+    /* flags in RFIFO1 register */
+    CAN_FLAG_RFO1     = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U),          /*!< receive FIFO1 overfull */ 
+    CAN_FLAG_RFF1     = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U),          /*!< receive FIFO1 full */ 
+    /* flags in ERR register */
+    CAN_FLAG_BOERR    = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U),             /*!< bus-off error */ 
+    CAN_FLAG_PERR     = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U),             /*!< passive error */ 
+    CAN_FLAG_WERR     = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U),             /*!< warning error */ 
+}can_flag_enum;
+
+/* CAN interrupt flags */
+typedef enum
+{
+    /* interrupt flags in STAT register */
+    CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U),     /*!< status change interrupt flag of sleep working mode entering */ 
+    CAN_INT_FLAG_WUIF  = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16),      /*!< status change interrupt flag of wakeup from sleep working mode */ 
+    CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15),      /*!< error interrupt flag */ 
+    /* interrupt flags in TSTAT register */
+    CAN_INT_FLAG_MTF2  = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U),    /*!< mailbox 2 transmit finished interrupt flag */
+    CAN_INT_FLAG_MTF1  = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U),     /*!< mailbox 1 transmit finished interrupt flag */
+    CAN_INT_FLAG_MTF0  = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U),     /*!< mailbox 0 transmit finished interrupt flag */
+    /* interrupt flags in RFIFO0 register */
+    CAN_INT_FLAG_RFO0  = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U),    /*!< receive FIFO0 overfull interrupt flag */
+    CAN_INT_FLAG_RFF0  = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U),    /*!< receive FIFO0 full interrupt flag */
+    CAN_INT_FLAG_RFL0  = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U),    /*!< receive FIFO0 not empty interrupt flag */
+    /* interrupt flags in RFIFO0 register */
+    CAN_INT_FLAG_RFO1  = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U),    /*!< receive FIFO1 overfull interrupt flag */
+    CAN_INT_FLAG_RFF1  = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U),    /*!< receive FIFO1 full interrupt flag */
+    CAN_INT_FLAG_RFL1  = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U),    /*!< receive FIFO1 not empty interrupt flag */
+    /* interrupt flags in ERR register */
+    CAN_INT_FLAG_ERRN  = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U),      /*!< error number interrupt flag */ 
+    CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U),      /*!< bus-off error interrupt flag */ 
+    CAN_INT_FLAG_PERR  = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U),       /*!< passive error interrupt flag */ 
+    CAN_INT_FLAG_WERR  = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U),       /*!< warning error interrupt flag */ 
+}can_interrupt_flag_enum;
+
+/* CAN initiliaze parameters structure */
+typedef struct
+{
+    uint8_t working_mode;                                               /*!< CAN working mode */ 
+    uint8_t resync_jump_width;                                          /*!< CAN resynchronization jump width */
+    uint8_t time_segment_1;                                             /*!< time segment 1 */
+    uint8_t time_segment_2;                                             /*!< time segment 2 */
+    ControlStatus time_triggered;                                       /*!< time triggered communication mode */
+    ControlStatus auto_bus_off_recovery;                                /*!< automatic bus-off recovery */
+    ControlStatus auto_wake_up;                                         /*!< automatic wake-up mode */
+    ControlStatus no_auto_retrans;                                      /*!< automatic retransmission mode disable */
+    ControlStatus rec_fifo_overwrite;                                   /*!< receive FIFO overwrite mode */
+    ControlStatus trans_fifo_order;                                     /*!< transmit FIFO order */
+    uint16_t prescaler;                                                 /*!< baudrate prescaler */
+}can_parameter_struct;
+
+/* CAN transmit message structure */
+typedef struct
+{
+    uint32_t tx_sfid;                                                   /*!< standard format frame identifier */
+    uint32_t tx_efid;                                                   /*!< extended format frame identifier */
+    uint8_t tx_ff;                                                      /*!< format of frame, standard or extended format */
+    uint8_t tx_ft;                                                      /*!< type of frame, data or remote */
+    uint8_t tx_dlen;                                                    /*!< data length */
+    uint8_t tx_data[8];                                                 /*!< transmit data */
+}can_trasnmit_message_struct;
+
+/* CAN receive message structure */
+typedef struct
+{
+    uint32_t rx_sfid;                                                   /*!< standard format frame identifier */
+    uint32_t rx_efid;                                                   /*!< extended format frame identifier */
+    uint8_t rx_ff;                                                      /*!< format of frame, standard or extended format */
+    uint8_t rx_ft;                                                      /*!< type of frame, data or remote */
+    uint8_t rx_dlen;                                                    /*!< data length */
+    uint8_t rx_data[8];                                                 /*!< receive data */
+    uint8_t rx_fi;                                                      /*!< filtering index */
+} can_receive_message_struct;
+
+/* CAN filter parameters structure */
+typedef struct
+{
+    uint16_t filter_list_high;                                          /*!< filter list number high bits*/
+    uint16_t filter_list_low;                                           /*!< filter list number low bits */
+    uint16_t filter_mask_high;                                          /*!< filter mask number high bits */
+    uint16_t filter_mask_low;                                           /*!< filter mask number low bits */
+    uint16_t filter_fifo_number;                                        /*!< receive FIFO associated with the filter */
+    uint16_t filter_number;                                             /*!< filter number */
+    uint16_t filter_mode;                                               /*!< filter mode, list or mask */
+    uint16_t filter_bits;                                               /*!< filter scale */
+    ControlStatus filter_enable;                                        /*!< filter work or not */
+}can_filter_parameter_struct;
+
+/* CAN errors */
+typedef enum
+{
+    CAN_ERROR_NONE = 0,                                                 /*!< no error */
+    CAN_ERROR_FILL,                                                     /*!< fill error */
+    CAN_ERROR_FORMATE,                                                  /*!< format error */
+    CAN_ERROR_ACK,                                                      /*!< ACK error */
+    CAN_ERROR_BITRECESSIVE,                                             /*!< bit recessive error */
+    CAN_ERROR_BITDOMINANTER,                                            /*!< bit dominant error */
+    CAN_ERROR_CRC,                                                      /*!< CRC error */
+    CAN_ERROR_SOFTWARECFG,                                              /*!< software configure */
+}can_error_enum;
+
+/* transmit states */
+typedef enum
+{
+    CAN_TRANSMIT_FAILED = 0U,                                           /*!< CAN transmitted failure */
+    CAN_TRANSMIT_OK = 1U,                                               /*!< CAN transmitted success */
+    CAN_TRANSMIT_PENDING = 2U,                                          /*!< CAN transmitted pending */
+    CAN_TRANSMIT_NOMAILBOX = 4U,                                        /*!< no empty mailbox to be used for CAN */
+}can_transmit_state_enum;
+
+typedef enum
+{
+    CAN_INIT_STRUCT = 0,                                                /* CAN initiliaze parameters struct */
+    CAN_FILTER_STRUCT,                                                  /* CAN filter parameters struct */
+    CAN_TX_MESSAGE_STRUCT,                                              /* CAN transmit message struct */
+    CAN_RX_MESSAGE_STRUCT,                                              /* CAN receive message struct */
+}can_struct_type_enum;
+
+/* CAN baudrate prescaler*/
+#define BT_BAUDPSC(regval)                 (BITS(0,9) & ((uint32_t)(regval) << 0))
+
+/* CAN bit segment 1*/
+#define BT_BS1(regval)                     (BITS(16,19) & ((uint32_t)(regval) << 16))
+
+/* CAN bit segment 2*/
+#define BT_BS2(regval)                     (BITS(20,22) & ((uint32_t)(regval) << 20))
+
+/* CAN resynchronization jump width*/
+#define BT_SJW(regval)                     (BITS(24,25) & ((uint32_t)(regval) << 24))
+
+/* CAN communication mode*/
+#define BT_MODE(regval)                    (BITS(30,31) & ((uint32_t)(regval) << 30))
+
+/* CAN FDATA high 16 bits */
+#define FDATA_MASK_HIGH(regval)            (BITS(16,31) & ((uint32_t)(regval) << 16))
+
+/* CAN FDATA low 16 bits */
+#define FDATA_MASK_LOW(regval)             (BITS(0,15) & ((uint32_t)(regval) << 0))
+
+/* CAN1 filter start bank_number*/
+#define FCTL_HBC1F(regval)                 (BITS(8,13) & ((uint32_t)(regval) << 8))
+
+/* CAN transmit mailbox extended identifier*/
+#define TMI_EFID(regval)                   (BITS(3,31) & ((uint32_t)(regval) << 3))
+
+/* CAN transmit mailbox standard identifier*/
+#define TMI_SFID(regval)                   (BITS(21,31) & ((uint32_t)(regval) << 21))
+
+/* transmit data byte 0 */
+#define TMDATA0_DB0(regval)                (BITS(0,7) & ((uint32_t)(regval) << 0))
+
+/* transmit data byte 1 */
+#define TMDATA0_DB1(regval)                (BITS(8,15) & ((uint32_t)(regval) << 8))
+
+/* transmit data byte 2 */
+#define TMDATA0_DB2(regval)                (BITS(16,23) & ((uint32_t)(regval) << 16))
+
+/* transmit data byte 3 */                 
+#define TMDATA0_DB3(regval)                (BITS(24,31) & ((uint32_t)(regval) << 24))
+
+/* transmit data byte 4 */                 
+#define TMDATA1_DB4(regval)                (BITS(0,7) & ((uint32_t)(regval) << 0))
+
+/* transmit data byte 5 */                 
+#define TMDATA1_DB5(regval)                (BITS(8,15) & ((uint32_t)(regval) << 8))
+
+/* transmit data byte 6 */                 
+#define TMDATA1_DB6(regval)                (BITS(16,23) & ((uint32_t)(regval) << 16))
+
+/* transmit data byte 7 */                 
+#define TMDATA1_DB7(regval)                (BITS(24,31) & ((uint32_t)(regval) << 24))
+
+/* receive mailbox extended identifier*/
+#define GET_RFIFOMI_EFID(regval)           GET_BITS((uint32_t)(regval), 3U, 31U)
+
+/* receive mailbox standrad identifier*/
+#define GET_RFIFOMI_SFID(regval)           GET_BITS((uint32_t)(regval), 21U, 31U)
+
+/* receive data length */
+#define GET_RFIFOMP_DLENC(regval)          GET_BITS((uint32_t)(regval), 0U, 3U)
+
+/* the index of the filter by which the frame is passed */
+#define GET_RFIFOMP_FI(regval)             GET_BITS((uint32_t)(regval), 8U, 15U)
+
+/* receive data byte 0 */
+#define GET_RFIFOMDATA0_DB0(regval)        GET_BITS((uint32_t)(regval), 0U, 7U)
+
+/* receive data byte 1 */
+#define GET_RFIFOMDATA0_DB1(regval)        GET_BITS((uint32_t)(regval), 8U, 15U)
+
+/* receive data byte 2 */
+#define GET_RFIFOMDATA0_DB2(regval)        GET_BITS((uint32_t)(regval), 16U, 23U)
+
+/* receive data byte 3 */
+#define GET_RFIFOMDATA0_DB3(regval)        GET_BITS((uint32_t)(regval), 24U, 31U)
+
+/* receive data byte 4 */
+#define GET_RFIFOMDATA1_DB4(regval)        GET_BITS((uint32_t)(regval), 0U, 7U)
+
+/* receive data byte 5 */
+#define GET_RFIFOMDATA1_DB5(regval)        GET_BITS((uint32_t)(regval), 8U, 15U)
+
+/* receive data byte 6 */
+#define GET_RFIFOMDATA1_DB6(regval)        GET_BITS((uint32_t)(regval), 16U, 23U)
+
+/* receive data byte 7 */
+#define GET_RFIFOMDATA1_DB7(regval)        GET_BITS((uint32_t)(regval), 24U, 31U)
+
+/* error number */        
+#define GET_ERR_ERRN(regval)               GET_BITS((uint32_t)(regval), 4U, 6U)
+
+/* transmit error count */        
+#define GET_ERR_TECNT(regval)              GET_BITS((uint32_t)(regval), 16U, 23U)
+
+/* receive  error count */        
+#define GET_ERR_RECNT(regval)              GET_BITS((uint32_t)(regval), 24U, 31U)
+
+/* CAN errors */
+#define ERR_ERRN(regval)                   (BITS(4,6) & ((uint32_t)(regval) << 4))
+#define CAN_ERRN_0                         ERR_ERRN(0U)                 /*!< no error */
+#define CAN_ERRN_1                         ERR_ERRN(1U)                 /*!< fill error */
+#define CAN_ERRN_2                         ERR_ERRN(2U)                 /*!< format error */
+#define CAN_ERRN_3                         ERR_ERRN(3U)                 /*!< ACK error */
+#define CAN_ERRN_4                         ERR_ERRN(4U)                 /*!< bit recessive error */
+#define CAN_ERRN_5                         ERR_ERRN(5U)                 /*!< bit dominant error */
+#define CAN_ERRN_6                         ERR_ERRN(6U)                 /*!< CRC error */
+#define CAN_ERRN_7                         ERR_ERRN(7U)                 /*!< software error */
+
+#define CAN_STATE_PENDING                  ((uint32_t)0x00000000U)      /*!< CAN pending */
+
+/* CAN communication mode */
+#define CAN_NORMAL_MODE                    ((uint8_t)0x00U)             /*!< normal communication mode */
+#define CAN_LOOPBACK_MODE                  ((uint8_t)0x01U)             /*!< loopback communication mode */
+#define CAN_SILENT_MODE                    ((uint8_t)0x02U)             /*!< silent communication mode */
+#define CAN_SILENT_LOOPBACK_MODE           ((uint8_t)0x03U)             /*!< loopback and silent communication mode */
+
+/* CAN resynchronisation jump width */
+#define CAN_BT_SJW_1TQ                     ((uint8_t)0x00U)             /*!< 1 time quanta */
+#define CAN_BT_SJW_2TQ                     ((uint8_t)0x01U)             /*!< 2 time quanta */
+#define CAN_BT_SJW_3TQ                     ((uint8_t)0x02U)             /*!< 3 time quanta */
+#define CAN_BT_SJW_4TQ                     ((uint8_t)0x03U)             /*!< 4 time quanta */
+
+/* CAN time segment 1 */
+#define CAN_BT_BS1_1TQ                     ((uint8_t)0x00U)             /*!< 1 time quanta */
+#define CAN_BT_BS1_2TQ                     ((uint8_t)0x01U)             /*!< 2 time quanta */
+#define CAN_BT_BS1_3TQ                     ((uint8_t)0x02U)             /*!< 3 time quanta */
+#define CAN_BT_BS1_4TQ                     ((uint8_t)0x03U)             /*!< 4 time quanta */
+#define CAN_BT_BS1_5TQ                     ((uint8_t)0x04U)             /*!< 5 time quanta */
+#define CAN_BT_BS1_6TQ                     ((uint8_t)0x05U)             /*!< 6 time quanta */
+#define CAN_BT_BS1_7TQ                     ((uint8_t)0x06U)             /*!< 7 time quanta */
+#define CAN_BT_BS1_8TQ                     ((uint8_t)0x07U)             /*!< 8 time quanta */
+#define CAN_BT_BS1_9TQ                     ((uint8_t)0x08U)             /*!< 9 time quanta */
+#define CAN_BT_BS1_10TQ                    ((uint8_t)0x09U)             /*!< 10 time quanta */
+#define CAN_BT_BS1_11TQ                    ((uint8_t)0x0AU)             /*!< 11 time quanta */
+#define CAN_BT_BS1_12TQ                    ((uint8_t)0x0BU)             /*!< 12 time quanta */
+#define CAN_BT_BS1_13TQ                    ((uint8_t)0x0CU)             /*!< 13 time quanta */
+#define CAN_BT_BS1_14TQ                    ((uint8_t)0x0DU)             /*!< 14 time quanta */
+#define CAN_BT_BS1_15TQ                    ((uint8_t)0x0EU)             /*!< 15 time quanta */
+#define CAN_BT_BS1_16TQ                    ((uint8_t)0x0FU)             /*!< 16 time quanta */
+
+/* CAN time segment 2 */
+#define CAN_BT_BS2_1TQ                     ((uint8_t)0x00U)             /*!< 1 time quanta */
+#define CAN_BT_BS2_2TQ                     ((uint8_t)0x01U)             /*!< 2 time quanta */
+#define CAN_BT_BS2_3TQ                     ((uint8_t)0x02U)             /*!< 3 time quanta */
+#define CAN_BT_BS2_4TQ                     ((uint8_t)0x03U)             /*!< 4 time quanta */
+#define CAN_BT_BS2_5TQ                     ((uint8_t)0x04U)             /*!< 5 time quanta */
+#define CAN_BT_BS2_6TQ                     ((uint8_t)0x05U)             /*!< 6 time quanta */
+#define CAN_BT_BS2_7TQ                     ((uint8_t)0x06U)             /*!< 7 time quanta */
+#define CAN_BT_BS2_8TQ                     ((uint8_t)0x07U)             /*!< 8 time quanta */
+
+/* CAN mailbox number */
+#define CAN_MAILBOX0                       ((uint8_t)0x00U)             /*!< mailbox0 */
+#define CAN_MAILBOX1                       ((uint8_t)0x01U)             /*!< mailbox1 */
+#define CAN_MAILBOX2                       ((uint8_t)0x02U)             /*!< mailbox2 */
+#define CAN_NOMAILBOX                      ((uint8_t)0x03U)             /*!< no mailbox empty */
+
+/* CAN frame format */
+#define CAN_FF_STANDARD                    ((uint32_t)0x00000000U)      /*!< standard frame */
+#define CAN_FF_EXTENDED                    ((uint32_t)0x00000004U)      /*!< extended frame */
+
+/* CAN receive fifo */
+#define CAN_FIFO0                          ((uint8_t)0x00U)             /*!< receive FIFO0 */
+#define CAN_FIFO1                          ((uint8_t)0x01U)             /*!< receive FIFO1 */
+
+/* frame number of receive fifo */
+#define CAN_RFIF_RFL_MASK                  ((uint32_t)0x00000003U)      /*!< mask for frame number in receive FIFOx */
+
+#define CAN_SFID_MASK                      ((uint32_t)0x000007FFU)      /*!< mask of standard identifier */
+#define CAN_EFID_MASK                      ((uint32_t)0x1FFFFFFFU)      /*!< mask of extended identifier */
+
+/* CAN working mode */
+#define CAN_MODE_INITIALIZE                ((uint8_t)0x01U)             /*!< CAN initialize mode */
+#define CAN_MODE_NORMAL                    ((uint8_t)0x02U)             /*!< CAN normal mode */
+#define CAN_MODE_SLEEP                     ((uint8_t)0x04U)             /*!< CAN sleep mode */
+
+/* filter bits */
+#define CAN_FILTERBITS_16BIT               ((uint8_t)0x00U)             /*!< CAN filter 16 bits */
+#define CAN_FILTERBITS_32BIT               ((uint8_t)0x01U)             /*!< CAN filter 32 bits */
+
+/* filter mode */
+#define CAN_FILTERMODE_MASK                ((uint8_t)0x00U)             /*!< mask mode */
+#define CAN_FILTERMODE_LIST                ((uint8_t)0x01U)             /*!< list mode */
+
+/* filter 16 bits mask */
+#define CAN_FILTER_MASK_16BITS             ((uint32_t)0x0000FFFFU)      /*!< can filter 16 bits mask */
+
+/* frame type */
+#define CAN_FT_DATA                        ((uint32_t)0x00000000U)      /*!< data frame */
+#define CAN_FT_REMOTE                      ((uint32_t)0x00000002U)      /*!< remote frame */
+
+/* CAN timeout */
+#define CAN_TIMEOUT                        ((uint32_t)0x0000FFFFU)      /*!< timeout value */
+
+/* interrupt enable bits */
+#define CAN_INT_TME                        CAN_INTEN_TMEIE              /*!< transmit mailbox empty interrupt enable */
+#define CAN_INT_RFNE0                      CAN_INTEN_RFNEIE0            /*!< receive FIFO0 not empty interrupt enable */
+#define CAN_INT_RFF0                       CAN_INTEN_RFFIE0             /*!< receive FIFO0 full interrupt enable */
+#define CAN_INT_RFO0                       CAN_INTEN_RFOIE0             /*!< receive FIFO0 overfull interrupt enable */
+#define CAN_INT_RFNE1                      CAN_INTEN_RFNEIE1            /*!< receive FIFO1 not empty interrupt enable */
+#define CAN_INT_RFF1                       CAN_INTEN_RFFIE1             /*!< receive FIFO1 full interrupt enable */
+#define CAN_INT_RFO1                       CAN_INTEN_RFOIE1             /*!< receive FIFO1 overfull interrupt enable */
+#define CAN_INT_WERR                       CAN_INTEN_WERRIE             /*!< warning error interrupt enable */
+#define CAN_INT_PERR                       CAN_INTEN_PERRIE             /*!< passive error interrupt enable */
+#define CAN_INT_BO                         CAN_INTEN_BOIE               /*!< bus-off interrupt enable */
+#define CAN_INT_ERRN                       CAN_INTEN_ERRNIE             /*!< error number interrupt enable */
+#define CAN_INT_ERR                        CAN_INTEN_ERRIE              /*!< error interrupt enable */
+#define CAN_INT_WAKEUP                     CAN_INTEN_WIE                /*!< wakeup interrupt enable */
+#define CAN_INT_SLPW                       CAN_INTEN_SLPWIE             /*!< sleep working interrupt enable */
+
+/* function declarations */
+/* initialization functions */
+/* deinitialize CAN */
+void can_deinit(uint32_t can_periph);
+/* initialize CAN structure */
+void can_struct_para_init(can_struct_type_enum type, void* p_struct);
+/* initialize CAN */
+ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init);
+/* CAN filter initialization */
+void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init);
+
+/* function configuration */
+/* set can1 filter start bank number */
+void can1_filter_start_bank(uint8_t start_bank);
+/* enable functions */
+/* CAN debug freeze enable */
+void can_debug_freeze_enable(uint32_t can_periph);
+/* CAN debug freeze disable */
+void can_debug_freeze_disable(uint32_t can_periph);
+/* CAN time trigger mode enable */
+void can_time_trigger_mode_enable(uint32_t can_periph);
+/* CAN time trigger mode disable */
+void can_time_trigger_mode_disable(uint32_t can_periph);
+
+/* transmit functions */
+/* transmit CAN message */
+uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message);
+/* get CAN transmit state */
+can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number);
+/* stop CAN transmission */
+void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number);
+/* CAN receive message */
+void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message);
+/* CAN release fifo */
+void can_fifo_release(uint32_t can_periph, uint8_t fifo_number);
+/* CAN receive message length */
+uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number);
+/* CAN working mode */
+ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode);
+/* CAN wakeup from sleep mode */
+ErrStatus can_wakeup(uint32_t can_periph);
+
+/* CAN get error */
+can_error_enum can_error_get(uint32_t can_periph);
+/* get CAN receive error number */
+uint8_t can_receive_error_number_get(uint32_t can_periph);
+/* get CAN transmit error number */
+uint8_t can_transmit_error_number_get(uint32_t can_periph);
+
+/* interrupt & flag functions */
+/* CAN interrupt enable */
+void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt);
+/* CAN interrupt disable */
+void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt);
+/* CAN get flag state */
+FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag);
+/* CAN clear flag state */
+void can_flag_clear(uint32_t can_periph, can_flag_enum flag);
+/* CAN get interrupt flag state */
+FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag);
+/* CAN clear interrupt flag state */
+void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag);
+
+#endif /* GD32F10x_CAN_H */

+ 80 - 0
Library/Include/gd32f10x_crc.h

@@ -0,0 +1,80 @@
+/*!
+    \file    gd32f10x_crc.h
+    \brief   definitions for the CRC
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_CRC_H
+#define GD32F10X_CRC_H
+
+#include "gd32f10x.h"
+
+/* CRC definitions */
+#define CRC                            CRC_BASE
+
+/* registers definitions */
+#define CRC_DATA                       REG32(CRC + 0x00U)              /*!< CRC data register */
+#define CRC_FDATA                      REG32(CRC + 0x04U)              /*!< CRC free data register */
+#define CRC_CTL                        REG32(CRC + 0x08U)              /*!< CRC control register */
+
+/* bits definitions */
+/* CRC_DATA */
+#define CRC_DATA_DATA                  BITS(0,31)                      /*!< CRC calculation result bits */
+
+/* CRC_FDATA */
+#define CRC_FDATA_FDATA                BITS(0,7)                       /*!< CRC free data bits */
+
+/* CRC_CTL */
+#define CRC_CTL_RST                    BIT(0)                          /*!< CRC reset CRC_DATA register bit */
+
+/* function declarations */
+/* deinit CRC calculation unit */
+void crc_deinit(void);
+
+/* reset data register to the value of initializaiton data register */
+void crc_data_register_reset(void);
+/* read the value of the data register */
+uint32_t crc_data_register_read(void);
+
+/* read the value of the free data register */
+uint8_t crc_free_data_register_read(void);
+/* write data to the free data register */
+void crc_free_data_register_write(uint8_t free_data);
+
+/* calculate the CRC value of a 32-bit data */
+uint32_t crc_single_data_calculate(uint32_t sdata);
+/* calculate the CRC value of an array of 32-bit values */
+uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size);
+
+#endif /* GD32F10X_CRC_H */

+ 249 - 0
Library/Include/gd32f10x_dac.h

@@ -0,0 +1,249 @@
+/*!
+    \file    gd32f10x_dac.h
+    \brief   definitions for the DAC
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_DAC_H
+#define GD32F10X_DAC_H
+
+#include "gd32f10x.h"
+
+/* DACx(x=0,1) definitions */
+#define DAC                     DAC_BASE
+#define DAC0                    0U
+#define DAC1                    1U
+
+/* registers definitions */
+#define DAC_CTL                 REG32(DAC + 0x00U)   /*!< DAC control register */
+#define DAC_SWT                 REG32(DAC + 0x04U)   /*!< DAC software trigger register */
+#define DAC0_R12DH              REG32(DAC + 0x08U)   /*!< DAC0 12-bit right-aligned data holding register */
+#define DAC0_L12DH              REG32(DAC + 0x0CU)   /*!< DAC0 12-bit left-aligned data holding register */
+#define DAC0_R8DH               REG32(DAC + 0x10U)   /*!< DAC0 8-bit right-aligned data holding register */
+#define DAC1_R12DH              REG32(DAC + 0x14U)   /*!< DAC1 12-bit right-aligned data holding register */
+#define DAC1_L12DH              REG32(DAC + 0x18U)   /*!< DAC1 12-bit left-aligned data holding register */
+#define DAC1_R8DH               REG32(DAC + 0x1CU)   /*!< DAC1 8-bit right-aligned data holding register */
+#define DACC_R12DH              REG32(DAC + 0x20U)   /*!< DAC concurrent mode 12-bit right-aligned data holding register */
+#define DACC_L12DH              REG32(DAC + 0x24U)   /*!< DAC concurrent mode 12-bit left-aligned data holding register */
+#define DACC_R8DH               REG32(DAC + 0x28U)   /*!< DAC concurrent mode 8-bit right-aligned data holding register */
+#define DAC0_DO                 REG32(DAC + 0x2CU)   /*!< DAC0 data output register */
+#define DAC1_DO                 REG32(DAC + 0x30U)   /*!< DAC1 data output register */
+
+/* bits definitions */
+/* DAC_CTL */
+#define DAC_CTL_DEN0            BIT(0)               /*!< DAC0 enable/disable bit */
+#define DAC_CTL_DBOFF0          BIT(1)               /*!< DAC0 output buffer turn on/off bit */
+#define DAC_CTL_DTEN0           BIT(2)               /*!< DAC0 trigger enable/disable bit */
+#define DAC_CTL_DTSEL0          BITS(3,5)            /*!< DAC0 trigger source selection enable/disable bits */
+#define DAC_CTL_DWM0            BITS(6,7)            /*!< DAC0 noise wave mode */
+#define DAC_CTL_DWBW0           BITS(8,11)           /*!< DAC0 noise wave bit width */
+#define DAC_CTL_DDMAEN0         BIT(12)              /*!< DAC0 DMA enable/disable bit */
+#define DAC_CTL_DEN1            BIT(16)              /*!< DAC1 enable/disable bit */ 
+#define DAC_CTL_DBOFF1          BIT(17)              /*!< DAC1 output buffer turn on/turn off bit */
+#define DAC_CTL_DTEN1           BIT(18)              /*!< DAC1 trigger enable/disable bit */
+#define DAC_CTL_DTSEL1          BITS(19,21)          /*!< DAC1 trigger source selection enable/disable bits */
+#define DAC_CTL_DWM1            BITS(22,23)          /*!< DAC1 noise wave mode */
+#define DAC_CTL_DWBW1           BITS(24,27)          /*!< DAC1 noise wave bit width */
+#define DAC_CTL_DDMAEN1         BIT(28)              /*!< DAC1 DMA enable/disable bit */
+
+/* DAC_SWT */
+#define DAC_SWT_SWTR0           BIT(0)               /*!< DAC0 software trigger bit, cleared by hardware */
+#define DAC_SWT_SWTR1           BIT(1)               /*!< DAC1 software trigger bit, cleared by hardware */
+
+/* DAC0_R12DH */
+#define DAC0_R12DH_DAC0_DH      BITS(0,11)           /*!< DAC0 12-bit right-aligned data bits */
+
+/* DAC0_L12DH */
+#define DAC0_L12DH_DAC0_DH      BITS(4,15)           /*!< DAC0 12-bit left-aligned data bits */
+
+/* DAC0_R8DH */
+#define DAC0_R8DH_DAC0_DH       BITS(0,7)            /*!< DAC0 8-bit right-aligned data bits */
+
+/* DAC1_R12DH */
+#define DAC1_R12DH_DAC1_DH      BITS(0,11)           /*!< DAC1 12-bit right-aligned data bits */
+
+/* DAC1_L12DH */
+#define DAC1_L12DH_DAC1_DH      BITS(4,15)           /*!< DAC1 12-bit left-aligned data bits */
+
+/* DAC1_R8DH */
+#define DAC1_R8DH_DAC1_DH       BITS(0,7)            /*!< DAC1 8-bit right-aligned data bits */
+
+/* DACC_R12DH */
+#define DACC_R12DH_DAC0_DH      BITS(0,11)           /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */
+#define DACC_R12DH_DAC1_DH      BITS(16,27)          /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */
+
+/* DACC_L12DH */
+#define DACC_L12DH_DAC0_DH      BITS(4,15)           /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */
+#define DACC_L12DH_DAC1_DH      BITS(20,31)          /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */
+
+/* DACC_R8DH */
+#define DACC_R8DH_DAC0_DH       BITS(0,7)            /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */
+#define DACC_R8DH_DAC1_DH       BITS(8,15)           /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */
+
+/* DAC0_DO */
+#define DAC0_DO_DAC0_DO         BITS(0,11)           /*!< DAC0 12-bit output data bits */
+
+/* DAC1_DO */
+#define DAC1_DO_DAC1_DO         BITS(0,11)           /*!< DAC1 12-bit output data bits */
+
+/* constants definitions */
+/* DAC trigger source */
+#define CTL_DTSEL(regval)       (BITS(3,5) & ((uint32_t)(regval) << 3))
+#define DAC_TRIGGER_T5_TRGO     CTL_DTSEL(0)         /*!< TIMER5 TRGO */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define DAC_TRIGGER_T7_TRGO     CTL_DTSEL(1)         /*!< TIMER7 TRGO */
+#elif defined(GD32F10X_CL)
+#define DAC_TRIGGER_T2_TRGO     CTL_DTSEL(1)         /*!< TIMER2 TRGO */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+#define DAC_TRIGGER_T6_TRGO     CTL_DTSEL(2)         /*!< TIMER6 TRGO */
+#define DAC_TRIGGER_T4_TRGO     CTL_DTSEL(3)         /*!< TIMER4 TRGO */
+#define DAC_TRIGGER_T1_TRGO     CTL_DTSEL(4)         /*!< TIMER1 TRGO */
+#define DAC_TRIGGER_T3_TRGO     CTL_DTSEL(5)         /*!< TIMER3 TRGO */
+#define DAC_TRIGGER_EXTI_9      CTL_DTSEL(6)         /*!< EXTI interrupt line9 event */
+#define DAC_TRIGGER_SOFTWARE    CTL_DTSEL(7)         /*!< software trigger */
+
+/* DAC noise wave mode */
+#define CTL_DWM(regval)         (BITS(6,7) & ((uint32_t)(regval) << 6))
+#define DAC_WAVE_DISABLE        CTL_DWM(0)           /*!< wave disable */
+#define DAC_WAVE_MODE_LFSR      CTL_DWM(1)           /*!< LFSR noise mode */
+#define DAC_WAVE_MODE_TRIANGLE  CTL_DWM(2)           /*!< triangle noise mode */
+
+/* DAC noise wave bit width */
+#define DWBW(regval)            (BITS(8,11) & ((uint32_t)(regval) << 8))
+#define DAC_WAVE_BIT_WIDTH_1    DWBW(0)              /*!< bit width of the wave signal is 1 */
+#define DAC_WAVE_BIT_WIDTH_2    DWBW(1)              /*!< bit width of the wave signal is 2 */
+#define DAC_WAVE_BIT_WIDTH_3    DWBW(2)              /*!< bit width of the wave signal is 3 */
+#define DAC_WAVE_BIT_WIDTH_4    DWBW(3)              /*!< bit width of the wave signal is 4 */
+#define DAC_WAVE_BIT_WIDTH_5    DWBW(4)              /*!< bit width of the wave signal is 5 */
+#define DAC_WAVE_BIT_WIDTH_6    DWBW(5)              /*!< bit width of the wave signal is 6 */
+#define DAC_WAVE_BIT_WIDTH_7    DWBW(6)              /*!< bit width of the wave signal is 7 */
+#define DAC_WAVE_BIT_WIDTH_8    DWBW(7)              /*!< bit width of the wave signal is 8 */
+#define DAC_WAVE_BIT_WIDTH_9    DWBW(8)              /*!< bit width of the wave signal is 9 */
+#define DAC_WAVE_BIT_WIDTH_10   DWBW(9)              /*!< bit width of the wave signal is 10 */
+#define DAC_WAVE_BIT_WIDTH_11   DWBW(10)             /*!< bit width of the wave signal is 11 */
+#define DAC_WAVE_BIT_WIDTH_12   DWBW(11)             /*!< bit width of the wave signal is 12 */
+
+/* unmask LFSR bits in DAC LFSR noise mode */
+#define DAC_LFSR_BIT0           DAC_WAVE_BIT_WIDTH_1  /*!< unmask the LFSR bit0 */
+#define DAC_LFSR_BITS1_0        DAC_WAVE_BIT_WIDTH_2  /*!< unmask the LFSR bits[1:0] */
+#define DAC_LFSR_BITS2_0        DAC_WAVE_BIT_WIDTH_3  /*!< unmask the LFSR bits[2:0] */
+#define DAC_LFSR_BITS3_0        DAC_WAVE_BIT_WIDTH_4  /*!< unmask the LFSR bits[3:0] */
+#define DAC_LFSR_BITS4_0        DAC_WAVE_BIT_WIDTH_5  /*!< unmask the LFSR bits[4:0] */
+#define DAC_LFSR_BITS5_0        DAC_WAVE_BIT_WIDTH_6  /*!< unmask the LFSR bits[5:0] */
+#define DAC_LFSR_BITS6_0        DAC_WAVE_BIT_WIDTH_7  /*!< unmask the LFSR bits[6:0] */
+#define DAC_LFSR_BITS7_0        DAC_WAVE_BIT_WIDTH_8  /*!< unmask the LFSR bits[7:0] */
+#define DAC_LFSR_BITS8_0        DAC_WAVE_BIT_WIDTH_9  /*!< unmask the LFSR bits[8:0] */
+#define DAC_LFSR_BITS9_0        DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */
+#define DAC_LFSR_BITS10_0       DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */
+#define DAC_LFSR_BITS11_0       DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */
+
+/* DAC data alignment */
+#define DATA_ALIGN(regval)      (BITS(0,1) & ((uint32_t)(regval) << 0))
+#define DAC_ALIGN_12B_R         DATA_ALIGN(0)        /*!< data right 12b alignment */
+#define DAC_ALIGN_12B_L         DATA_ALIGN(1)        /*!< data left  12b alignment */
+#define DAC_ALIGN_8B_R          DATA_ALIGN(2)        /*!< data right  8b alignment */
+/* triangle amplitude in DAC triangle noise mode */
+#define DAC_TRIANGLE_AMPLITUDE_1    DAC_WAVE_BIT_WIDTH_1  /*!< triangle amplitude is 1 */
+#define DAC_TRIANGLE_AMPLITUDE_3    DAC_WAVE_BIT_WIDTH_2  /*!< triangle amplitude is 3 */
+#define DAC_TRIANGLE_AMPLITUDE_7    DAC_WAVE_BIT_WIDTH_3  /*!< triangle amplitude is 7 */
+#define DAC_TRIANGLE_AMPLITUDE_15   DAC_WAVE_BIT_WIDTH_4  /*!< triangle amplitude is 15 */
+#define DAC_TRIANGLE_AMPLITUDE_31   DAC_WAVE_BIT_WIDTH_5  /*!< triangle amplitude is 31 */
+#define DAC_TRIANGLE_AMPLITUDE_63   DAC_WAVE_BIT_WIDTH_6  /*!< triangle amplitude is 63 */
+#define DAC_TRIANGLE_AMPLITUDE_127  DAC_WAVE_BIT_WIDTH_7  /*!< triangle amplitude is 127 */
+#define DAC_TRIANGLE_AMPLITUDE_255  DAC_WAVE_BIT_WIDTH_8  /*!< triangle amplitude is 255 */
+#define DAC_TRIANGLE_AMPLITUDE_511  DAC_WAVE_BIT_WIDTH_9  /*!< triangle amplitude is 511 */
+#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */
+#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */
+#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */
+
+/* function declarations */
+/* initialization functions */
+/* deinitialize DAC */
+void dac_deinit(void);
+/* enable DAC */
+void dac_enable(uint32_t dac_periph);
+/* disable DAC */
+void dac_disable(uint32_t dac_periph);
+/* enable DAC DMA */
+void dac_dma_enable(uint32_t dac_periph);
+/* disable DAC DMA */
+void dac_dma_disable(uint32_t dac_periph); 
+/* enable DAC output buffer */
+void dac_output_buffer_enable(uint32_t dac_periph);
+/* disable DAC output buffer */
+void dac_output_buffer_disable(uint32_t dac_periph);
+/* get the last data output value */
+uint16_t dac_output_value_get(uint32_t dac_periph);
+/* set DAC data holding register value */
+void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data);
+
+/* DAC trigger configuration */
+/* enable DAC trigger */
+void dac_trigger_enable(uint32_t dac_periph);
+/* disable DAC trigger */
+void dac_trigger_disable(uint32_t dac_periph);
+/* configure DAC trigger source */
+void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource);
+/* enable DAC software trigger */
+void dac_software_trigger_enable(uint32_t dac_periph);
+/* disable DAC software trigger */
+void dac_software_trigger_disable(uint32_t dac_periph);
+
+/* DAC wave mode configuration */
+/* configure DAC wave mode */
+void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode);
+/* configure DAC wave bit width */
+void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width);
+/* configure DAC LFSR noise mode */
+void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits);
+/* configure DAC triangle noise mode */
+void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude);
+
+/* DAC concurrent mode configuration */
+/* enable DAC concurrent mode */
+void dac_concurrent_enable(void);
+/* disable DAC concurrent mode */
+void dac_concurrent_disable(void);
+/* enable DAC concurrent software trigger */
+void dac_concurrent_software_trigger_enable(void);
+/* disable DAC concurrent software trigger */
+void dac_concurrent_software_trigger_disable(void);
+/* enable DAC concurrent buffer function */
+void dac_concurrent_output_buffer_enable(void);
+/* disable DAC concurrent buffer function */
+void dac_concurrent_output_buffer_disable(void);
+/* set DAC concurrent mode data holding register value */
+void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); 
+
+#endif /* GD32F10X_DAC_H */

+ 152 - 0
Library/Include/gd32f10x_dbg.h

@@ -0,0 +1,152 @@
+/*!
+    \file    gd32f10x_dbg.h
+    \brief   definitions for the DBG
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-07-01, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_DBG_H
+#define GD32F10X_DBG_H
+
+#include "gd32f10x.h"
+
+/* DBG definitions */
+#define DBG                      DBG_BASE
+
+/* registers definitions */
+#define DBG_ID                   REG32(DBG + 0x00U)         /*!< DBG_ID code register */
+#define DBG_CTL                  REG32(DBG + 0x04U)         /*!< DBG control register */
+
+/* bits definitions */
+/* DBG_ID */
+#define DBG_ID_ID_CODE           BITS(0,31)                 /*!< DBG ID code values */
+
+/* DBG_CTL */
+#define DBG_CTL_SLP_HOLD        BIT(0)                      /*!< keep debugger connection during sleep mode */
+#define DBG_CTL_DSLP_HOLD       BIT(1)                      /*!< keep debugger connection during deepsleep mode */
+#define DBG_CTL_STB_HOLD        BIT(2)                      /*!< keep debugger connection during standby mode */
+#define DBG_CTL_TRACE_IOEN      BIT(5)                      /*!< enable trace pin assignment */
+#define DBG_CTL_TRACE_MODE      BITS(6,7)                   /*!< trace pin mode selection */
+#define DBG_CTL_FWDGT_HOLD      BIT(8)                      /*!< debug FWDGT kept when core is halted */
+#define DBG_CTL_WWDGT_HOLD      BIT(9)                      /*!< debug WWDGT kept when core is halted */
+#define DBG_CTL_TIMER0_HOLD     BIT(10)                     /*!< hold TIMER0 counter when core is halted */
+#define DBG_CTL_TIMER1_HOLD     BIT(11)                     /*!< hold TIMER1 counter when core is halted */
+#define DBG_CTL_TIMER2_HOLD     BIT(12)                     /*!< hold TIMER2 counter when core is halted */
+#define DBG_CTL_TIMER3_HOLD     BIT(13)                     /*!< hold TIMER3 counter when core is halted */
+#define DBG_CTL_CAN0_HOLD       BIT(14)                     /*!< debug CAN0 kept when core is halted */
+#define DBG_CTL_I2C0_HOLD       BIT(15)                     /*!< hold I2C0 smbus when core is halted */
+#define DBG_CTL_I2C1_HOLD       BIT(16)                     /*!< hold I2C1 smbus when core is halted */
+#define DBG_CTL_TIMER7_HOLD     BIT(17)                     /*!< hold TIMER7 counter when core is halted */
+#define DBG_CTL_TIMER4_HOLD     BIT(18)                     /*!< hold TIMER4 counter when core is halted */
+#define DBG_CTL_TIMER5_HOLD     BIT(19)                     /*!< hold TIMER5 counter when core is halted */
+#define DBG_CTL_TIMER6_HOLD     BIT(20)                     /*!< hold TIMER6 counter when core is halted */
+#ifdef GD32F10X_CL
+#define DBG_CTL_CAN1_HOLD       BIT(21)                     /*!< debug CAN1 kept when core is halted */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+#define DBG_CTL_TIMER11_HOLD    BIT(25)                     /*!< hold TIMER11 counter when core is halted */
+#define DBG_CTL_TIMER12_HOLD    BIT(26)                     /*!< hold TIMER12 counter when core is halted */
+#define DBG_CTL_TIMER13_HOLD    BIT(27)                     /*!< hold TIMER13 counter when core is halted */
+#define DBG_CTL_TIMER8_HOLD     BIT(28)                     /*!< hold TIMER8 counter when core is halted */
+#define DBG_CTL_TIMER9_HOLD     BIT(29)                     /*!< hold TIMER9 counter when core is halted */
+#define DBG_CTL_TIMER10_HOLD    BIT(30)                     /*!< hold TIMER10 counter when core is halted */
+#endif /* GD32F10X_XD */
+
+/* constants definitions */
+/* debug hold when core is halted */
+typedef enum
+{
+    DBG_FWDGT_HOLD             = BIT(8),                    /*!< debug FWDGT kept when core is halted */
+    DBG_WWDGT_HOLD             = BIT(9),                    /*!< debug WWDGT kept when core is halted */
+    DBG_TIMER0_HOLD            = BIT(10),                   /*!< hold TIMER0 counter when core is halted */
+    DBG_TIMER1_HOLD            = BIT(11),                   /*!< hold TIMER1 counter when core is halted */
+    DBG_TIMER2_HOLD            = BIT(12),                   /*!< hold TIMER2 counter when core is halted */
+    DBG_TIMER3_HOLD            = BIT(13),                   /*!< hold TIMER3 counter when core is halted */
+    DBG_CAN0_HOLD              = BIT(14),                   /*!< debug CAN0 kept when core is halted */
+    DBG_I2C0_HOLD              = BIT(15),                   /*!< hold I2C0 smbus when core is halted */
+    DBG_I2C1_HOLD              = BIT(16),                   /*!< hold I2C1 smbus when core is halted */
+    DBG_TIMER7_HOLD            = BIT(17),                   /*!< hold TIMER7 counter when core is halted */
+    DBG_TIMER4_HOLD            = BIT(18),                   /*!< hold TIMER4 counter when core is halted */
+    DBG_TIMER5_HOLD            = BIT(19),                   /*!< hold TIMER5 counter when core is halted */
+    DBG_TIMER6_HOLD            = BIT(20),                   /*!< hold TIMER6 counter when core is halted */
+#ifdef GD32F10X_CL
+    DBG_CAN1_HOLD              = BIT(21),                   /*!< debug CAN1 kept when core is halted */
+#endif /* GD32F10X_CL */
+#if (defined(GD32F10X_XD) || defined(GD32F10X_CL))
+    DBG_TIMER11_HOLD           = BIT(25),                   /*!< hold TIMER11 counter when core is halted */
+    DBG_TIMER12_HOLD           = BIT(26),                   /*!< hold TIMER12 counter when core is halted */
+    DBG_TIMER13_HOLD           = BIT(27),                   /*!< hold TIMER13 counter when core is halted */
+    DBG_TIMER8_HOLD            = BIT(28),                   /*!< hold TIMER8 counter when core is halted */
+    DBG_TIMER9_HOLD            = BIT(29),                   /*!< hold TIMER9 counter when core is halted */
+    DBG_TIMER10_HOLD           = BIT(30),                   /*!< hold TIMER10 counter when core is halted */
+#endif /* GD32F10X_XD || GD32F10X_CL*/
+}dbg_periph_enum;
+
+/* DBG low power mode configurations */
+#define DBG_LOW_POWER_SLEEP      DBG_CTL_SLP_HOLD           /*!< keep debugger connection during sleep mode */
+#define DBG_LOW_POWER_DEEPSLEEP  DBG_CTL_DSLP_HOLD          /*!< keep debugger connection during deepsleep mode */
+#define DBG_LOW_POWER_STANDBY    DBG_CTL_STB_HOLD           /*!< keep debugger connection during standby mode */
+
+/* DBG_CTL0_TRACE_MODE configurations */
+#define CTL_TRACE_MODE(regval)       (BITS(6,7) & ((uint32_t)(regval) << 6U))
+#define TRACE_MODE_ASYNC              CTL_TRACE_MODE(0)     /*!< trace pin used for async mode */
+#define TRACE_MODE_SYNC_DATASIZE_1    CTL_TRACE_MODE(1)     /*!< trace pin used for sync mode and data size is 1 */
+#define TRACE_MODE_SYNC_DATASIZE_2    CTL_TRACE_MODE(2)     /*!< trace pin used for sync mode and data size is 2 */
+#define TRACE_MODE_SYNC_DATASIZE_4    CTL_TRACE_MODE(3)     /*!< trace pin used for sync mode and data size is 4 */
+
+/* function declarations */
+/* read DBG_ID code register */
+uint32_t dbg_id_get(void);
+
+/* low power behavior configuration */
+/* enable low power behavior when the MCU is in debug mode */
+void dbg_low_power_enable(uint32_t dbg_low_power);
+/* disable low power behavior when the MCU is in debug mode */
+void dbg_low_power_disable(uint32_t dbg_low_power);
+
+/* peripheral behavior configuration */
+/* enable peripheral behavior when the MCU is in debug mode */
+void dbg_periph_enable(dbg_periph_enum dbg_periph);
+/* disable peripheral behavior when the MCU is in debug mode */
+void dbg_periph_disable(dbg_periph_enum dbg_periph);
+
+/* trace pin assignment configuration */
+/* enable trace pin assignment */
+void dbg_trace_pin_enable(void);
+/* disable trace pin assignment */
+void dbg_trace_pin_disable(void);
+/* set trace pin mode */
+void dbg_trace_pin_mode_set(uint32_t trace_mode);
+
+#endif /* GD32F10X_DBG_H */

+ 289 - 0
Library/Include/gd32f10x_dma.h

@@ -0,0 +1,289 @@
+/*!
+    \file    gd32f10x_dma.h
+    \brief   definitions for the DMA
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-10-30, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_DMA_H
+#define GD32F10X_DMA_H
+
+#include "gd32f10x.h"
+
+/* DMA definitions */
+#define DMA0                            (DMA_BASE)               /*!< DMA0 base address */
+#define DMA1                            (DMA_BASE + 0x0400U)     /*!< DMA1 base address */
+
+/* registers definitions */
+#define DMA_INTF(dmax)                  REG32((dmax) + 0x00U)    /*!< DMA interrupt flag register */
+#define DMA_INTC(dmax)                  REG32((dmax) + 0x04U)    /*!< DMA interrupt flag clear register */
+
+#define DMA_CH0CTL(dmax)                REG32((dmax) + 0x08U)    /*!< DMA channel 0 control register */
+#define DMA_CH0CNT(dmax)                REG32((dmax) + 0x0CU)    /*!< DMA channel 0 counter register */
+#define DMA_CH0PADDR(dmax)              REG32((dmax) + 0x10U)    /*!< DMA channel 0 peripheral base address register */
+#define DMA_CH0MADDR(dmax)              REG32((dmax) + 0x14U)    /*!< DMA channel 0 memory base address register */
+
+#define DMA_CH1CTL(dmax)                REG32((dmax) + 0x1CU)    /*!< DMA channel 1 control register */
+#define DMA_CH1CNT(dmax)                REG32((dmax) + 0x20U)    /*!< DMA channel 1 counter register */
+#define DMA_CH1PADDR(dmax)              REG32((dmax) + 0x24U)    /*!< DMA channel 1 peripheral base address register */
+#define DMA_CH1MADDR(dmax)              REG32((dmax) + 0x28U)    /*!< DMA channel 1 memory base address register */
+
+#define DMA_CH2CTL(dmax)                REG32((dmax) + 0x30U)    /*!< DMA channel 2 control register */
+#define DMA_CH2CNT(dmax)                REG32((dmax) + 0x34U)    /*!< DMA channel 2 counter register */
+#define DMA_CH2PADDR(dmax)              REG32((dmax) + 0x38U)    /*!< DMA channel 2 peripheral base address register */
+#define DMA_CH2MADDR(dmax)              REG32((dmax) + 0x3CU)    /*!< DMA channel 2 memory base address register */
+
+#define DMA_CH3CTL(dmax)                REG32((dmax) + 0x44U)    /*!< DMA channel 3 control register */
+#define DMA_CH3CNT(dmax)                REG32((dmax) + 0x48U)    /*!< DMA channel 3 counter register */
+#define DMA_CH3PADDR(dmax)              REG32((dmax) + 0x4CU)    /*!< DMA channel 3 peripheral base address register */
+#define DMA_CH3MADDR(dmax)              REG32((dmax) + 0x50U)    /*!< DMA channel 3 memory base address register */
+
+#define DMA_CH4CTL(dmax)                REG32((dmax) + 0x58U)    /*!< DMA channel 4 control register */
+#define DMA_CH4CNT(dmax)                REG32((dmax) + 0x5CU)    /*!< DMA channel 4 counter register */
+#define DMA_CH4PADDR(dmax)              REG32((dmax) + 0x60U)    /*!< DMA channel 4 peripheral base address register */
+#define DMA_CH4MADDR(dmax)              REG32((dmax) + 0x64U)    /*!< DMA channel 4 memory base address register */
+
+#define DMA_CH5CTL(dmax)                REG32((dmax) + 0x6CU)    /*!< DMA channel 5 control register */
+#define DMA_CH5CNT(dmax)                REG32((dmax) + 0x70U)    /*!< DMA channel 5 counter register */
+#define DMA_CH5PADDR(dmax)              REG32((dmax) + 0x74U)    /*!< DMA channel 5 peripheral base address register */
+#define DMA_CH5MADDR(dmax)              REG32((dmax) + 0x78U)    /*!< DMA channel 5 memory base address register */
+
+#define DMA_CH6CTL(dmax)                REG32((dmax) + 0x80U)    /*!< DMA channel 6 control register */
+#define DMA_CH6CNT(dmax)                REG32((dmax) + 0x84U)    /*!< DMA channel 6 counter register */
+#define DMA_CH6PADDR(dmax)              REG32((dmax) + 0x88U)    /*!< DMA channel 6 peripheral base address register */
+#define DMA_CH6MADDR(dmax)              REG32((dmax) + 0x8CU)    /*!< DMA channel 6 memory base address register */
+
+/* bits definitions */
+/* DMA_INTF */
+#define DMA_INTF_GIF                    BIT(0)                  /*!< global interrupt flag of channel */
+#define DMA_INTF_FTFIF                  BIT(1)                  /*!< full transfer finish flag of channel */
+#define DMA_INTF_HTFIF                  BIT(2)                  /*!< half transfer finish flag of channel */
+#define DMA_INTF_ERRIF                  BIT(3)                  /*!< error flag of channel */
+
+/* DMA_INTC */
+#define DMA_INTC_GIFC                   BIT(0)                  /*!< clear global interrupt flag of channel */
+#define DMA_INTC_FTFIFC                 BIT(1)                  /*!< clear transfer finish flag of channel */
+#define DMA_INTC_HTFIFC                 BIT(2)                  /*!< clear half transfer finish flag of channel */
+#define DMA_INTC_ERRIFC                 BIT(3)                  /*!< clear error flag of channel */
+
+/* DMA_CHxCTL, x=0..6 */
+#define DMA_CHXCTL_CHEN                 BIT(0)                  /*!< channel enable */
+#define DMA_CHXCTL_FTFIE                BIT(1)                  /*!< enable bit for channel full transfer finish interrupt */
+#define DMA_CHXCTL_HTFIE                BIT(2)                  /*!< enable bit for channel half transfer finish interrupt */
+#define DMA_CHXCTL_ERRIE                BIT(3)                  /*!< enable bit for channel error interrupt */
+#define DMA_CHXCTL_DIR                  BIT(4)                  /*!< transfer direction */
+#define DMA_CHXCTL_CMEN                 BIT(5)                  /*!< circular mode enable */
+#define DMA_CHXCTL_PNAGA                BIT(6)                  /*!< next address generation algorithm of peripheral */
+#define DMA_CHXCTL_MNAGA                BIT(7)                  /*!< next address generation algorithm of memory */
+#define DMA_CHXCTL_PWIDTH               BITS(8,9)               /*!< transfer data width of peripheral */
+#define DMA_CHXCTL_MWIDTH               BITS(10,11)             /*!< transfer data width of memory */
+#define DMA_CHXCTL_PRIO                 BITS(12,13)             /*!< priority level */
+#define DMA_CHXCTL_M2M                  BIT(14)                 /*!< memory to memory mode */
+
+/* DMA_CHxCNT, x=0..6 */
+#define DMA_CHXCNT_CNT                  BITS(0,15)              /*!< transfer counter */
+
+/* DMA_CHxPADDR, x=0..6 */
+#define DMA_CHXPADDR_PADDR              BITS(0,31)              /*!< peripheral base address */
+
+/* DMA_CHxMADDR, x=0..6 */
+#define DMA_CHXMADDR_MADDR              BITS(0,31)              /*!< memory base address */
+
+/* constants definitions */
+/* DMA channel select */
+typedef enum 
+{
+    DMA_CH0 = 0,                /*!< DMA channel 0 */
+    DMA_CH1,                    /*!< DMA channel 1 */ 
+    DMA_CH2,                    /*!< DMA channel 2 */ 
+    DMA_CH3,                    /*!< DMA channel 3 */ 
+    DMA_CH4,                    /*!< DMA channel 4 */ 
+    DMA_CH5,                    /*!< DMA channel 5 */ 
+    DMA_CH6                     /*!< DMA channel 6 */
+} dma_channel_enum;
+
+/* DMA initialize struct */
+typedef struct
+{
+    uint32_t periph_addr;       /*!< peripheral base address */
+    uint32_t periph_width;      /*!< transfer data size of peripheral */
+    uint32_t memory_addr;       /*!< memory base address */
+    uint32_t memory_width;      /*!< transfer data size of memory */
+    uint32_t number;            /*!< channel transfer number */
+    uint32_t priority;          /*!< channel priority level */
+    uint8_t periph_inc;         /*!< peripheral increasing mode */
+    uint8_t memory_inc;         /*!< memory increasing mode */
+    uint8_t direction;          /*!< channel data transfer direction */
+
+} dma_parameter_struct;
+
+#define DMA_FLAG_ADD(flag, shift)           ((flag) << ((shift) * 4U))                      /*!< DMA channel flag shift */
+
+/* DMA_register address */
+#define DMA_CHCTL(dma, channel)             REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel))      /*!< the address of DMA channel CHXCTL register */
+#define DMA_CHCNT(dma, channel)             REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel))      /*!< the address of DMA channel CHXCNT register */
+#define DMA_CHPADDR(dma, channel)           REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel))      /*!< the address of DMA channel CHXPADDR register */
+#define DMA_CHMADDR(dma, channel)           REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel))      /*!< the address of DMA channel CHXMADDR register */
+
+/* DMA reset value */
+#define DMA_CHCTL_RESET_VALUE               ((uint32_t)0x00000000U)                         /*!< the reset value of DMA channel CHXCTL register */
+#define DMA_CHCNT_RESET_VALUE               ((uint32_t)0x00000000U)                         /*!< the reset value of DMA channel CHXCNT register */
+#define DMA_CHPADDR_RESET_VALUE             ((uint32_t)0x00000000U)                         /*!< the reset value of DMA channel CHXPADDR register */
+#define DMA_CHMADDR_RESET_VALUE             ((uint32_t)0x00000000U)                         /*!< the reset value of DMA channel CHXMADDR register */
+#define DMA_CHINTF_RESET_VALUE              (DMA_INTF_GIF | DMA_INTF_FTFIF | \
+                                             DMA_INTF_HTFIF | DMA_INTF_ERRIF)               /*!< clear DMA channel DMA_INTF register */
+
+/* DMA_INTF register */
+/* interrupt flag bits */
+#define DMA_INT_FLAG_G                      DMA_INTF_GIF                                    /*!< global interrupt flag of channel */
+#define DMA_INT_FLAG_FTF                    DMA_INTF_FTFIF                                  /*!< full transfer finish interrupt flag of channel */
+#define DMA_INT_FLAG_HTF                    DMA_INTF_HTFIF                                  /*!< half transfer finish interrupt flag of channel */
+#define DMA_INT_FLAG_ERR                    DMA_INTF_ERRIF                                  /*!< error interrupt flag of channel */
+
+/* flag bits */
+#define DMA_FLAG_G                          DMA_INTF_GIF                                    /*!< global interrupt flag of channel */
+#define DMA_FLAG_FTF                        DMA_INTF_FTFIF                                  /*!< full transfer finish flag of channel */
+#define DMA_FLAG_HTF                        DMA_INTF_HTFIF                                  /*!< half transfer finish flag of channel */
+#define DMA_FLAG_ERR                        DMA_INTF_ERRIF                                  /*!< error flag of channel */
+
+/* DMA_CHxCTL register */
+/* interrupt enable bits */
+#define DMA_INT_FTF                         DMA_CHXCTL_FTFIE                                /*!< enable bit for channel full transfer finish interrupt */
+#define DMA_INT_HTF                         DMA_CHXCTL_HTFIE                                /*!< enable bit for channel half transfer finish interrupt */
+#define DMA_INT_ERR                         DMA_CHXCTL_ERRIE                                /*!< enable bit for channel error interrupt */
+
+/* transfer direction */
+#define DMA_PERIPHERAL_TO_MEMORY            ((uint8_t)0x00U)                                /*!< read from peripheral and write to memory */
+#define DMA_MEMORY_TO_PERIPHERAL            ((uint8_t)0x01U)                                /*!< read from memory and write to peripheral */
+/* circular mode */
+#define DMA_CIRCULAR_MODE_DISABLE           ((uint32_t)0x00000000U)                         /*!< circular mode disable */
+#define DMA_CIRCULAR_MODE_ENABLE            ((uint32_t)0x00000001U)                         /*!< circular mode enable */
+
+/* peripheral increasing mode */
+#define DMA_PERIPH_INCREASE_DISABLE         ((uint8_t)0x00U)                                /*!< next address of peripheral is fixed address mode */
+#define DMA_PERIPH_INCREASE_ENABLE          ((uint8_t)0x01U)                                /*!< next address of peripheral is increasing address mode */
+
+/* memory increasing mode */
+#define DMA_MEMORY_INCREASE_DISABLE         ((uint8_t)0x00U)                                /*!< next address of memory is fixed address mode */
+#define DMA_MEMORY_INCREASE_ENABLE          ((uint8_t)0x01U)                                /*!< next address of memory is increasing address mode */
+
+/* transfer data size of peripheral */
+#define CHCTL_PWIDTH(regval)                (BITS(8,9) & ((regval) << 8))                   /*!< transfer data size of peripheral */
+#define DMA_PERIPHERAL_WIDTH_8BIT           CHCTL_PWIDTH(0U)                                 /*!< transfer data size of peripheral is 8-bit */
+#define DMA_PERIPHERAL_WIDTH_16BIT          CHCTL_PWIDTH(1U)                                 /*!< transfer data size of peripheral is 16-bit */
+#define DMA_PERIPHERAL_WIDTH_32BIT          CHCTL_PWIDTH(2U)                                 /*!< transfer data size of peripheral is 32-bit */
+
+/* transfer data size of memory */
+#define CHCTL_MWIDTH(regval)                (BITS(10,11) & ((regval) << 10))                /*!< transfer data size of memory */
+#define DMA_MEMORY_WIDTH_8BIT               CHCTL_MWIDTH(0U)                                 /*!< transfer data size of memory is 8-bit */
+#define DMA_MEMORY_WIDTH_16BIT              CHCTL_MWIDTH(1U)                                 /*!< transfer data size of memory is 16-bit */
+#define DMA_MEMORY_WIDTH_32BIT              CHCTL_MWIDTH(2U)                                 /*!< transfer data size of memory is 32-bit */
+
+/* channel priority level */
+#define CHCTL_PRIO(regval)                  (BITS(12,13) & ((regval) << 12))                /*!< DMA channel priority level */
+#define DMA_PRIORITY_LOW                    CHCTL_PRIO(0U)                                   /*!< low priority */
+#define DMA_PRIORITY_MEDIUM                 CHCTL_PRIO(1U)                                   /*!< medium priority */
+#define DMA_PRIORITY_HIGH                   CHCTL_PRIO(2U)                                   /*!< high priority */
+#define DMA_PRIORITY_ULTRA_HIGH             CHCTL_PRIO(3U)                                   /*!< ultra high priority */
+
+/* memory to memory mode */
+#define DMA_MEMORY_TO_MEMORY_DISABLE        ((uint32_t)0x00000000U)                         /*!< disable memory to memory mode */
+#define DMA_MEMORY_TO_MEMORY_ENABLE         ((uint32_t)0x00000001U)                         /*!< enable memory to memory mode */
+
+/* DMA_CHxCNT register */
+/* transfer counter */
+#define DMA_CHANNEL_CNT_MASK                DMA_CHXCNT_CNT                                  /*!< transfer counter mask */
+
+/* function declarations */
+/* DMA deinitialization and initialization functions */
+/* deinitialize DMA a channel registers */
+void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx);
+/* initialize the parameters of DMA struct with the default values */
+void dma_struct_para_init(dma_parameter_struct* init_struct);
+/* initialize DMA channel */
+void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct);
+/* enable DMA circulation mode */
+void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx);
+/* disable DMA circulation mode */
+void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx);
+/* enable memory to memory mode */
+void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx);
+/* disable memory to memory mode */
+void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx);
+/* enable DMA channel */
+void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx);
+/* disable DMA channel */
+void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx);
+
+/* DMA configuration functions */
+/* set DMA peripheral base address */
+void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address);
+/* set DMA memory base address */
+void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address);
+/* set the number of remaining data to be transferred by the DMA */
+void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number);
+/* get the number of remaining data to be transferred by the DMA */
+uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx);
+/* configure priority level of DMA channel */
+void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority);
+/* configure transfer data size of memory */
+void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth);
+/* configure transfer data size of peripheral */
+void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth);
+/* enable next address increasement algorithm of memory */
+void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx);
+/* disable next address increasement algorithm of memory */
+void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx);
+/* enable next address increasement algorithm of peripheral */
+void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx);
+/* disable next address increasement algorithm of peripheral */
+void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx);
+/* configure the direction of data transfer on the channel */
+void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction);
+
+/* flag and interrupt functions */
+/* check DMA flag is set or not */
+FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag);
+/* clear the flag of a DMA channel */
+void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag);
+/* check DMA flag and interrupt enable bit is set or not */
+FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag);
+/* clear the interrupt flag of a DMA channel */
+void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag);
+/* enable DMA interrupt */
+void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source);
+/* disable DMA interrupt */
+void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source);
+
+#endif /* GD32F10X_DMA_H */

+ 1497 - 0
Library/Include/gd32f10x_enet.h

@@ -0,0 +1,1497 @@
+/*!
+    \file    gd32f10x_enet.h
+    \brief   definitions for the ENET
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10x_ENET_H
+#define GD32F10x_ENET_H
+
+#include "gd32f10x.h"
+#include <stdlib.h>
+
+#define IF_USE_EXTERNPHY_LIB             0
+#if (1 == IF_USE_EXTERNPHY_LIB)
+#include "phy.h"
+#endif
+
+#ifndef ENET_RXBUF_NUM
+#define ENET_RXBUF_NUM                   5U                                     /*!< ethernet Rx DMA descriptor number */
+#endif
+
+#ifndef ENET_TXBUF_NUM
+#define ENET_TXBUF_NUM                   5U                                     /*!< ethernet Tx DMA descriptor number */
+#endif
+
+#ifndef ENET_RXBUF_SIZE
+#define ENET_RXBUF_SIZE                  ENET_MAX_FRAME_SIZE                    /*!< ethernet receive buffer size */
+#endif
+
+#ifndef ENET_TXBUF_SIZE
+#define ENET_TXBUF_SIZE                  ENET_MAX_FRAME_SIZE                    /*!< ethernet transmit buffer size */
+#endif
+
+/* #define USE_DELAY */
+
+#ifndef _PHY_H_
+#define DP83848                          0
+#define LAN8700                          1
+#define PHY_TYPE                         DP83848
+
+#define PHY_ADDRESS                      ((uint16_t)1U)                         /*!< phy address determined by the hardware */
+
+/* PHY read write timeouts */ 
+#define PHY_READ_TO                      ((uint32_t)0x0004FFFFU)                /*!< PHY read timeout */
+#define PHY_WRITE_TO                     ((uint32_t)0x0004FFFFU)                /*!< PHY write timeout */
+
+/* PHY delay */
+#define PHY_RESETDELAY                   ((uint32_t)0x008FFFFFU)                /*!< PHY reset delay */
+#define PHY_CONFIGDELAY                  ((uint32_t)0x00FFFFFFU)                /*!< PHY configure delay */
+
+/* PHY register address */ 
+#define PHY_REG_BCR                      0U                                     /*!< tranceiver basic control register */
+#define PHY_REG_BSR                      1U                                     /*!< tranceiver basic status register */
+
+/* PHY basic control register */
+#define PHY_RESET                        ((uint16_t)0x8000)                     /*!< PHY reset */
+#define PHY_LOOPBACK                     ((uint16_t)0x4000)                     /*!< enable phy loop-back mode */
+#define PHY_FULLDUPLEX_100M              ((uint16_t)0x2100)                     /*!< configure speed to 100 Mbit/s and the full-duplex mode */
+#define PHY_HALFDUPLEX_100M              ((uint16_t)0x2000)                     /*!< configure speed to 100 Mbit/s and the half-duplex mode */
+#define PHY_FULLDUPLEX_10M               ((uint16_t)0x0100)                     /*!< configure speed to 10 Mbit/s and the full-duplex mode */
+#define PHY_HALFDUPLEX_10M               ((uint16_t)0x0000)                     /*!< configure speed to 10 Mbit/s and the half-duplex mode */
+#define PHY_AUTONEGOTIATION              ((uint16_t)0x1000)                     /*!< enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION      ((uint16_t)0x0200)                     /*!< restart auto-negotiation function */
+#define PHY_POWERDOWN                    ((uint16_t)0x0800)                     /*!< enable the power down mode */
+#define PHY_ISOLATE                      ((uint16_t)0x0400)                     /*!< isolate PHY from MII */
+
+/* PHY basic status register */
+#define PHY_AUTONEGO_COMPLETE            ((uint16_t)0x0020)                     /*!< auto-negotioation process completed */
+#define PHY_LINKED_STATUS                ((uint16_t)0x0004)                     /*!< valid link established */
+#define PHY_JABBER_DETECTION             ((uint16_t)0x0002)                     /*!< jabber condition detected */
+
+#if(PHY_TYPE == LAN8700) 
+#define PHY_SR                           31U                                    /*!< tranceiver status register */
+#define PHY_SPEED_STATUS                 ((uint16_t)0x0004)                     /*!< configured information of speed: 10Mbit/s */
+#define PHY_DUPLEX_STATUS                ((uint16_t)0x0010)                     /*!< configured information of duplex: full-duplex */
+#elif(PHY_TYPE == DP83848)
+#define PHY_SR                           16U                                    /*!< tranceiver status register */
+#define PHY_SPEED_STATUS                 ((uint16_t)0x0002)                     /*!< configured information of speed: 10Mbit/s */
+#define PHY_DUPLEX_STATUS                ((uint16_t)0x0004)                     /*!< configured information of duplex: full-duplex */
+#endif /* PHY_TYPE */
+
+#endif /* _PHY_H_ */
+
+
+/* ENET definitions */
+#define ENET                             ENET_BASE
+
+/* registers definitions */
+#define ENET_MAC_CFG                     REG32((ENET) + 0x00U)                  /*!< ethernet MAC configuration register */
+#define ENET_MAC_FRMF                    REG32((ENET) + 0x04U)                  /*!< ethernet MAC frame filter register */
+#define ENET_MAC_HLH                     REG32((ENET) + 0x08U)                  /*!< ethernet MAC hash list high register */
+#define ENET_MAC_HLL                     REG32((ENET) + 0x0CU)                  /*!< ethernet MAC hash list low register */
+#define ENET_MAC_PHY_CTL                 REG32((ENET) + 0x10U)                  /*!< ethernet MAC PHY control register */
+#define ENET_MAC_PHY_DATA                REG32((ENET) + 0x14U)                  /*!< ethernet MAC MII data register */
+#define ENET_MAC_FCTL                    REG32((ENET) + 0x18U)                  /*!< ethernet MAC flow control register */
+#define ENET_MAC_FCTH                    REG32((ENET) + 0x1080U)                /*!< ethernet MAC flow control threshold register */
+#define ENET_MAC_VLT                     REG32((ENET) + 0x1CU)                  /*!< ethernet MAC VLAN tag register */
+#define ENET_MAC_RWFF                    REG32((ENET) + 0x28U)                  /*!< ethernet MAC remote wakeup frame filter register */
+#define ENET_MAC_WUM                     REG32((ENET) + 0x2CU)                  /*!< ethernet MAC wakeup management register */
+#define ENET_MAC_INTF                    REG32((ENET) + 0x38U)                  /*!< ethernet MAC interrupt flag register */
+#define ENET_MAC_INTMSK                  REG32((ENET) + 0x3CU)                  /*!< ethernet MAC interrupt mask register */
+#define ENET_MAC_ADDR0H                  REG32((ENET) + 0x40U)                  /*!< ethernet MAC address 0 high register */
+#define ENET_MAC_ADDR0L                  REG32((ENET) + 0x44U)                  /*!< ethernet MAC address 0 low register */
+#define ENET_MAC_ADDR1H                  REG32((ENET) + 0x48U)                  /*!< ethernet MAC address 1 high register */
+#define ENET_MAC_ADDR1L                  REG32((ENET) + 0x4CU)                  /*!< ethernet MAC address 1 low register */
+#define ENET_MAC_ADDT2H                  REG32((ENET) + 0x50U)                  /*!< ethernet MAC address 2 high register */
+#define ENET_MAC_ADDR2L                  REG32((ENET) + 0x54U)                  /*!< ethernet MAC address 2 low register */
+#define ENET_MAC_ADDR3H                  REG32((ENET) + 0x58U)                  /*!< ethernet MAC address 3 high register */
+#define ENET_MAC_ADDR3L                  REG32((ENET) + 0x5CU)                  /*!< ethernet MAC address 3 low register */
+
+#define ENET_MSC_CTL                     REG32((ENET) + 0x100U)                 /*!< ethernet MSC control register */
+#define ENET_MSC_RINTF                   REG32((ENET) + 0x104U)                 /*!< ethernet MSC receive interrupt flag register */
+#define ENET_MSC_TINTF                   REG32((ENET) + 0x108U)                 /*!< ethernet MSC transmit interrupt flag register */
+#define ENET_MSC_RINTMSK                 REG32((ENET) + 0x10CU)                 /*!< ethernet MSC receive interrupt mask register */
+#define ENET_MSC_TINTMSK                 REG32((ENET) + 0x110U)                 /*!< ethernet MSC transmit interrupt mask register */
+#define ENET_MSC_SCCNT                   REG32((ENET) + 0x14CU)                 /*!< ethernet MSC transmitted good frames after a single collision counter register */
+#define ENET_MSC_MSCCNT                  REG32((ENET) + 0x150U)                 /*!< ethernet MSC transmitted good frames after more than a single collision counter register */
+#define ENET_MSC_TGFCNT                  REG32((ENET) + 0x168U)                 /*!< ethernet MSC transmitted good frames counter register */
+#define ENET_MSC_RFCECNT                 REG32((ENET) + 0x194U)                 /*!< ethernet MSC received frames with CRC error counter register */
+#define ENET_MSC_RFAECNT                 REG32((ENET) + 0x198U)                 /*!< ethernet MSC received frames with alignment error counter register */
+#define ENET_MSC_RGUFCNT                 REG32((ENET) + 0x1C4U)                 /*!< ethernet MSC received good unicast frames counter register */
+
+#define ENET_PTP_TSCTL                   REG32((ENET) + 0x700U)                 /*!< ethernet PTP time stamp control register */
+#define ENET_PTP_SSINC                   REG32((ENET) + 0x704U)                 /*!< ethernet PTP subsecond increment register */ 
+#define ENET_PTP_TSH                     REG32((ENET) + 0x708U)                 /*!< ethernet PTP time stamp high register */
+#define ENET_PTP_TSL                     REG32((ENET) + 0x70CU)                 /*!< ethernet PTP time stamp low register */
+#define ENET_PTP_TSUH                    REG32((ENET) + 0x710U)                 /*!< ethernet PTP time stamp update high register */
+#define ENET_PTP_TSUL                    REG32((ENET) + 0x714U)                 /*!< ethernet PTP time stamp update low register */
+#define ENET_PTP_TSADDEND                REG32((ENET) + 0x718U)                 /*!< ethernet PTP time stamp addend register */
+#define ENET_PTP_ETH                     REG32((ENET) + 0x71CU)                 /*!< ethernet PTP expected time high register */
+#define ENET_PTP_ETL                     REG32((ENET) + 0x720U)                 /*!< ethernet PTP expected time low register */
+
+#define ENET_DMA_BCTL                    REG32((ENET) + 0x1000U)                /*!< ethernet DMA bus control register */
+#define ENET_DMA_TPEN                    REG32((ENET) + 0x1004U)                /*!< ethernet DMA transmit poll enable register */ 
+#define ENET_DMA_RPEN                    REG32((ENET) + 0x1008U)                /*!< ethernet DMA receive poll enable register */
+#define ENET_DMA_RDTADDR                 REG32((ENET) + 0x100CU)                /*!< ethernet DMA receive descriptor table address register */
+#define ENET_DMA_TDTADDR                 REG32((ENET) + 0x1010U)                /*!< ethernet DMA transmit descriptor table address register */
+#define ENET_DMA_STAT                    REG32((ENET) + 0x1014U)                /*!< ethernet DMA status register */
+#define ENET_DMA_CTL                     REG32((ENET) + 0x1018U)                /*!< ethernet DMA control register */
+#define ENET_DMA_INTEN                   REG32((ENET) + 0x101CU)                /*!< ethernet DMA interrupt enable register */
+#define ENET_DMA_MFBOCNT                 REG32((ENET) + 0x1020U)                /*!< ethernet DMA missed frame and buffer overflow counter register */
+#define ENET_DMA_CTDADDR                 REG32((ENET) + 0x1048U)                /*!< ethernet DMA current transmit descriptor address register */ 
+#define ENET_DMA_CRDADDR                 REG32((ENET) + 0x104CU)                /*!< ethernet DMA current receive descriptor address register */
+#define ENET_DMA_CTBADDR                 REG32((ENET) + 0x1050U)                /*!< ethernet DMA current transmit buffer address register */
+#define ENET_DMA_CRBADDR                 REG32((ENET) + 0x1054U)                /*!< ethernet DMA current receive buffer address register */
+
+/* bits definitions */
+/* ENET_MAC_CFG */
+#define ENET_MAC_CFG_REN                 BIT(2)                                 /*!< receiver enable */
+#define ENET_MAC_CFG_TEN                 BIT(3)                                 /*!< transmitter enable */
+#define ENET_MAC_CFG_DFC                 BIT(4)                                 /*!< defferal check */
+#define ENET_MAC_CFG_BOL                 BITS(5,6)                              /*!< back-off limit */
+#define ENET_MAC_CFG_APCD                BIT(7)                                 /*!< automatic pad/CRC drop */
+#define ENET_MAC_CFG_RTD                 BIT(9)                                 /*!< retry disable */
+#define ENET_MAC_CFG_IPFCO               BIT(10)                                /*!< IP frame checksum offload */
+#define ENET_MAC_CFG_DPM                 BIT(11)                                /*!< duplex mode */
+#define ENET_MAC_CFG_LBM                 BIT(12)                                /*!< loopback mode */
+#define ENET_MAC_CFG_ROD                 BIT(13)                                /*!< receive own disable */
+#define ENET_MAC_CFG_SPD                 BIT(14)                                /*!< fast eneternet speed */
+#define ENET_MAC_CFG_CSD                 BIT(16)                                /*!< carrier sense disable */
+#define ENET_MAC_CFG_IGBS                BITS(17,19)                            /*!< inter-frame gap bit selection */            
+#define ENET_MAC_CFG_JBD                 BIT(22)                                /*!< jabber disable */
+#define ENET_MAC_CFG_WDD                 BIT(23)                                /*!< watchdog disable */
+
+/* ENET_MAC_FRMF */
+#define ENET_MAC_FRMF_PM                 BIT(0)                                 /*!< promiscuous mode */
+#define ENET_MAC_FRMF_HUF                BIT(1)                                 /*!< hash unicast filter */
+#define ENET_MAC_FRMF_HMF                BIT(2)                                 /*!< hash multicast filter */ 
+#define ENET_MAC_FRMF_DAIFLT             BIT(3)                                 /*!< destination address inverse filtering enable */ 
+#define ENET_MAC_FRMF_MFD                BIT(4)                                 /*!< multicast filter disable */ 
+#define ENET_MAC_FRMF_BFRMD              BIT(5)                                 /*!< broadcast frame disable */ 
+#define ENET_MAC_FRMF_PCFRM              BITS(6,7)                              /*!< pass control frames */ 
+#define ENET_MAC_FRMF_SAIFLT             BIT(8)                                 /*!< source address inverse filtering */ 
+#define ENET_MAC_FRMF_SAFLT              BIT(9)                                 /*!< source address filter */ 
+#define ENET_MAC_FRMF_HPFLT              BIT(10)                                /*!< hash or perfect filter */ 
+#define ENET_MAC_FRMF_FAR                BIT(31)                                /*!< frames all receive */ 
+  
+/* ENET_MAC_HLH */
+#define ENET_MAC_HLH_HLH                 BITS(0,31)                             /*!< hash list high */
+  
+/* ENET_MAC_HLL */
+#define ENET_MAC_HLL_HLL                 BITS(0,31)                             /*!< hash list low */
+  
+/* ENET_MAC_PHY_CTL */
+#define ENET_MAC_PHY_CTL_PB              BIT(0)                                 /*!< PHY busy */ 
+#define ENET_MAC_PHY_CTL_PW              BIT(1)                                 /*!< PHY write */ 
+#define ENET_MAC_PHY_CTL_CLR             BITS(2,4)                              /*!< clock range */ 
+#define ENET_MAC_PHY_CTL_PR              BITS(6,10)                             /*!< PHY register */ 
+#define ENET_MAC_PHY_CTL_PA              BITS(11,15)                            /*!< PHY address */ 
+    
+/* ENET_MAC_PHY_DATA */
+#define ENET_MAC_PHY_DATA_PD             BITS(0,15)                             /*!< PHY data */
+  
+/* ENET_MAC_FCTL */
+#define ENET_MAC_FCTL_FLCBBKPA           BIT(0)                                 /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */
+#define ENET_MAC_FCTL_TFCEN              BIT(1)                                 /*!< transmit flow control enable */
+#define ENET_MAC_FCTL_RFCEN              BIT(2)                                 /*!< receive flow control enable */
+#define ENET_MAC_FCTL_UPFDT              BIT(3)                                 /*!< unicast pause frame detect */
+#define ENET_MAC_FCTL_PLTS               BITS(4,5)                              /*!< pause low threshold */     
+#define ENET_MAC_FCTL_DZQP               BIT(7)                                 /*!< disable zero-quanta pause */
+#define ENET_MAC_FCTL_PTM                BITS(16,31)                            /*!< pause time */
+  
+/* ENET_MAC_FCTH */
+#define ENET_MAC_FCTH_RFA                BITS(0,2)                              /*!< threshold of active flow control */
+#define ENET_MAC_FCTH_RFD                BITS(4,6)                              /*!< threshold of deactive flow control */
+  
+/* ENET_MAC_VLT */
+#define ENET_MAC_VLT_VLTI                BITS(0,15)                             /*!< VLAN tag identifier(for receive frames) */
+#define ENET_MAC_VLT_VLTC                BIT(16)                                /*!< 12-bit VLAN tag comparison */
+  
+/* ENET_MAC_RWFF */
+#define ENET_MAC_RWFF_DATA               BITS(0,31)                             /*!< wakeup frame filter register data */
+  
+/* ENET_MAC_WUM */ 
+#define ENET_MAC_WUM_PWD                 BIT(0)                                 /*!< power down */
+#define ENET_MAC_WUM_MPEN                BIT(1)                                 /*!< magic packet enable */
+#define ENET_MAC_WUM_WFEN                BIT(2)                                 /*!< wakeup frame enable */
+#define ENET_MAC_WUM_MPKR                BIT(5)                                 /*!< magic packet received */
+#define ENET_MAC_WUM_WUFR                BIT(6)                                 /*!< wakeup frame received */
+#define ENET_MAC_WUM_GU                  BIT(9)                                 /*!< global unicast */
+#define ENET_MAC_WUM_WUFFRPR             BIT(31)                                /*!< wakeup frame filter register pointer reset */
+
+/* ENET_MAC_INTF */ 
+#define ENET_MAC_INTF_WUM                BIT(3)                                 /*!< WUM status */
+#define ENET_MAC_INTF_MSC                BIT(4)                                 /*!< MSC status */
+#define ENET_MAC_INTF_MSCR               BIT(5)                                 /*!< MSC receive status */
+#define ENET_MAC_INTF_MSCT               BIT(6)                                 /*!< MSC transmit status */
+#define ENET_MAC_INTF_TMST               BIT(9)                                 /*!< timestamp trigger status */
+
+/* ENET_MAC_INTMSK */
+#define ENET_MAC_INTMSK_WUMIM            BIT(3)                                 /*!< WUM interrupt mask */
+#define ENET_MAC_INTMSK_TMSTIM           BIT(9)                                 /*!< timestamp trigger interrupt mask */
+
+/* ENET_MAC_ADDR0H */
+#define ENET_MAC_ADDR0H_ADDR0H           BITS(0,15)                             /*!< MAC address0 high */
+#define ENET_MAC_ADDR0H_MO               BIT(31)                                /*!< always read 1 and must be kept */
+  
+/* ENET_MAC_ADDR0L */
+#define ENET_MAC_ADDR0L_ADDR0L           BITS(0,31)                             /*!< MAC address0 low */
+  
+/* ENET_MAC_ADDR1H */
+#define ENET_MAC_ADDR1H_ADDR1H           BITS(0,15)                             /*!< MAC address1 high */
+#define ENET_MAC_ADDR1H_MB               BITS(24,29)                            /*!< mask byte */ 
+#define ENET_MAC_ADDR1H_SAF              BIT(30)                                /*!< source address filter */
+#define ENET_MAC_ADDR1H_AFE              BIT(31)                                /*!< address filter enable */
+  
+/* ENET_MAC_ADDR1L */
+#define ENET_MAC_ADDR1L_ADDR1L           BITS(0,31)                             /*!< MAC address1 low */
+  
+/* ENET_MAC_ADDR2H */
+#define ENET_MAC_ADDR2H_ADDR2H           BITS(0,15)                             /*!< MAC address2 high */
+#define ENET_MAC_ADDR2H_MB               BITS(24,29)                            /*!< mask byte */
+#define ENET_MAC_ADDR2H_SAF              BIT(30)                                /*!< source address filter */
+#define ENET_MAC_ADDR2H_AFE              BIT(31)                                /*!< address filter enable */
+  
+/* ENET_MAC_ADDR2L */
+#define ENET_MAC_ADDR2L_ADDR2L           BITS(0,31)                             /*!< MAC address2 low */
+  
+/* ENET_MAC_ADDR3H */
+#define ENET_MAC_ADDR3H_ADDR3H           BITS(0,15)                             /*!< MAC address3 high */
+#define ENET_MAC_ADDR3H_MB               BITS(24,29)                            /*!< mask byte */
+#define ENET_MAC_ADDR3H_SAF              BIT(30)                                /*!< source address filter */
+#define ENET_MAC_ADDR3H_AFE              BIT(31)                                /*!< address filter enable */
+
+/* ENET_MAC_ADDR3L */
+#define ENET_MAC_ADDR3L_ADDR3L           BITS(0,31)                             /*!< MAC address3 low */
+ 
+/* ENET_MSC_CTL */
+#define ENET_MSC_CTL_CTR                 BIT(0)                                 /*!< counter reset */
+#define ENET_MSC_CTL_CTSR                BIT(1)                                 /*!< counter stop rollover */
+#define ENET_MSC_CTL_RTOR                BIT(2)                                 /*!< reset on read */
+#define ENET_MSC_CTL_MCFZ                BIT(3)                                 /*!< MSC counter freeze */
+
+/* ENET_MSC_RINTF */
+#define ENET_MSC_RINTF_RFCE              BIT(5)                                 /*!< received frames CRC error */
+#define ENET_MSC_RINTF_RFAE              BIT(6)                                 /*!< received frames alignment error */
+#define ENET_MSC_RINTF_RGUF              BIT(17)                                /*!< receive good unicast frames */
+  
+/* ENET_MSC_TINTF */
+#define ENET_MSC_TINTF_TGFSC             BIT(14)                                /*!< transmitted good frames single collision */
+#define ENET_MSC_TINTF_TGFMSC            BIT(15)                                /*!< transmitted good frames more single collision */
+#define ENET_MSC_TINTF_TGF               BIT(21)                                /*!< transmitted good frames */
+
+/* ENET_MSC_RINTMSK */
+#define ENET_MSC_RINTMSK_RFCEIM          BIT(5)                                 /*!< received frame CRC error interrupt mask */
+#define ENET_MSC_RINTMSK_RFAEIM          BIT(6)                                 /*!< received frames alignment error interrupt mask */
+#define ENET_MSC_RINTMSK_RGUFIM          BIT(17)                                /*!< received good unicast frames interrupt mask */
+  
+/* ENET_MSC_TINTMSK */
+#define ENET_MSC_TINTMSK_TGFSCIM         BIT(14)                                /*!< transmitted good frames single collision interrupt mask */
+#define ENET_MSC_TINTMSK_TGFMSCIM        BIT(15)                                /*!< transmitted good frames more single collision interrupt mask */
+#define ENET_MSC_TINTMSK_TGFIM           BIT(21)                                /*!< transmitted good frames interrupt mask */
+  
+/* ENET_MSC_SCCNT */
+#define ENET_MSC_SCCNT_SCC               BITS(0,31)                             /*!< transmitted good frames single collision counter */
+  
+/* ENET_MSC_MSCCNT */
+#define ENET_MSC_MSCCNT_MSCC             BITS(0,31)                             /*!< transmitted good frames more one single collision counter */
+  
+/* ENET_MSC_TGFCNT */
+#define ENET_MSC_TGFCNT_TGF              BITS(0,31)                             /*!< transmitted good frames counter */
+  
+/* ENET_MSC_RFCECNT */
+#define ENET_MSC_RFCECNT_RFCER           BITS(0,31)                             /*!< received frames with CRC error counter */
+  
+/* ENET_MSC_RFAECNT */
+#define ENET_MSC_RFAECNT_RFAER           BITS(0,31)                             /*!< received frames alignment error counter */
+  
+/* ENET_MSC_RGUFCNT */
+#define ENET_MSC_RGUFCNT_RGUF            BITS(0,31)                             /*!< received good unicast frames counter */
+   
+/* ENET_PTP_TSCTL */
+#define ENET_PTP_TSCTL_TMSEN             BIT(0)                                 /*!< timestamp enable */
+#define ENET_PTP_TSCTL_TMSFCU            BIT(1)                                 /*!< timestamp fine or coarse update */
+#define ENET_PTP_TSCTL_TMSSTI            BIT(2)                                 /*!< timestamp system time initialize */
+#define ENET_PTP_TSCTL_TMSSTU            BIT(3)                                 /*!< timestamp system time update */
+#define ENET_PTP_TSCTL_TMSITEN           BIT(4)                                 /*!< timestamp interrupt trigger enable */
+#define ENET_PTP_TSCTL_TMSARU            BIT(5)                                 /*!< timestamp addend register update */
+
+/* ENET_PTP_SSINC */
+#define ENET_PTP_SSINC_STMSSI            BITS(0,7)                              /*!< system time subsecond increment */
+  
+/* ENET_PTP_TSH */
+#define ENET_PTP_TSH_STMS                BITS(0,31)                             /*!< system time second */
+  
+/* ENET_PTP_TSL */
+#define ENET_PTP_TSL_STMSS               BITS(0,30)                             /*!< system time subseconds */
+#define ENET_PTP_TSL_STS                 BIT(31)                                /*!< system time sign */
+  
+/* ENET_PTP_TSUH */
+#define ENET_PTP_TSUH_TMSUS              BITS(0,31)                             /*!< timestamp update seconds */
+  
+/* ENET_PTP_TSUL */
+#define ENET_PTP_TSUL_TMSUSS             BITS(0,30)                             /*!< timestamp update subseconds */
+#define ENET_PTP_TSUL_TMSUPNS            BIT(31)                                /*!< timestamp update positive or negative sign */
+
+/* ENET_PTP_TSADDEND */
+#define ENET_PTP_TSADDEND_TMSA           BITS(0,31)                             /*!< timestamp addend */
+  
+/* ENET_PTP_ETH */
+#define ENET_PTP_ETH_ETSH                BITS(0,31)                             /*!< expected time high */
+  
+/* ENET_PTP_ETL */
+#define ENET_PTP_ETL_ETSL                BITS(0,31)                             /*!< expected time low */
+  
+/* ENET_DMA_BCTL */
+#define ENET_DMA_BCTL_SWR                BIT(0)                                 /*!< software reset */
+#define ENET_DMA_BCTL_DAB                BIT(1)                                 /*!< DMA arbitration */
+#define ENET_DMA_BCTL_DPSL               BITS(2,6)                              /*!< descriptor skip length */
+#define ENET_DMA_BCTL_PGBL               BITS(8,13)                             /*!< programmable burst length */
+#define ENET_DMA_BCTL_RTPR               BITS(14,15)                            /*!< RxDMA and TxDMA transfer priority ratio */
+#define ENET_DMA_BCTL_FB                 BIT(16)                                /*!< fixed Burst */
+#define ENET_DMA_BCTL_RXDP               BITS(17,22)                            /*!< RxDMA PGBL */
+#define ENET_DMA_BCTL_UIP                BIT(23)                                /*!< use independent PGBL */
+#define ENET_DMA_BCTL_FPBL               BIT(24)                                /*!< four times PGBL mode */
+#define ENET_DMA_BCTL_AA                 BIT(25)                                /*!< address-aligned */
+  
+/* ENET_DMA_TPEN */
+#define ENET_DMA_TPEN_TPE                BITS(0,31)                             /*!< transmit poll enable */
+  
+/* ENET_DMA_RPEN */
+#define ENET_DMA_RPEN_RPE                BITS(0,31)                             /*!< receive poll enable  */
+
+/* ENET_DMA_RDTADDR */
+#define ENET_DMA_RDTADDR_SRT             BITS(0,31)                             /*!< start address of receive table */
+  
+/* ENET_DMA_TDTADDR */
+#define ENET_DMA_TDTADDR_STT             BITS(0,31)                             /*!< start address of transmit table */
+  
+/* ENET_DMA_STAT */
+#define ENET_DMA_STAT_TS                 BIT(0)                                 /*!< transmit status */
+#define ENET_DMA_STAT_TPS                BIT(1)                                 /*!< transmit process stopped status */
+#define ENET_DMA_STAT_TBU                BIT(2)                                 /*!< transmit buffer unavailable status */
+#define ENET_DMA_STAT_TJT                BIT(3)                                 /*!< transmit jabber timeout status */
+#define ENET_DMA_STAT_RO                 BIT(4)                                 /*!< receive overflow status */
+#define ENET_DMA_STAT_TU                 BIT(5)                                 /*!< transmit underflow status */
+#define ENET_DMA_STAT_RS                 BIT(6)                                 /*!< receive status */
+#define ENET_DMA_STAT_RBU                BIT(7)                                 /*!< receive buffer unavailable status */
+#define ENET_DMA_STAT_RPS                BIT(8)                                 /*!< receive process stopped status */
+#define ENET_DMA_STAT_RWT                BIT(9)                                 /*!< receive watchdog timeout status */
+#define ENET_DMA_STAT_ET                 BIT(10)                                /*!< early transmit status */
+#define ENET_DMA_STAT_FBE                BIT(13)                                /*!< fatal bus error status */
+#define ENET_DMA_STAT_ER                 BIT(14)                                /*!< early receive status */
+#define ENET_DMA_STAT_AI                 BIT(15)                                /*!< abnormal interrupt summary */
+#define ENET_DMA_STAT_NI                 BIT(16)                                /*!< normal interrupt summary */
+#define ENET_DMA_STAT_RP                 BITS(17,19)                            /*!< receive process state */
+#define ENET_DMA_STAT_TP                 BITS(20,22)                            /*!< transmit process state */
+#define ENET_DMA_STAT_EB                 BITS(23,25)                            /*!< error bits status */
+#define ENET_DMA_STAT_MSC                BIT(27)                                /*!< MSC status */
+#define ENET_DMA_STAT_WUM                BIT(28)                                /*!< WUM status */
+#define ENET_DMA_STAT_TST                BIT(29)                                /*!< timestamp trigger status */
+ 
+/* ENET_DMA_CTL */
+#define ENET_DMA_CTL_SRE                 BIT(1)                                 /*!< start/stop receive enable */
+#define ENET_DMA_CTL_OSF                 BIT(2)                                 /*!< operate on second frame */
+#define ENET_DMA_CTL_RTHC                BITS(3,4)                              /*!< receive threshold control */
+#define ENET_DMA_CTL_FUF                 BIT(6)                                 /*!< forward undersized good frames */
+#define ENET_DMA_CTL_FERF                BIT(7)                                 /*!< forward error frames */
+#define ENET_DMA_CTL_STE                 BIT(13)                                /*!< start/stop transmission enable */
+#define ENET_DMA_CTL_TTHC                BITS(14,16)                            /*!< transmit threshold control */
+#define ENET_DMA_CTL_FTF                 BIT(20)                                /*!< flush transmit FIFO */
+#define ENET_DMA_CTL_TSFD                BIT(21)                                /*!< transmit store-and-forward */
+#define ENET_DMA_CTL_DAFRF               BIT(24)                                /*!< disable flushing of received frames */
+#define ENET_DMA_CTL_RSFD                BIT(25)                                /*!< receive store-and-forward */
+#define ENET_DMA_CTL_DTCERFD             BIT(26)                                /*!< dropping of TCP/IP checksum error frames disable */
+  
+/* ENET_DMA_INTEN */
+#define ENET_DMA_INTEN_TIE               BIT(0)                                 /*!< transmit interrupt enable */
+#define ENET_DMA_INTEN_TPSIE             BIT(1)                                 /*!< transmit process stopped interrupt enable */
+#define ENET_DMA_INTEN_TBUIE             BIT(2)                                 /*!< transmit buffer unavailable interrupt enable */
+#define ENET_DMA_INTEN_TJTIE             BIT(3)                                 /*!< transmit jabber timeout interrupt enable */
+#define ENET_DMA_INTEN_ROIE              BIT(4)                                 /*!< receive overflow interrupt enable */
+#define ENET_DMA_INTEN_TUIE              BIT(5)                                 /*!< transmit underflow interrupt enable */
+#define ENET_DMA_INTEN_RIE               BIT(6)                                 /*!< receive interrupt enable */
+#define ENET_DMA_INTEN_RBUIE             BIT(7)                                 /*!< receive buffer unavailable interrupt enable */
+#define ENET_DMA_INTEN_RPSIE             BIT(8)                                 /*!< receive process stopped interrupt enable */
+#define ENET_DMA_INTEN_RWTIE             BIT(9)                                 /*!< receive watchdog timeout interrupt enable */
+#define ENET_DMA_INTEN_ETIE              BIT(10)                                /*!< early transmit interrupt enable */
+#define ENET_DMA_INTEN_FBEIE             BIT(13)                                /*!< fatal bus error interrupt enable */
+#define ENET_DMA_INTEN_ERIE              BIT(14)                                /*!< early receive interrupt enable */
+#define ENET_DMA_INTEN_AIE               BIT(15)                                /*!< abnormal interrupt summary enable */
+#define ENET_DMA_INTEN_NIE               BIT(16)                                /*!< normal interrupt summary enable */
+  
+/* ENET_DMA_MFBOCNT */
+#define ENET_DMA_MFBOCNT_MSFC            BITS(0,15)                             /*!< missed frames by the controller */
+#define ENET_DMA_MFBOCNT_OBMFC           BIT(16)                                /* Overflow bit for missed frame counter */
+#define ENET_DMA_MFBOCNT_MSFA            BITS(17,27)                            /*!< missed frames by the application */
+#define ENET_DMA_MFBOCNT_OBFOC           BIT(28)                                /*!< Overflow bit for FIFO overflow counter */
+
+/* ENET_DMA_CTDADDR */
+#define ENET_DMA_CTDADDR_TDAP            BITS(0,31)                             /*!< transmit descriptor address pointer */
+
+/* ENET_DMA_CRDADDR */
+#define ENET_DMA_CRDADDR_RDAP            BITS(0,31)                             /*!< receive descriptor address pointer */
+  
+/* ENET_DMA_CTBADDR */
+#define ENET_DMA_CTBADDR_TBAP            BITS(0,31)                             /*!< transmit buffer address pointer */
+  
+/* ENET_DMA_CRBADDR */
+#define ENET_DMA_CRBADDR_RBAP            BITS(0,31)                             /*!< receive buffer address pointer */
+
+/* ENET DMA Tx descriptor TDES0 */
+#define ENET_TDES0_DB                    BIT(0)                                 /*!< deferred */
+#define ENET_TDES0_UFE                   BIT(1)                                 /*!< underflow error */
+#define ENET_TDES0_EXD                   BIT(2)                                 /*!< excessive deferral */
+#define ENET_TDES0_COCNT                 BITS(3,6)                              /*!< collision count */
+#define ENET_TDES0_VFRM                  BIT(7)                                 /*!< VLAN frame */
+#define ENET_TDES0_ECO                   BIT(8)                                 /*!< excessive collision */
+#define ENET_TDES0_LCO                   BIT(9)                                 /*!< late collision */
+#define ENET_TDES0_NCA                   BIT(10)                                /*!< no carrier */
+#define ENET_TDES0_LCA                   BIT(11)                                /*!< loss of carrier */
+#define ENET_TDES0_IPPE                  BIT(12)                                /*!< IP payload error */
+#define ENET_TDES0_FRMF                  BIT(13)                                /*!< frame flushed */
+#define ENET_TDES0_JT                    BIT(14)                                /*!< jabber timeout */
+#define ENET_TDES0_ES                    BIT(15)                                /*!< error summary */
+#define ENET_TDES0_IPHE                  BIT(16)                                /*!< IP header error */
+#define ENET_TDES0_TTMSS                 BIT(17)                                /*!< transmit timestamp status */
+#define ENET_TDES0_TCHM                  BIT(20)                                /*!< the second address chained mode */
+#define ENET_TDES0_TERM                  BIT(21)                                /*!< transmit end of ring mode*/
+#define ENET_TDES0_CM                    BITS(22,23)                            /*!< checksum mode */
+#define ENET_TDES0_TTSEN                 BIT(25)                                /*!< transmit timestamp function enable */
+#define ENET_TDES0_DPAD                  BIT(26)                                /*!< disable adding pad */
+#define ENET_TDES0_DCRC                  BIT(27)                                /*!< disable CRC */
+#define ENET_TDES0_FSG                   BIT(28)                                /*!< first segment */
+#define ENET_TDES0_LSG                   BIT(29)                                /*!< last segment */
+#define ENET_TDES0_INTC                  BIT(30)                                /*!< interrupt on completion */
+#define ENET_TDES0_DAV                   BIT(31)                                /*!< DAV bit */
+
+/* ENET DMA Tx descriptor TDES1 */
+#define ENET_TDES1_TB1S                  BITS(0,12)                             /*!< transmit buffer 1 size */
+#define ENET_TDES1_TB2S                  BITS(16,28)                            /*!< transmit buffer 2 size */
+
+/* ENET DMA Tx descriptor TDES2 */
+#define ENET_TDES2_TB1AP                 BITS(0,31)                             /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */
+
+/* ENET DMA Tx descriptor TDES3 */
+#define ENET_TDES3_TB2AP                 BITS(0,31)                             /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */
+
+/* ENET DMA Rx descriptor RDES0 */
+#define ENET_RDES0_PCERR                 BIT(0)                                 /*!< payload checksum error */
+#define ENET_RDES0_CERR                  BIT(1)                                 /*!< CRC error */
+#define ENET_RDES0_DBERR                 BIT(2)                                 /*!< dribble bit error */
+#define ENET_RDES0_RERR                  BIT(3)                                 /*!< receive error */
+#define ENET_RDES0_RWDT                  BIT(4)                                 /*!< receive watchdog timeout */
+#define ENET_RDES0_FRMT                  BIT(5)                                 /*!< frame type */
+#define ENET_RDES0_LCO                   BIT(6)                                 /*!< late collision */
+#define ENET_RDES0_IPHERR                BIT(7)                                 /*!< IP frame header error */
+#define ENET_RDES0_LDES                  BIT(8)                                 /*!< last descriptor */ 
+#define ENET_RDES0_FDES                  BIT(9)                                 /*!< first descriptor */
+#define ENET_RDES0_VTAG                  BIT(10)                                /*!< VLAN tag */
+#define ENET_RDES0_OERR                  BIT(11)                                /*!< overflow Error */
+#define ENET_RDES0_LERR                  BIT(12)                                /*!< length error */
+#define ENET_RDES0_SAFF                  BIT(13)                                /*!< SA filter fail */
+#define ENET_RDES0_DERR                  BIT(14)                                /*!< descriptor error */
+#define ENET_RDES0_ERRS                  BIT(15)                                /*!< error summary */
+#define ENET_RDES0_FRML                  BITS(16,29)                            /*!< frame length */
+#define ENET_RDES0_DAFF                  BIT(30)                                /*!< destination address filter fail */
+#define ENET_RDES0_DAV                   BIT(31)                                /*!< descriptor available */
+
+/* ENET DMA Rx descriptor RDES1 */ 
+#define ENET_RDES1_RB1S                  BITS(0,12)                             /*!< receive buffer 1 size */
+#define ENET_RDES1_RCHM                  BIT(14)                                /*!< receive chained mode for second address */
+#define ENET_RDES1_RERM                  BIT(15)                                /*!< receive end of ring mode*/
+#define ENET_RDES1_RB2S                  BITS(16,28)                            /*!< receive buffer 2 size */
+#define ENET_RDES1_DINTC                 BIT(31)                                /*!< disable interrupt on completion */
+
+/* ENET DMA Rx descriptor RDES2 */
+#define ENET_RDES2_RB1AP                 BITS(0,31)                             /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */
+
+/* ENET DMA Rx descriptor RDES3 */
+#define ENET_RDES3_RB2AP                 BITS(0,31)                             /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */
+
+/* constants definitions */
+/* define bit position and its register index offset */
+#define ENET_REGIDX_BIT(regidx, bitpos)  (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define ENET_REG_VAL(periph)             (REG32(ENET + ((uint32_t)(periph)>>6)))
+#define ENET_BIT_POS(val)                ((uint32_t)(val) & 0x1FU)
+
+/* ENET clock range judgement */
+#define ENET_RANGE(hclk, n, m)           (((hclk) >= (n))&&((hclk) < (m)))
+
+/* define MAC address configuration and reference address */
+#define ENET_SET_MACADDRH(p)             (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4])         
+#define ENET_SET_MACADDRL(p)             (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0])
+#define ENET_ADDRH_BASE                  ((ENET) + 0x40U)
+#define ENET_ADDRL_BASE                  ((ENET) + 0x44U)
+#define ENET_GET_MACADDR(offset, n)      ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU))
+
+/* register offset */
+#define MAC_FCTL_REG_OFFSET              0x0018U                                /*!< MAC flow control register offset */
+#define MAC_WUM_REG_OFFSET               0x002CU                                /*!< MAC wakeup management register offset */
+#define MAC_INTF_REG_OFFSET              0x0038U                                /*!< MAC interrupt flag register offset */
+#define MAC_INTMSK_REG_OFFSET            0x003CU                                /*!< MAC interrupt mask register offset */
+
+#define MSC_RINTF_REG_OFFSET             0x0104U                                /*!< MSC receive interrupt flag register offset */
+#define MSC_TINTF_REG_OFFSET             0x0108U                                /*!< MSC transmit interrupt flag register offset */
+#define MSC_RINTMSK_REG_OFFSET           0x010CU                                /*!< MSC receive interrupt mask register offset */
+#define MSC_TINTMSK_REG_OFFSET           0x0110U                                /*!< MSC transmit interrupt mask register offset */
+#define MSC_SCCNT_REG_OFFSET             0x014CU                                /*!< MSC transmitted good frames after a single collision counter register offset */
+#define MSC_MSCCNT_REG_OFFSET            0x0150U                                /*!< MSC transmitted good frames after more than a single collision counter register offset */
+#define MSC_TGFCNT_REG_OFFSET            0x0168U                                /*!< MSC transmitted good frames counter register offset */
+#define MSC_RFCECNT_REG_OFFSET           0x0194U                                /*!< MSC received frames with CRC error counter register offset */
+#define MSC_RFAECNT_REG_OFFSET           0x0198U                                /*!< MSC received frames with alignment error counter register offset */
+#define MSC_RGUFCNT_REG_OFFSET           0x01C4U                                /*!< MSC received good unicast frames counter register offset */
+
+#define DMA_STAT_REG_OFFSET              0x1014U                                /*!< DMA status register offset */
+#define DMA_INTEN_REG_OFFSET             0x101CU                                /*!< DMA interrupt enable register offset */
+#define DMA_TDTADDR_REG_OFFSET           0x1010U                                /*!< DMA transmit descriptor table address register offset */
+#define DMA_CTDADDR_REG_OFFSET           0x1048U                                /*!< DMA current transmit descriptor address register */
+#define DMA_CTBADDR_REG_OFFSET           0x1050U                                /*!< DMA current transmit buffer address register */
+#define DMA_RDTADDR_REG_OFFSET           0x100CU                                /*!< DMA receive descriptor table address register */
+#define DMA_CRDADDR_REG_OFFSET           0x104CU                                /*!< DMA current receive descriptor address register */
+#define DMA_CRBADDR_REG_OFFSET           0x1054U                                /*!< DMA current receive buffer address register */
+
+/* ENET status flag get */
+typedef enum
+{
+    /* ENET_MAC_WUM register */
+    ENET_MAC_FLAG_MPKR              = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U),      /*!< magic packet received flag */
+    ENET_MAC_FLAG_WUFR              = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U),      /*!< wakeup frame received flag */ 
+    /* ENET_MAC_FCTL register */
+    ENET_MAC_FLAG_FLOWCONTROL       = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U),     /*!< flow control status flag */
+    /* ENET_MAC_INTF register */
+    ENET_MAC_FLAG_WUM               = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U),     /*!< WUM status flag */
+    ENET_MAC_FLAG_MSC               = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U),     /*!< MSC status flag */
+    ENET_MAC_FLAG_MSCR              = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U),     /*!< MSC receive status flag */
+    ENET_MAC_FLAG_MSCT              = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U),     /*!< MSC transmit status flag */
+    ENET_MAC_FLAG_TMST              = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U),     /*!< timestamp trigger status flag */
+    /* ENET_MSC_RINTF register */
+    ENET_MSC_FLAG_RFCE              = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U),    /*!< received frames CRC error flag */
+    ENET_MSC_FLAG_RFAE              = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U),    /*!< received frames alignment error flag */
+    ENET_MSC_FLAG_RGUF              = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U),   /*!< received good unicast frames flag */
+    /* ENET_MSC_TINTF register */ 
+    ENET_MSC_FLAG_TGFSC             = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U),   /*!< transmitted good frames single collision flag */
+    ENET_MSC_FLAG_TGFMSC            = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U),   /*!< transmitted good frames more single collision flag */
+    ENET_MSC_FLAG_TGF               = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U),   /*!< transmitted good frames flag */
+    /* ENET_DMA_STAT register */
+    ENET_DMA_FLAG_TS                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U),     /*!< transmit status flag */
+    ENET_DMA_FLAG_TPS               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U),     /*!< transmit process stopped status flag */
+    ENET_DMA_FLAG_TBU               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U),     /*!< transmit buffer unavailable status flag */
+    ENET_DMA_FLAG_TJT               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U),     /*!< transmit jabber timeout status flag */
+    ENET_DMA_FLAG_RO                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U),     /*!< receive overflow status flag */
+    ENET_DMA_FLAG_TU                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U),     /*!< transmit underflow status flag */
+    ENET_DMA_FLAG_RS                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U),     /*!< receive status flag */
+    ENET_DMA_FLAG_RBU               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U),     /*!< receive buffer unavailable status flag */
+    ENET_DMA_FLAG_RPS               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U),     /*!< receive process stopped status flag */
+    ENET_DMA_FLAG_RWT               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U),     /*!< receive watchdog timeout status flag */
+    ENET_DMA_FLAG_ET                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U),    /*!< early transmit status flag */
+    ENET_DMA_FLAG_FBE               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U),    /*!< fatal bus error status flag */
+    ENET_DMA_FLAG_ER                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U),    /*!< early receive status flag */
+    ENET_DMA_FLAG_AI                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U),    /*!< abnormal interrupt summary flag */
+    ENET_DMA_FLAG_NI                = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U),    /*!< normal interrupt summary flag */
+    ENET_DMA_FLAG_EB_DMA_ERROR      = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U),    /*!< error during data transfer by RxDMA/TxDMA flag */
+    ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U),    /*!< error during write/read transfer flag */
+    ENET_DMA_FLAG_EB_ACCESS_ERROR   = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U),    /*!< error during data buffer/descriptor access flag */
+    ENET_DMA_FLAG_MSC               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U),    /*!< MSC status flag */
+    ENET_DMA_FLAG_WUM               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U),    /*!< WUM status flag */
+    ENET_DMA_FLAG_TST               = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U),    /*!< timestamp trigger status flag */                        
+}enet_flag_enum;
+
+/* ENET stutus flag clear */
+typedef enum
+{
+    /* ENET_DMA_STAT register */
+    ENET_DMA_FLAG_TS_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U),     /*!< transmit status flag */
+    ENET_DMA_FLAG_TPS_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U),     /*!< transmit process stopped status flag */
+    ENET_DMA_FLAG_TBU_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U),     /*!< transmit buffer unavailable status flag */
+    ENET_DMA_FLAG_TJT_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U),     /*!< transmit jabber timeout status flag */
+    ENET_DMA_FLAG_RO_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U),     /*!< receive overflow status flag */
+    ENET_DMA_FLAG_TU_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U),     /*!< transmit underflow status flag */
+    ENET_DMA_FLAG_RS_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U),     /*!< receive status flag */
+    ENET_DMA_FLAG_RBU_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U),     /*!< receive buffer unavailable status flag */
+    ENET_DMA_FLAG_RPS_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U),     /*!< receive process stopped status flag */
+    ENET_DMA_FLAG_RWT_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U),     /*!< receive watchdog timeout status flag */
+    ENET_DMA_FLAG_ET_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U),    /*!< early transmit status flag */
+    ENET_DMA_FLAG_FBE_CLR           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U),    /*!< fatal bus error status flag */
+    ENET_DMA_FLAG_ER_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U),    /*!< early receive status flag */
+    ENET_DMA_FLAG_AI_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U),    /*!< abnormal interrupt summary flag */
+    ENET_DMA_FLAG_NI_CLR            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U),    /*!< normal interrupt summary flag */                       
+}enet_flag_clear_enum;
+
+/* ENET interrupt enable/disable */
+typedef enum
+{
+    /* ENET_MAC_INTMSK register */
+    ENET_MAC_INT_WUMIM              = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U),   /*!< WUM interrupt mask */
+    ENET_MAC_INT_TMSTIM             = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U),   /*!< timestamp trigger interrupt mask */
+    /* ENET_MSC_RINTMSK register */ 
+    ENET_MSC_INT_RFCEIM             = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U),  /*!< received frame CRC error interrupt mask */
+    ENET_MSC_INT_RFAEIM             = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U),  /*!< received frames alignment error interrupt mask */
+    ENET_MSC_INT_RGUFIM             = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */
+    /* ENET_MSC_TINTMSK register */ 
+    ENET_MSC_INT_TGFSCIM            = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */
+    ENET_MSC_INT_TGFMSCIM           = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */
+    ENET_MSC_INT_TGFIM              = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */
+    /* ENET_DMA_INTEN register */ 
+    ENET_DMA_INT_TIE                = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U),    /*!< transmit interrupt enable */
+    ENET_DMA_INT_TPSIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U),    /*!< transmit process stopped interrupt enable */
+    ENET_DMA_INT_TBUIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U),    /*!< transmit buffer unavailable interrupt enable */
+    ENET_DMA_INT_TJTIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U),    /*!< transmit jabber timeout interrupt enable */
+    ENET_DMA_INT_ROIE               = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U),    /*!< receive overflow interrupt enable */
+    ENET_DMA_INT_TUIE               = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U),    /*!< transmit underflow interrupt enable */
+    ENET_DMA_INT_RIE                = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U),    /*!< receive interrupt enable */
+    ENET_DMA_INT_RBUIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U),    /*!< receive buffer unavailable interrupt enable */
+    ENET_DMA_INT_RPSIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U),    /*!< receive process stopped interrupt enable */
+    ENET_DMA_INT_RWTIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U),    /*!< receive watchdog timeout interrupt enable */
+    ENET_DMA_INT_ETIE               = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U),   /*!< early transmit interrupt enable */
+    ENET_DMA_INT_FBEIE              = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U),   /*!< fatal bus error interrupt enable */
+    ENET_DMA_INT_ERIE               = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U),   /*!< early receive interrupt enable */
+    ENET_DMA_INT_AIE                = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U),   /*!< abnormal interrupt summary enable */
+    ENET_DMA_INT_NIE                = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U),   /*!< normal interrupt summary enable */
+}enet_int_enum;
+ 
+/* ENET interrupt flag get */
+typedef enum
+{
+    /* ENET_MAC_INTF register */
+    ENET_MAC_INT_FLAG_WUM           = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U),     /*!< WUM status flag */
+    ENET_MAC_INT_FLAG_MSC           = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U),     /*!< MSC status flag */
+    ENET_MAC_INT_FLAG_MSCR          = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U),     /*!< MSC receive status flag */
+    ENET_MAC_INT_FLAG_MSCT          = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U),     /*!< MSC transmit status flag */
+    ENET_MAC_INT_FLAG_TMST          = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U),     /*!< timestamp trigger status flag */
+    /* ENET_MSC_RINTF register */
+    ENET_MSC_INT_FLAG_RFCE          = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U),    /*!< received frames CRC error flag */
+    ENET_MSC_INT_FLAG_RFAE          = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U),    /*!< received frames alignment error flag */
+    ENET_MSC_INT_FLAG_RGUF          = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U),   /*!< received good unicast frames flag */
+    /* ENET_MSC_TINTF register */
+    ENET_MSC_INT_FLAG_TGFSC         = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U),   /*!< transmitted good frames single collision flag */
+    ENET_MSC_INT_FLAG_TGFMSC        = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U),   /*!< transmitted good frames more single collision flag */
+    ENET_MSC_INT_FLAG_TGF           = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U),   /*!< transmitted good frames flag */
+    /* ENET_DMA_STAT register */
+    ENET_DMA_INT_FLAG_TS            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U),     /*!< transmit status flag */
+    ENET_DMA_INT_FLAG_TPS           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U),     /*!< transmit process stopped status flag */
+    ENET_DMA_INT_FLAG_TBU           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U),     /*!< transmit buffer unavailable status flag */
+    ENET_DMA_INT_FLAG_TJT           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U),     /*!< transmit jabber timeout status flag */
+    ENET_DMA_INT_FLAG_RO            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U),     /*!< receive overflow status flag */
+    ENET_DMA_INT_FLAG_TU            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U),     /*!< transmit underflow status flag */
+    ENET_DMA_INT_FLAG_RS            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U),     /*!< receive status flag */
+    ENET_DMA_INT_FLAG_RBU           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U),     /*!< receive buffer unavailable status flag */
+    ENET_DMA_INT_FLAG_RPS           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U),     /*!< receive process stopped status flag */
+    ENET_DMA_INT_FLAG_RWT           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U),     /*!< receive watchdog timeout status flag */
+    ENET_DMA_INT_FLAG_ET            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U),    /*!< early transmit status flag */
+    ENET_DMA_INT_FLAG_FBE           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U),    /*!< fatal bus error status flag */
+    ENET_DMA_INT_FLAG_ER            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U),    /*!< early receive status flag */
+    ENET_DMA_INT_FLAG_AI            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U),    /*!< abnormal interrupt summary flag */
+    ENET_DMA_INT_FLAG_NI            = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U),    /*!< normal interrupt summary flag */
+    ENET_DMA_INT_FLAG_MSC           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U),    /*!< MSC status flag */
+    ENET_DMA_INT_FLAG_WUM           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U),    /*!< WUM status flag */
+    ENET_DMA_INT_FLAG_TST           = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U),    /*!< timestamp trigger status flag */ 
+}enet_int_flag_enum;
+
+/* ENET interrupt flag clear */
+typedef enum
+{
+    /* ENET_DMA_STAT register */
+    ENET_DMA_INT_FLAG_TS_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U),     /*!< transmit status flag */
+    ENET_DMA_INT_FLAG_TPS_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U),     /*!< transmit process stopped status flag */
+    ENET_DMA_INT_FLAG_TBU_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U),     /*!< transmit buffer unavailable status flag */
+    ENET_DMA_INT_FLAG_TJT_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U),     /*!< transmit jabber timeout status flag */
+    ENET_DMA_INT_FLAG_RO_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U),     /*!< receive overflow status flag */
+    ENET_DMA_INT_FLAG_TU_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U),     /*!< transmit underflow status flag */
+    ENET_DMA_INT_FLAG_RS_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U),     /*!< receive status flag */
+    ENET_DMA_INT_FLAG_RBU_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U),     /*!< receive buffer unavailable status flag */
+    ENET_DMA_INT_FLAG_RPS_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U),     /*!< receive process stopped status flag */
+    ENET_DMA_INT_FLAG_RWT_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U),     /*!< receive watchdog timeout status flag */
+    ENET_DMA_INT_FLAG_ET_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U),    /*!< early transmit status flag */
+    ENET_DMA_INT_FLAG_FBE_CLR       = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U),    /*!< fatal bus error status flag */
+    ENET_DMA_INT_FLAG_ER_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U),    /*!< early receive status flag */
+    ENET_DMA_INT_FLAG_AI_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U),    /*!< abnormal interrupt summary flag */
+    ENET_DMA_INT_FLAG_NI_CLR        = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U),    /*!< normal interrupt summary flag */
+}enet_int_flag_clear_enum;
+
+/* current RX/TX descriptor/buffer/descriptor table address get */
+typedef enum
+{
+    ENET_RX_DESC_TABLE              = DMA_RDTADDR_REG_OFFSET,                       /*!< RX descriptor table */
+    ENET_RX_CURRENT_DESC            = DMA_CRDADDR_REG_OFFSET,                       /*!< current RX descriptor */
+    ENET_RX_CURRENT_BUFFER          = DMA_CRBADDR_REG_OFFSET,                       /*!< current RX buffer */
+    ENET_TX_DESC_TABLE              = DMA_TDTADDR_REG_OFFSET,                       /*!< TX descriptor table */
+    ENET_TX_CURRENT_DESC            = DMA_CTDADDR_REG_OFFSET,                       /*!< current TX descriptor */
+    ENET_TX_CURRENT_BUFFER          = DMA_CTBADDR_REG_OFFSET                        /*!< current TX buffer */
+}enet_desc_reg_enum;
+
+/* MAC statistics counter get */
+typedef enum
+{
+    ENET_MSC_TX_SCCNT               = MSC_SCCNT_REG_OFFSET,                         /*!< MSC transmitted good frames after a single collision counter */
+    ENET_MSC_TX_MSCCNT              = MSC_MSCCNT_REG_OFFSET,                        /*!< MSC transmitted good frames after more than a single collision counter */
+    ENET_MSC_TX_TGFCNT              = MSC_TGFCNT_REG_OFFSET,                        /*!< MSC transmitted good frames counter */
+    ENET_MSC_RX_RFCECNT             = MSC_RFCECNT_REG_OFFSET,                       /*!< MSC received frames with CRC error counter */
+    ENET_MSC_RX_RFAECNT             = MSC_RFAECNT_REG_OFFSET,                       /*!< MSC received frames with alignment error counter */
+    ENET_MSC_RX_RGUFCNT             = MSC_RGUFCNT_REG_OFFSET                        /*!< MSC received good unicast frames counter */
+}enet_msc_counter_enum; 
+
+/* function option, used for ENET initialization */
+typedef enum
+{
+    FORWARD_OPTION                  = BIT(0),                                       /*!< configure the frame forward related parameters */
+    DMABUS_OPTION                   = BIT(1),                                       /*!< configure the DMA bus mode related parameters */
+    DMA_MAXBURST_OPTION             = BIT(2),                                       /*!< configure the DMA max burst related parameters */
+    DMA_ARBITRATION_OPTION          = BIT(3),                                       /*!< configure the DMA arbitration related parameters */
+    STORE_OPTION                    = BIT(4),                                       /*!< configure the store forward mode related parameters */
+    DMA_OPTION                      = BIT(5),                                       /*!< configure the DMA control related parameters */
+    VLAN_OPTION                     = BIT(6),                                       /*!< configure the VLAN tag related parameters */
+    FLOWCTL_OPTION                  = BIT(7),                                       /*!< configure the flow control related parameters */
+    HASHH_OPTION                    = BIT(8),                                       /*!< configure the hash list high 32-bit related parameters */
+    HASHL_OPTION                    = BIT(9),                                       /*!< configure the hash list low 32-bit related parameters */
+    FILTER_OPTION                   = BIT(10),                                      /*!< configure the frame filter control related parameters */
+    HALFDUPLEX_OPTION               = BIT(11),                                      /*!< configure the halfduplex related parameters */
+    TIMER_OPTION                    = BIT(12),                                      /*!< configure the frame timer related parameters */
+    INTERFRAMEGAP_OPTION            = BIT(13),                                      /*!< configure the inter frame gap related parameters */
+}enet_option_enum;
+
+/* phy mode and mac loopback configurations */
+typedef enum
+{
+    ENET_AUTO_NEGOTIATION           = 0x01u,                                        /*!< PHY auto negotiation */
+    ENET_100M_FULLDUPLEX            = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM),        /*!< 100Mbit/s, full-duplex */
+    ENET_100M_HALFDUPLEX            = ENET_MAC_CFG_SPD ,                            /*!< 100Mbit/s, half-duplex */
+    ENET_10M_FULLDUPLEX             = ENET_MAC_CFG_DPM,                             /*!< 10Mbit/s, full-duplex */
+    ENET_10M_HALFDUPLEX             = (uint32_t)0x00000000U,                        /*!< 10Mbit/s, half-duplex */
+    ENET_LOOPBACKMODE               = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM)         /*!< MAC in loopback mode at the MII */
+}enet_mediamode_enum;
+
+/* IP frame checksum function */
+typedef enum
+{
+    ENET_NO_AUTOCHECKSUM                = (uint32_t)0x00000000U,                    /*!< disable IP frame checksum function */
+    ENET_AUTOCHECKSUM_DROP_FAILFRAMES   = ENET_MAC_CFG_IPFCO,                       /*!< enable IP frame checksum function */
+    ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame
+                                                                                         with only payload error but no other errors will not be dropped */
+}enet_chksumconf_enum;
+
+/* received frame filter function */
+typedef enum
+{
+    ENET_PROMISCUOUS_MODE           = ENET_MAC_FRMF_PM,                             /*!< promiscuous mode enabled */
+    ENET_RECEIVEALL                 = (int32_t)ENET_MAC_FRMF_FAR,                   /*!< all received frame are forwarded to application */
+    ENET_BROADCAST_FRAMES_PASS      = (uint32_t)0x00000000U,                        /*!< the address filters pass all received broadcast frames */
+    ENET_BROADCAST_FRAMES_DROP      = ENET_MAC_FRMF_BFRMD                           /*!< the address filters filter all incoming broadcast frames */
+}enet_frmrecept_enum;
+
+/* register group value get */
+typedef enum
+{
+    ALL_MAC_REG                     = 0,                                            /*!< MAC register group */
+    ALL_MSC_REG                     = 22,                                           /*!< MSC register group */
+    ALL_PTP_REG                     = 33,                                           /*!< PTP register group */
+    ALL_DMA_REG                     = 44,                                           /*!< DMA register group */
+}enet_registers_type_enum;
+
+/* dma direction select */
+typedef enum
+{
+    ENET_DMA_TX                     = ENET_DMA_STAT_TP,                             /*!< DMA transmit direction */
+    ENET_DMA_RX                     = ENET_DMA_STAT_RP                              /*!< DMA receive direction */
+}enet_dmadirection_enum;
+
+/* PHY operation direction select */
+typedef enum
+{
+    ENET_PHY_READ                   = (uint32_t)0x00000000,                         /*!< read PHY */
+    ENET_PHY_WRITE                  = ENET_MAC_PHY_CTL_PW                           /*!< write PHY */
+}enet_phydirection_enum;
+
+/* register operation direction select */
+typedef enum
+{
+    ENET_REG_READ,                                                                  /*!< read register */
+    ENET_REG_WRITE                                                                  /*!< write register */
+}enet_regdirection_enum;
+
+/* ENET MAC addresses */ 
+typedef enum
+{
+    ENET_MAC_ADDRESS0               = ((uint32_t)0x00000000),                       /*!< MAC address0 */
+    ENET_MAC_ADDRESS1               = ((uint32_t)0x00000008),                       /*!< MAC address1 */
+    ENET_MAC_ADDRESS2               = ((uint32_t)0x00000010),                       /*!< MAC address2 */
+    ENET_MAC_ADDRESS3               = ((uint32_t)0x00000018)                        /*!< MAC address3 */
+}enet_macaddress_enum;
+
+/* descriptor information */
+typedef enum
+{
+    TXDESC_COLLISION_COUNT,                                                         /*!< the number of collisions occurred before the frame was transmitted */
+    TXDESC_BUFFER_1_ADDR,                                                           /*!< transmit frame buffer 1 address */
+    RXDESC_FRAME_LENGTH,                                                            /*!< the byte length of the received frame that was transferred to the buffer */
+    RXDESC_BUFFER_1_SIZE,                                                           /*!< receive buffer 1 size */
+    RXDESC_BUFFER_2_SIZE,                                                           /*!< receive buffer 2 size */
+    RXDESC_BUFFER_1_ADDR                                                            /*!< receive frame buffer 1 address */
+}enet_descstate_enum;
+
+/* structure for initialization of the ENET  */
+typedef struct
+{
+    uint32_t option_enable;                                                         /*!< select which function to configure */
+    uint32_t forward_frame;                                                         /*!< frame forward related parameters */ 
+    uint32_t dmabus_mode;                                                           /*!< DMA bus mode related parameters */
+    uint32_t dma_maxburst;                                                          /*!< DMA max burst related parameters */
+    uint32_t dma_arbitration;                                                       /*!< DMA Tx and Rx arbitration related parameters */
+    uint32_t store_forward_mode;                                                    /*!< store forward mode related parameters */
+    uint32_t dma_function;                                                          /*!< DMA control related parameters */
+    uint32_t vlan_config;                                                           /*!< VLAN tag related parameters */   
+    uint32_t flow_control;                                                          /*!< flow control related parameters */
+    uint32_t hashtable_high;                                                        /*!< hash list high 32-bit related parameters */
+    uint32_t hashtable_low;                                                         /*!< hash list low 32-bit related parameters */
+    uint32_t framesfilter_mode;                                                     /*!< frame filter control related parameters */
+    uint32_t halfduplex_param;                                                      /*!< halfduplex related parameters */            
+    uint32_t timer_config;                                                          /*!< frame timer related parameters */
+    uint32_t interframegap;                                                         /*!< inter frame gap related parameters */
+}enet_initpara_struct;
+
+/* structure for ENET DMA desciptors */ 
+typedef struct  
+{
+    uint32_t status;                                                                /*!< status */
+    uint32_t control_buffer_size;                                                   /*!< control and buffer1, buffer2 lengths */
+    uint32_t buffer1_addr;                                                          /*!< buffer1 address pointer/timestamp low */
+    uint32_t buffer2_next_desc_addr;                                                /*!< buffer2 or next descriptor address pointer/timestamp high */
+} enet_descriptors_struct;
+
+/* structure of PTP system time */ 
+typedef struct
+{
+    uint32_t second;                                                                /*!< second of system time */
+    uint32_t nanosecond;                                                            /*!< nanosecond of system time */
+    uint32_t sign;                                                                  /*!< sign of system time */
+}enet_ptp_systime_struct;
+
+/* mac_cfg register value */
+#define MAC_CFG_BOL(regval)                       (BITS(5,6) & ((uint32_t)(regval) << 5))       /*!< write value to ENET_MAC_CFG_BOL bit field */
+#define ENET_BACKOFFLIMIT_10                      MAC_CFG_BOL(0)                                /*!< min (n, 10) */
+#define ENET_BACKOFFLIMIT_8                       MAC_CFG_BOL(1)                                /*!< min (n, 8) */
+#define ENET_BACKOFFLIMIT_4                       MAC_CFG_BOL(2)                                /*!< min (n, 4) */
+#define ENET_BACKOFFLIMIT_1                       MAC_CFG_BOL(3)                                /*!< min (n, 1) */ 
+
+#define MAC_CFG_IGBS(regval)                      (BITS(17,19) & ((uint32_t)(regval) << 17))    /*!< write value to ENET_MAC_CFG_IGBS bit field */
+#define ENET_INTERFRAMEGAP_96BIT                  MAC_CFG_IGBS(0)                               /*!< minimum 96 bit times */ 
+#define ENET_INTERFRAMEGAP_88BIT                  MAC_CFG_IGBS(1)                               /*!< minimum 88 bit times */
+#define ENET_INTERFRAMEGAP_80BIT                  MAC_CFG_IGBS(2)                               /*!< minimum 80 bit times */
+#define ENET_INTERFRAMEGAP_72BIT                  MAC_CFG_IGBS(3)                               /*!< minimum 72 bit times */
+#define ENET_INTERFRAMEGAP_64BIT                  MAC_CFG_IGBS(4)                               /*!< minimum 64 bit times */        
+#define ENET_INTERFRAMEGAP_56BIT                  MAC_CFG_IGBS(5)                               /*!< minimum 56 bit times */
+#define ENET_INTERFRAMEGAP_48BIT                  MAC_CFG_IGBS(6)                               /*!< minimum 48 bit times */
+#define ENET_INTERFRAMEGAP_40BIT                  MAC_CFG_IGBS(7)                               /*!< minimum 40 bit times */  
+
+#define ENET_WATCHDOG_ENABLE                      ((uint32_t)0x00000000U)                       /*!< the MAC allows no more than 2048 bytes of the frame being received */
+#define ENET_WATCHDOG_DISABLE                     ENET_MAC_CFG_WDD                              /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */
+ 
+#define ENET_JABBER_ENABLE                        ((uint32_t)0x00000000U)                       /*!< the maximum transmission byte is 2048 */
+#define ENET_JABBER_DISABLE                       ENET_MAC_CFG_JBD                              /*!< the maximum transmission byte can be 16384 */
+
+#define ENET_CARRIERSENSE_ENABLE                  ((uint32_t)0x00000000U)                       /*!< the MAC transmitter generates carrier sense error and aborts the transmission */
+#define ENET_CARRIERSENSE_DISABLE                 ENET_MAC_CFG_CSD                              /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */
+ 
+#define ENET_SPEEDMODE_10M                        ((uint32_t)0x00000000U)                       /*!< 10 Mbit/s */
+#define ENET_SPEEDMODE_100M                       ENET_MAC_CFG_SPD                              /*!< 100 Mbit/s */
+
+#define ENET_RECEIVEOWN_ENABLE                    ((uint32_t)0x00000000U)                       /*!< the MAC receives all packets that are given by the PHY while transmitting */
+#define ENET_RECEIVEOWN_DISABLE                   ENET_MAC_CFG_ROD                              /*!< the MAC disables the reception of frames in half-duplex mode */
+
+#define ENET_LOOPBACKMODE_ENABLE                  ENET_MAC_CFG_LBM                              /*!< the MAC operates in loopback mode at the MII */
+#define ENET_LOOPBACKMODE_DISABLE                 ((uint32_t)0x00000000U)                       /*!< the MAC operates in normal mode */
+
+#define ENET_MODE_FULLDUPLEX                      ENET_MAC_CFG_DPM                              /*!< full-duplex mode enable */
+#define ENET_MODE_HALFDUPLEX                      ((uint32_t)0x00000000U)                       /*!< half-duplex mode enable */
+
+#define ENET_CHECKSUMOFFLOAD_ENABLE               ENET_MAC_CFG_IPFCO                            /*!< IP frame checksum offload function enabled for received IP frame */
+#define ENET_CHECKSUMOFFLOAD_DISABLE              ((uint32_t)0x00000000U)                       /*!< the checksum offload function in the receiver is disabled */
+
+#define ENET_RETRYTRANSMISSION_ENABLE             ((uint32_t)0x00000000U)                       /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/
+#define ENET_RETRYTRANSMISSION_DISABLE            ENET_MAC_CFG_RTD                              /*!< the MAC attempts only 1 transmission */
+
+#define ENET_AUTO_PADCRC_DROP_ENABLE              ENET_MAC_CFG_APCD                             /*!< the MAC strips the Pad/FCS field on received frames */
+#define ENET_AUTO_PADCRC_DROP_DISABLE             ((uint32_t)0x00000000U)                       /*!< the MAC forwards all received frames without modify it */
+#define ENET_AUTO_PADCRC_DROP                     ENET_MAC_CFG_APCD                             /*!< the function of the MAC strips the Pad/FCS field on received frames */
+
+#define ENET_DEFERRALCHECK_ENABLE                 ENET_MAC_CFG_DFC                              /*!< the deferral check function is enabled in the MAC */
+#define ENET_DEFERRALCHECK_DISABLE                ((uint32_t)0x00000000U)                       /*!< the deferral check function is disabled */
+
+/* mac_frmf register value */
+#define MAC_FRMF_PCFRM(regval)                    (BITS(6,7) & ((uint32_t)(regval) << 6))       /*!< write value to ENET_MAC_FRMF_PCFRM bit field */
+#define ENET_PCFRM_PREVENT_ALL                    MAC_FRMF_PCFRM(0)                             /*!< MAC prevents all control frames from reaching the application */
+#define ENET_PCFRM_PREVENT_PAUSEFRAME             MAC_FRMF_PCFRM(1)                             /*!< MAC only forwards all other control frames except pause control frame */
+#define ENET_PCFRM_FORWARD_ALL                    MAC_FRMF_PCFRM(2)                             /*!< MAC forwards all control frames to application even if they fail the address filter */
+#define ENET_PCFRM_FORWARD_FILTERED               MAC_FRMF_PCFRM(3)                             /*!< MAC forwards control frames that only pass the address filter */
+ 
+#define ENET_RX_FILTER_DISABLE                    ENET_MAC_FRMF_FAR                             /*!< all received frame are forwarded to application */
+#define ENET_RX_FILTER_ENABLE                     ((uint32_t)0x00000000U)                       /*!< only the frame passed the filter can be forwarded to application */
+ 
+#define ENET_SRC_FILTER_NORMAL_ENABLE             ENET_MAC_FRMF_SAFLT                           /*!< filter source address */
+#define ENET_SRC_FILTER_INVERSE_ENABLE            (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT)  /*!< inverse source address filtering result */
+#define ENET_SRC_FILTER_DISABLE                   ((uint32_t)0x00000000U)                       /*!< source address function in filter disable */
+#define ENET_SRC_FILTER                           ENET_MAC_FRMF_SAFLT                           /*!< filter source address function */
+#define ENET_SRC_FILTER_INVERSE                   ENET_MAC_FRMF_SAIFLT                          /*!< inverse source address filtering result function */
+
+#define ENET_BROADCASTFRAMES_ENABLE               ((uint32_t)0x00000000U)                       /*!< the address filters pass all received broadcast frames */
+#define ENET_BROADCASTFRAMES_DISABLE              ENET_MAC_FRMF_BFRMD                           /*!< the address filters filter all incoming broadcast frames */
+ 
+#define ENET_DEST_FILTER_INVERSE_ENABLE           ENET_MAC_FRMF_DAIFLT                          /*!< inverse DA filtering result */
+#define ENET_DEST_FILTER_INVERSE_DISABLE          ((uint32_t)0x00000000U)                       /*!< not inverse DA filtering result */
+#define ENET_DEST_FILTER_INVERSE                  ENET_MAC_FRMF_DAIFLT                          /*!< inverse DA filtering result function */
+
+#define ENET_PROMISCUOUS_ENABLE                   ENET_MAC_FRMF_PM                              /*!< promiscuous mode enabled */
+#define ENET_PROMISCUOUS_DISABLE                  ((uint32_t)0x00000000U)                       /*!< promiscuous mode disabled */
+          
+#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT     (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT)     /*!< pass multicast frames that match either the perfect or the hash filtering */
+#define ENET_MULTICAST_FILTER_HASH                ENET_MAC_FRMF_HMF                             /*!< pass multicast frames that match the hash filtering */
+#define ENET_MULTICAST_FILTER_PERFECT             ((uint32_t)0x00000000U)                       /*!< pass multicast frames that match the perfect filtering */
+#define ENET_MULTICAST_FILTER_NONE                ENET_MAC_FRMF_MFD                             /*!< all multicast frames are passed */
+#define ENET_MULTICAST_FILTER_PASS                ENET_MAC_FRMF_MFD                             /*!< pass all multicast frames function */
+#define ENET_MULTICAST_FILTER_HASH_MODE           ENET_MAC_FRMF_HMF                             /*!< HASH multicast filter function */
+#define ENET_FILTER_MODE_EITHER                   ENET_MAC_FRMF_HPFLT                           /*!< HASH or perfect filter function */
+
+#define ENET_UNICAST_FILTER_EITHER                (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT)     /*!< pass unicast frames that match either the perfect or the hash filtering */
+#define ENET_UNICAST_FILTER_HASH                  ENET_MAC_FRMF_HUF                             /*!< pass unicast frames that match the hash filtering */
+#define ENET_UNICAST_FILTER_PERFECT               ((uint32_t)0x00000000U)                       /*!< pass unicast frames that match the perfect filtering */
+#define ENET_UNICAST_FILTER_HASH_MODE             ENET_MAC_FRMF_HUF                             /*!< HASH unicast filter function */
+
+/* mac_phy_ctl register value */
+#define MAC_PHY_CTL_CLR(regval)                   (BITS(2,4) & ((uint32_t)(regval) << 2))       /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */
+#define ENET_MDC_HCLK_DIV42                       MAC_PHY_CTL_CLR(0)                            /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */
+#define ENET_MDC_HCLK_DIV62                       MAC_PHY_CTL_CLR(1)                            /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */
+#define ENET_MDC_HCLK_DIV16                       MAC_PHY_CTL_CLR(2)                            /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */
+#define ENET_MDC_HCLK_DIV26                       MAC_PHY_CTL_CLR(3)                            /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */
+
+#define MAC_PHY_CTL_PR(regval)                    (BITS(6,10) & ((uint32_t)(regval) << 6))      /*!< write value to ENET_MAC_PHY_CTL_PR bit field */
+
+#define MAC_PHY_CTL_PA(regval)                    (BITS(11,15) & ((uint32_t)(regval) << 11))    /*!< write value to ENET_MAC_PHY_CTL_PA bit field */
+
+/* mac_phy_data register value */
+#define MAC_PHY_DATA_PD(regval)                   (BITS(0,15) & ((uint32_t)(regval) << 0))      /*!< write value to ENET_MAC_PHY_DATA_PD bit field */
+
+/* mac_fctl register value */
+#define MAC_FCTL_PLTS(regval)                     (BITS(4,5) & ((uint32_t)(regval) << 4))       /*!< write value to ENET_MAC_FCTL_PLTS bit field */
+#define ENET_PAUSETIME_MINUS4                     MAC_FCTL_PLTS(0)                              /*!< pause time minus 4 slot times */
+#define ENET_PAUSETIME_MINUS28                    MAC_FCTL_PLTS(1)                              /*!< pause time minus 28 slot times */
+#define ENET_PAUSETIME_MINUS144                   MAC_FCTL_PLTS(2)                              /*!< pause time minus 144 slot times */
+#define ENET_PAUSETIME_MINUS256                   MAC_FCTL_PLTS(3)                              /*!< pause time minus 256 slot times */ 
+
+#define ENET_ZERO_QUANTA_PAUSE_ENABLE             ((uint32_t)0x00000000U)                       /*!< enable the automatic zero-quanta generation function */
+#define ENET_ZERO_QUANTA_PAUSE_DISABLE            ENET_MAC_FCTL_DZQP                            /*!< disable the automatic zero-quanta generation function */
+#define ENET_ZERO_QUANTA_PAUSE                    ENET_MAC_FCTL_DZQP                            /*!< the automatic zero-quanta generation function */
+
+#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT  ENET_MAC_FCTL_UPFDT                           /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */
+#define ENET_UNIQUE_PAUSEDETECT                   ((uint32_t)0x00000000U)                       /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */
+ 
+#define ENET_RX_FLOWCONTROL_ENABLE                ENET_MAC_FCTL_RFCEN                           /*!< enable decoding function for the received pause frame and process it */
+#define ENET_RX_FLOWCONTROL_DISABLE               ((uint32_t)0x00000000U)                       /*!< decode function for pause frame is disabled */
+#define ENET_RX_FLOWCONTROL                       ENET_MAC_FCTL_RFCEN                           /*!< decoding function for the received pause frame and process it */
+
+#define ENET_TX_FLOWCONTROL_ENABLE                ENET_MAC_FCTL_TFCEN                           /*!< enable the flow control operation in the MAC */
+#define ENET_TX_FLOWCONTROL_DISABLE               ((uint32_t)0x00000000U)                       /*!< disable the flow control operation in the MAC */
+#define ENET_TX_FLOWCONTROL                       ENET_MAC_FCTL_TFCEN                           /*!< the flow control operation in the MAC */
+
+#define ENET_BACK_PRESSURE_ENABLE                 ENET_MAC_FCTL_FLCBBKPA                        /*!< enable the back pressure operation in the MAC */
+#define ENET_BACK_PRESSURE_DISABLE                ((uint32_t)0x00000000U)                       /*!< disable the back pressure operation in the MAC */
+#define ENET_BACK_PRESSURE                        ENET_MAC_FCTL_FLCBBKPA                        /*!< the back pressure operation in the MAC */
+                                                                                      
+#define MAC_FCTL_PTM(regval)                      (BITS(16,31) & ((uint32_t)(regval) << 16))    /*!< write value to ENET_MAC_FCTL_PTM bit field */
+/* mac_vlt register value */
+#define MAC_VLT_VLTI(regval)                      (BITS(0,15) & ((uint32_t)(regval) << 0))      /*!< write value to ENET_MAC_VLT_VLTI bit field */
+ 
+#define ENET_VLANTAGCOMPARISON_12BIT              ENET_MAC_VLT_VLTC                             /*!< only low 12 bits of the VLAN tag are used for comparison */
+#define ENET_VLANTAGCOMPARISON_16BIT              ((uint32_t)0x00000000U)                       /*!< all 16 bits of the VLAN tag are used for comparison */
+
+/* mac_wum register value */ 
+#define ENET_WUM_FLAG_WUFFRPR                     ENET_MAC_WUM_WUFFRPR                          /*!< wakeup frame filter register poniter reset */
+#define ENET_WUM_FLAG_WUFR                        ENET_MAC_WUM_WUFR                             /*!< wakeup frame received */
+#define ENET_WUM_FLAG_MPKR                        ENET_MAC_WUM_MPKR                             /*!< magic packet received */
+#define ENET_WUM_POWER_DOWN                       ENET_MAC_WUM_PWD                              /*!< power down mode */    
+#define ENET_WUM_MAGIC_PACKET_FRAME               ENET_MAC_WUM_MPEN                             /*!< enable a wakeup event due to magic packet reception */   
+#define ENET_WUM_WAKE_UP_FRAME                    ENET_MAC_WUM_WFEN                             /*!< enable a wakeup event due to wakeup frame reception */     
+#define ENET_WUM_GLOBAL_UNICAST                   ENET_MAC_WUM_GU                               /*!< any received unicast frame passed filter is considered to be a wakeup frame */
+
+/* mac_addr0h register value */
+#define MAC_ADDR0H_ADDR0H(regval)                 (BITS(0,15) & ((uint32_t)(regval) << 0))      /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */
+
+/* mac_addrxh register value, x = 1,2,3 */
+#define MAC_ADDR123H_ADDR123H(regval)             (BITS(0,15) & ((uint32_t)(regval) << 0))      /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */
+
+#define ENET_ADDRESS_MASK_BYTE0                   BIT(24)                                       /*!< low register bits [7:0] */
+#define ENET_ADDRESS_MASK_BYTE1                   BIT(25)                                       /*!< low register bits [15:8] */
+#define ENET_ADDRESS_MASK_BYTE2                   BIT(26)                                       /*!< low register bits [23:16] */
+#define ENET_ADDRESS_MASK_BYTE3                   BIT(27)                                       /*!< low register bits [31:24] */
+#define ENET_ADDRESS_MASK_BYTE4                   BIT(28)                                       /*!< high register bits [7:0] */
+#define ENET_ADDRESS_MASK_BYTE5                   BIT(29)                                       /*!< high register bits [15:8] */
+
+#define ENET_ADDRESS_FILTER_SA                    BIT(30)                                       /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */
+#define ENET_ADDRESS_FILTER_DA                    ((uint32_t)0x00000000)                        /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */
+ 
+/* mac_fcth register value */
+#define MAC_FCTH_RFA(regval)                      ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8)  /*!< write value to ENET_MAC_FCTH_RFA bit field */
+#define ENET_ACTIVE_THRESHOLD_256BYTES            MAC_FCTH_RFA(0)                               /*!< threshold level is 256 bytes */
+#define ENET_ACTIVE_THRESHOLD_512BYTES            MAC_FCTH_RFA(1)                               /*!< threshold level is 512 bytes */
+#define ENET_ACTIVE_THRESHOLD_768BYTES            MAC_FCTH_RFA(2)                               /*!< threshold level is 768 bytes */
+#define ENET_ACTIVE_THRESHOLD_1024BYTES           MAC_FCTH_RFA(3)                               /*!< threshold level is 1024 bytes */
+#define ENET_ACTIVE_THRESHOLD_1280BYTES           MAC_FCTH_RFA(4)                               /*!< threshold level is 1280 bytes */
+#define ENET_ACTIVE_THRESHOLD_1536BYTES           MAC_FCTH_RFA(5)                               /*!< threshold level is 1536 bytes */
+#define ENET_ACTIVE_THRESHOLD_1792BYTES           MAC_FCTH_RFA(6)                               /*!< threshold level is 1792 bytes */
+
+#define MAC_FCTH_RFD(regval)                      ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8)  /*!< write value to ENET_MAC_FCTH_RFD bit field */
+#define ENET_DEACTIVE_THRESHOLD_256BYTES          MAC_FCTH_RFD(0)                               /*!< threshold level is 256 bytes */
+#define ENET_DEACTIVE_THRESHOLD_512BYTES          MAC_FCTH_RFD(1)                               /*!< threshold level is 512 bytes */
+#define ENET_DEACTIVE_THRESHOLD_768BYTES          MAC_FCTH_RFD(2)                               /*!< threshold level is 768 bytes */
+#define ENET_DEACTIVE_THRESHOLD_1024BYTES         MAC_FCTH_RFD(3)                               /*!< threshold level is 1024 bytes */
+#define ENET_DEACTIVE_THRESHOLD_1280BYTES         MAC_FCTH_RFD(4)                               /*!< threshold level is 1280 bytes */
+#define ENET_DEACTIVE_THRESHOLD_1536BYTES         MAC_FCTH_RFD(5)                               /*!< threshold level is 1536 bytes */
+#define ENET_DEACTIVE_THRESHOLD_1792BYTES         MAC_FCTH_RFD(6)                               /*!< threshold level is 1792 bytes */
+
+/* msc_ctl register value */
+#define ENET_MSC_COUNTER_STOP_ROLLOVER            ENET_MSC_CTL_CTSR                             /*!< counter stop rollover */
+#define ENET_MSC_RESET_ON_READ                    ENET_MSC_CTL_RTOR                             /*!< reset on read */
+#define ENET_MSC_COUNTERS_FREEZE                  ENET_MSC_CTL_MCFZ                             /*!< MSC counter freeze */
+
+/* ptp_tsctl register value */
+#define ENET_RXTX_TIMESTAMP                       ENET_PTP_TSCTL_TMSEN                          /*!< enable timestamp function for transmit and receive frames */
+#define ENET_PTP_TIMESTAMP_INT                    ENET_PTP_TSCTL_TMSITEN                        /*!< timestamp interrupt trigger enable */
+
+/* ptp_ssinc register value */
+#define PTP_SSINC_STMSSI(regval)                  (BITS(0,7) & ((uint32_t)(regval) << 0))       /*!< write value to ENET_PTP_SSINC_STMSSI bit field */
+
+/* ptp_tsl register value */
+#define GET_PTP_TSL_STMSS(regval)                 GET_BITS((uint32_t)(regval),0,30)             /*!< get value of ENET_PTP_TSL_STMSS bit field */
+ 
+#define ENET_PTP_TIME_POSITIVE                    ((uint32_t)0x00000000)                        /*!< time value is positive */
+#define ENET_PTP_TIME_NEGATIVE                    ENET_PTP_TSL_STS                              /*!< time value is negative */
+
+#define GET_PTP_TSL_STS(regval)                   (((regval) & BIT(31)) >> (31U))               /*!< get value of ENET_PTP_TSL_STS bit field */
+
+/* ptp_tsul register value */
+#define PTP_TSUL_TMSUSS(regval)                   (BITS(0,30) & ((uint32_t)(regval) << 0))      /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */
+
+#define ENET_PTP_ADD_TO_TIME                      ((uint32_t)0x00000000)                        /*!< timestamp update value is added to system time */
+#define ENET_PTP_SUBSTRACT_FROM_TIME              ENET_PTP_TSUL_TMSUPNS                         /*!< timestamp update value is subtracted from system time */
+
+/* dma_bctl register value */
+#define DMA_BCTL_DPSL(regval)                     (BITS(2,6) & ((uint32_t)(regval) << 2))       /*!< write value to ENET_DMA_BCTL_DPSL bit field */
+#define GET_DMA_BCTL_DPSL(regval)                 GET_BITS((regval),2,6)                        /*!< get value of ENET_DMA_BCTL_DPSL bit field */
+
+#define DMA_BCTL_PGBL(regval)                     (BITS(8,13) & ((uint32_t)(regval) << 8))      /*!< write value to ENET_DMA_BCTL_PGBL bit field */
+#define ENET_PGBL_1BEAT                           DMA_BCTL_PGBL(1)                              /*!< maximum number of beats is 1 */
+#define ENET_PGBL_2BEAT                           DMA_BCTL_PGBL(2)                              /*!< maximum number of beats is 2 */
+#define ENET_PGBL_4BEAT                           DMA_BCTL_PGBL(4)                              /*!< maximum number of beats is 4 */
+#define ENET_PGBL_8BEAT                           DMA_BCTL_PGBL(8)                              /*!< maximum number of beats is 8 */
+#define ENET_PGBL_16BEAT                          DMA_BCTL_PGBL(16)                             /*!< maximum number of beats is 16 */
+#define ENET_PGBL_32BEAT                          DMA_BCTL_PGBL(32)                             /*!< maximum number of beats is 32 */                
+#define ENET_PGBL_4xPGBL_4BEAT                    (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats is 4 */
+#define ENET_PGBL_4xPGBL_8BEAT                    (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats is 8 */
+#define ENET_PGBL_4xPGBL_16BEAT                   (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats is 16 */
+#define ENET_PGBL_4xPGBL_32BEAT                   (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats is 32 */
+#define ENET_PGBL_4xPGBL_64BEAT                   (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL)        /*!< maximum number of beats is 64 */
+#define ENET_PGBL_4xPGBL_128BEAT                  (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL)        /*!< maximum number of beats is 128 */
+
+#define DMA_BCTL_RTPR(regval)                     (BITS(14,15) & ((uint32_t)(regval) << 14))    /*!< write value to ENET_DMA_BCTL_RTPR bit field */
+#define ENET_ARBITRATION_RXTX_1_1                 DMA_BCTL_RTPR(0)                              /*!< receive and transmit priority ratio is 1:1*/
+#define ENET_ARBITRATION_RXTX_2_1                 DMA_BCTL_RTPR(1)                              /*!< receive and transmit priority ratio is 2:1*/
+#define ENET_ARBITRATION_RXTX_3_1                 DMA_BCTL_RTPR(2)                              /*!< receive and transmit priority ratio is 3:1 */
+#define ENET_ARBITRATION_RXTX_4_1                 DMA_BCTL_RTPR(3)                              /*!< receive and transmit priority ratio is 4:1 */  
+#define ENET_ARBITRATION_RXPRIORTX                ENET_DMA_BCTL_DAB                             /*!< RxDMA has higher priority than TxDMA */
+
+#define ENET_FIXED_BURST_ENABLE                   ENET_DMA_BCTL_FB                              /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */
+#define ENET_FIXED_BURST_DISABLE                  ((uint32_t)0x00000000)                        /*!< AHB can use SINGLE/INCR burst transfer operations */
+
+#define DMA_BCTL_RXDP(regval)                     (BITS(17,22) & ((uint32_t)(regval) << 17))    /*!< write value to ENET_DMA_BCTL_RXDP bit field */
+#define ENET_RXDP_1BEAT                           DMA_BCTL_RXDP(1)                              /*!< maximum number of beats 1 */
+#define ENET_RXDP_2BEAT                           DMA_BCTL_RXDP(2)                              /*!< maximum number of beats 2 */
+#define ENET_RXDP_4BEAT                           DMA_BCTL_RXDP(4)                              /*!< maximum number of beats 4 */
+#define ENET_RXDP_8BEAT                           DMA_BCTL_RXDP(8)                              /*!< maximum number of beats 8 */
+#define ENET_RXDP_16BEAT                          DMA_BCTL_RXDP(16)                             /*!< maximum number of beats 16 */
+#define ENET_RXDP_32BEAT                          DMA_BCTL_RXDP(32)                             /*!< maximum number of beats 32 */                
+#define ENET_RXDP_4xPGBL_4BEAT                    (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats 4 */
+#define ENET_RXDP_4xPGBL_8BEAT                    (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats 8 */
+#define ENET_RXDP_4xPGBL_16BEAT                   (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats 16 */
+#define ENET_RXDP_4xPGBL_32BEAT                   (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL)         /*!< maximum number of beats 32 */
+#define ENET_RXDP_4xPGBL_64BEAT                   (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL)        /*!< maximum number of beats 64 */
+#define ENET_RXDP_4xPGBL_128BEAT                  (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL)        /*!< maximum number of beats 128 */  
+
+#define ENET_RXTX_DIFFERENT_PGBL                  ENET_DMA_BCTL_UIP                             /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */
+#define ENET_RXTX_SAME_PGBL                       ((uint32_t)0x00000000)                        /*!< RxDMA/TxDMA uses PGBL[5:0] */
+
+#define ENET_ADDRESS_ALIGN_ENABLE                 ENET_DMA_BCTL_AA                              /*!< enabled address-aligned */
+#define ENET_ADDRESS_ALIGN_DISABLE                ((uint32_t)0x00000000)                        /*!< disable address-aligned */
+
+/* dma_stat register value */
+#define GET_DMA_STAT_RP(regval)                   GET_BITS((uint32_t)(regval),17,19)            /*!< get value of ENET_DMA_STAT_RP bit field */
+#define ENET_RX_STATE_STOPPED                     ((uint32_t)0x00000000)                        /*!< reset or stop rx command issued */
+#define ENET_RX_STATE_FETCHING                    BIT(17)                                       /*!< fetching the Rx descriptor */
+#define ENET_RX_STATE_WAITING                     (BIT(17)|BIT(18))                             /*!< waiting for receive packet */
+#define ENET_RX_STATE_SUSPENDED                   BIT(19)                                       /*!< Rx descriptor unavailable */
+#define ENET_RX_STATE_CLOSING                     (BIT(17)|BIT(19))                             /*!< closing receive descriptor */
+#define ENET_RX_STATE_QUEUING                     ENET_DMA_STAT_RP                              /*!< transferring the receive packet data from recevie buffer to host memory */
+
+#define GET_DMA_STAT_TP(regval)                   GET_BITS((uint32_t)(regval),20,22)            /*!< get value of ENET_DMA_STAT_TP bit field */
+#define ENET_TX_STATE_STOPPED                     ((uint32_t)0x00000000)                        /*!< reset or stop Tx Command issued  */
+#define ENET_TX_STATE_FETCHING                    BIT(20)                                       /*!< fetching the Tx descriptor */
+#define ENET_TX_STATE_WAITING                     BIT(21)                                       /*!< waiting for status */
+#define ENET_TX_STATE_READING                     (BIT(20)|BIT(21))                             /*!< reading the data from host memory buffer and queuing it to transmit buffer */
+#define ENET_TX_STATE_SUSPENDED                   (BIT(21)|BIT(22))                             /*!< Tx descriptor unavailabe or transmit buffer underflow */
+#define ENET_TX_STATE_CLOSING                     ENET_DMA_STAT_TP                              /*!< closing Tx descriptor */
+
+#define GET_DMA_STAT_EB(regval)                   GET_BITS((uint32_t)(regval),23,25)            /*!< get value of ENET_DMA_STAT_EB bit field */
+#define ENET_ERROR_TXDATA_TRANSFER                BIT(23)                                       /*!< error during data transfer by TxDMA or RxDMA */
+#define ENET_ERROR_READ_TRANSFER                  BIT(24)                                       /*!< error during write transfer or read transfer */
+#define ENET_ERROR_DESC_ACCESS                    BIT(25)                                       /*!< error during descriptor or buffer access */
+
+/* dma_ctl register value */
+#define DMA_CTL_RTHC(regval)                      (BITS(3,4) & ((uint32_t)(regval) << 3))       /*!< write value to ENET_DMA_CTL_RTHC bit field */
+#define ENET_RX_THRESHOLD_64BYTES                 DMA_CTL_RTHC(0)                               /*!< threshold level is 64 Bytes */
+#define ENET_RX_THRESHOLD_32BYTES                 DMA_CTL_RTHC(1)                               /*!< threshold level is 32 Bytes */
+#define ENET_RX_THRESHOLD_96BYTES                 DMA_CTL_RTHC(2)                               /*!< threshold level is 96 Bytes */
+#define ENET_RX_THRESHOLD_128BYTES                DMA_CTL_RTHC(3)                               /*!< threshold level is 128 Bytes */
+
+#define DMA_CTL_TTHC(regval)                      (BITS(14,16) & ((uint32_t)(regval) << 14))    /*!< write value to ENET_DMA_CTL_TTHC bit field */
+#define ENET_TX_THRESHOLD_64BYTES                 DMA_CTL_TTHC(0)                               /*!< threshold level is 64 Bytes */
+#define ENET_TX_THRESHOLD_128BYTES                DMA_CTL_TTHC(1)                               /*!< threshold level is 128 Bytes */
+#define ENET_TX_THRESHOLD_192BYTES                DMA_CTL_TTHC(2)                               /*!< threshold level is 192 Bytes */
+#define ENET_TX_THRESHOLD_256BYTES                DMA_CTL_TTHC(3)                               /*!< threshold level is 256 Bytes */
+#define ENET_TX_THRESHOLD_40BYTES                 DMA_CTL_TTHC(4)                               /*!< threshold level is 40 Bytes */
+#define ENET_TX_THRESHOLD_32BYTES                 DMA_CTL_TTHC(5)                               /*!< threshold level is 32 Bytes */
+#define ENET_TX_THRESHOLD_24BYTES                 DMA_CTL_TTHC(6)                               /*!< threshold level is 24 Bytes */
+#define ENET_TX_THRESHOLD_16BYTES                 DMA_CTL_TTHC(7)                               /*!< threshold level is 16 Bytes */
+
+#define ENET_TCPIP_CKSUMERROR_ACCEPT              ENET_DMA_CTL_DTCERFD                          /*!< Rx frame with only payload error but no other errors will not be dropped */
+#define ENET_TCPIP_CKSUMERROR_DROP                ((uint32_t)0x00000000)                        /*!< all error frames will be dropped when FERF = 0 */
+
+#define ENET_RX_MODE_STOREFORWARD                 ENET_DMA_CTL_RSFD                             /*!< RxFIFO operates in store-and-forward mode */
+#define ENET_RX_MODE_CUTTHROUGH                   ((uint32_t)0x00000000)                        /*!< RxFIFO operates in cut-through mode */
+
+#define ENET_FLUSH_RXFRAME_ENABLE                 ((uint32_t)0x00000000)                        /*!< RxDMA flushes all frames */
+#define ENET_FLUSH_RXFRAME_DISABLE                ENET_DMA_CTL_DAFRF                            /*!< RxDMA does not flush any frames */
+#define ENET_NO_FLUSH_RXFRAME                     ENET_DMA_CTL_DAFRF                            /*!< RxDMA does not flush frames function */
+
+#define ENET_TX_MODE_STOREFORWARD                 ENET_DMA_CTL_TSFD                             /*!< TxFIFO operates in store-and-forward mode */
+#define ENET_TX_MODE_CUTTHROUGH                   ((uint32_t)0x00000000)                        /*!< TxFIFO operates in cut-through mode */
+
+#define ENET_FORWARD_ERRFRAMES_ENABLE             (ENET_DMA_CTL_FERF << 2)                      /*!< all frame received with error except runt error are forwarded to memory */
+#define ENET_FORWARD_ERRFRAMES_DISABLE            ((uint32_t)0x00000000)                        /*!< RxFIFO drop error frame */
+#define ENET_FORWARD_ERRFRAMES                    (ENET_DMA_CTL_FERF << 2)                      /*!< the function that all frame received with error except runt error are forwarded to memory */
+
+#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE    (ENET_DMA_CTL_FUF << 2)                       /*!< forward undersized good frames */
+#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE   ((uint32_t)0x00000000)                        /*!< RxFIFO drops all frames whose length is less than 64 bytes */
+#define ENET_FORWARD_UNDERSZ_GOODFRAMES           (ENET_DMA_CTL_FUF << 2)                       /*!< the function that forwarding undersized good frames */
+
+#define ENET_SECONDFRAME_OPT_ENABLE               ENET_DMA_CTL_OSF                              /*!< TxDMA controller operate on second frame mode enable*/
+#define ENET_SECONDFRAME_OPT_DISABLE              ((uint32_t)0x00000000)                        /*!< TxDMA controller operate on second frame mode disable */
+#define ENET_SECONDFRAME_OPT                      ENET_DMA_CTL_OSF                              /*!< TxDMA controller operate on second frame function */
+
+/* dma_mfbocnt register value */
+#define GET_DMA_MFBOCNT_MSFC(regval)              GET_BITS((regval),0,15)                       /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */
+
+#define GET_DMA_MFBOCNT_MSFA(regval)              GET_BITS((regval),17,27)                      /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */
+
+/* dma tx descriptor tdes0 register value */
+#define TDES0_CONT(regval)                        (BITS(3,6) & ((uint32_t)(regval) << 3))       /*!< write value to ENET DMA TDES0 CONT bit field */
+#define GET_TDES0_COCNT(regval)                   GET_BITS((regval),3,6)                        /*!< get value of ENET DMA TDES0 CONT bit field */
+
+#define TDES0_CM(regval)                          (BITS(22,23) & ((uint32_t)(regval) << 22))    /*!< write value to ENET DMA TDES0 CM bit field */
+#define ENET_CHECKSUM_DISABLE                     TDES0_CM(0)                                   /*!< checksum insertion disabled */ 
+#define ENET_CHECKSUM_IPV4HEADER                  TDES0_CM(1)                                   /*!< only IP header checksum calculation and insertion are enabled */ 
+#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT          TDES0_CM(2)                                   /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header  */ 
+#define ENET_CHECKSUM_TCPUDPICMP_FULL             TDES0_CM(3)                                   /*!< TCP/UDP/ICMP checksum insertion fully calculated */ 
+
+/* dma tx descriptor tdes1 register value */
+#define TDES1_TB1S(regval)                        (BITS(0,12) & ((uint32_t)(regval) << 0))      /*!< write value to ENET DMA TDES1 TB1S bit field */
+
+#define TDES1_TB2S(regval)                        (BITS(16,28) & ((uint32_t)(regval) << 16))    /*!< write value to ENET DMA TDES1 TB2S bit field */
+
+/* dma rx descriptor rdes0 register value */
+#define RDES0_FRML(regval)                        (BITS(16,29) & ((uint32_t)(regval) << 16))    /*!< write value to ENET DMA RDES0 FRML bit field */
+#define GET_RDES0_FRML(regval)                    GET_BITS((regval),16,29)                      /*!< get value of ENET DMA RDES0 FRML bit field */
+
+/* dma rx descriptor rdes1 register value */
+#define ENET_RECEIVE_COMPLETE_INT_ENABLE          ((uint32_t)0x00000000U)                       /*!< RS bit immediately set after Rx completed */
+#define ENET_RECEIVE_COMPLETE_INT_DISABLE         ENET_RDES1_DINTC                              /*!< RS bit not immediately set after Rx completed */
+
+#define GET_RDES1_RB1S(regval)                    GET_BITS((regval),0,12)                       /*!< get value of ENET DMA RDES1 RB1S bit field */
+
+#define GET_RDES1_RB2S(regval)                    GET_BITS((regval),16,28)                      /*!< get value of ENET DMA RDES1 RB2S bit field */
+
+/* dma rx descriptor rdes4 register value */
+#define RDES4_IPPLDT(regval)                      (BITS(0,2) & ((uint32_t)(regval) << 0))       /*!< write value to ENET DMA RDES4 IPPLDT bit field */
+#define GET_RDES4_IPPLDT(regval)                  GET_BITS((regval),0,2)                        /*!< get value of ENET DMA RDES4 IPPLDT bit field */
+
+#define RDES4_PTPMT(regval)                       (BITS(8,11) & ((uint32_t)(regval) << 8))      /*!< write value to ENET DMA RDES4 PTPMT bit field */
+#define GET_RDES4_PTPMT(regval)                   GET_BITS((regval),8,11)                       /*!< get value of ENET DMA RDES4 PTPMT bit field */
+
+/* ENET register mask value */
+#define MAC_CFG_MASK                              ((uint32_t)0xFD30810FU)                       /*!< ENET_MAC_CFG register mask */
+#define MAC_FCTL_MASK                             ((uint32_t)0x0000FF41U)                       /*!< ENET_MAC_FCTL register mask */
+#define DMA_CTL_MASK                              ((uint32_t)0xF8DE3F23U)                       /*!< ENET_DMA_CTL register mask */
+#define DMA_BCTL_MASK                             ((uint32_t)0xF800007DU)                       /*!< ENET_DMA_BCTL register mask */
+
+#define ETH_DMATXDESC_SIZE                        0x10U                                         /*!< TxDMA descriptor size */
+#define ETH_DMARXDESC_SIZE                        0x10U                                         /*!< RxDMA descriptor size */
+
+typedef enum{
+    ENET_PTP_SYSTIME_INIT             = ENET_PTP_TSCTL_TMSSTI,                                  /*!< timestamp initialize */
+    ENET_PTP_SYSTIME_UPDATE           = ENET_PTP_TSCTL_TMSSTU,                                  /*!< timestamp update */ 
+    ENET_PTP_ADDEND_UPDATE            = ENET_PTP_TSCTL_TMSARU,                                  /*!< addend register update */
+    ENET_PTP_FINEMODE                 = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)),              /*!< the system timestamp uses the fine method for updating */
+    ENET_PTP_COARSEMODE               = ENET_PTP_TSCTL_TMSFCU,                                  /*!< the system timestamp uses the coarse method for updating */
+}enet_ptp_function_enum;
+
+
+/* ENET remote wake-up frame register length */
+#define ETH_WAKEUP_REGISTER_LENGTH                8U                                            /*!< remote wake-up frame register length */
+
+/* ENET frame size */ 
+#define ENET_MAX_FRAME_SIZE                       1524U                                         /*!< header + frame_extra + payload + CRC */    
+
+/* ENET delay timeout */
+#define ENET_DELAY_TO                             ((uint32_t)0x0004FFFFU)                       /*!< ENET delay timeout */
+#define ENET_RESET_TO                             ((uint32_t)0x000004FFU)                       /*!< ENET reset timeout */
+
+/* function declarations */
+/* main function */
+/* deinitialize the ENET, and reset structure parameters for ENET initialization */
+void enet_deinit(void);
+/* configure the parameters which are usually less cared for initialization */
+void enet_initpara_config(enet_option_enum option, uint32_t para);
+/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */
+ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept);
+/* reset all core internal registers located in CLK_TX and CLK_RX */
+ErrStatus enet_software_reset(void);
+/* check receive frame valid and return frame size */
+uint32_t enet_rxframe_size_get(void);
+/* initialize the dma tx/rx descriptors's parameters in chain mode */
+void enet_descriptors_chain_init(enet_dmadirection_enum direction);
+/* initialize the dma tx/rx descriptors's parameters in ring mode */
+void enet_descriptors_ring_init(enet_dmadirection_enum direction);
+/* handle current received frame data to application buffer */
+ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize);
+/* handle current received frame but without data copy to application buffer */
+#define ENET_NOCOPY_FRAME_RECEIVE()         enet_frame_receive(NULL, 0U)
+/* handle application buffer data to transmit it */
+ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length);
+/* handle current transmit frame but without data copy from application buffer */
+#define ENET_NOCOPY_FRAME_TRANSMIT(len)     enet_frame_transmit(NULL, (len))
+/* configure the transmit IP frame checksum offload calculation and insertion */
+void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum);
+/* ENET Tx and Rx function enable (include MAC and DMA module) */
+void enet_enable(void);   
+/* ENET Tx and Rx function disable (include MAC and DMA module) */
+void enet_disable(void);
+/* configure MAC address */
+void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]);
+/* get MAC address */   
+void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]);
+
+/* get the ENET MAC/MSC/PTP/DMA status flag */
+FlagStatus enet_flag_get(enet_flag_enum enet_flag);
+/* clear the ENET DMA status flag */
+void enet_flag_clear(enet_flag_clear_enum enet_flag);
+/* enable ENET MAC/MSC/DMA interrupt */
+void enet_interrupt_enable(enet_int_enum enet_int);
+/* disable ENET MAC/MSC/DMA interrupt */
+void enet_interrupt_disable(enet_int_enum enet_int);
+/* get ENET MAC/MSC/DMA interrupt flag */
+FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag);
+/* clear ENET DMA interrupt flag */
+void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear);
+
+/* MAC function */
+/* ENET Tx function enable (include MAC and DMA module) */
+void enet_tx_enable(void);
+/* ENET Tx function disable (include MAC and DMA module) */
+void enet_tx_disable(void);
+/* ENET Rx function enable (include MAC and DMA module) */
+void enet_rx_enable(void);
+/* ENET Rx function disable (include MAC and DMA module) */
+void enet_rx_disable(void);
+/* put registers value into the application buffer */
+void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num);
+/* enable the MAC address filter */
+void enet_address_filter_enable(enet_macaddress_enum mac_addr);
+/* disable the MAC address filter */
+void enet_address_filter_disable(enet_macaddress_enum mac_addr);
+/* configure the MAC address filter */
+void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type);
+/* PHY interface configuration (configure SMI clock and reset PHY chip) */
+ErrStatus enet_phy_config(void);
+/* write to/read from a PHY register */
+ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue);
+/* enable the loopback function of phy chip */
+ErrStatus enet_phyloopback_enable(void);
+/* disable the loopback function of phy chip */
+ErrStatus enet_phyloopback_disable(void);
+/* enable ENET forward feature */
+void enet_forward_feature_enable(uint32_t feature);
+/* disable ENET forward feature */
+void enet_forward_feature_disable(uint32_t feature);
+/* enable ENET filter feature */
+void enet_fliter_feature_enable(uint32_t feature);
+/* disable ENET filter feature */
+void enet_fliter_feature_disable(uint32_t feature);
+
+/* flow control function */
+/* generate the pause frame, ENET will send pause frame after enable transmit flow control */
+ErrStatus enet_pauseframe_generate(void);
+/* configure the pause frame detect type */
+void enet_pauseframe_detect_config(uint32_t detect);
+/* configure the pause frame parameters */
+void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold);
+/* configure the threshold of the flow control(deactive and active threshold) */
+void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active);
+/* enable ENET flow control feature */
+void enet_flowcontrol_feature_enable(uint32_t feature);
+/* disable ENET flow control feature */
+void enet_flowcontrol_feature_disable(uint32_t feature);
+
+/* DMA function */
+/* get the dma transmit/receive process state */
+uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); 
+/* poll the dma transmission/reception enable */
+void enet_dmaprocess_resume(enet_dmadirection_enum direction);
+/* check and recover the Rx process */
+void enet_rxprocess_check_recovery(void);
+/* flush the ENET transmit fifo, and wait until the flush operation completes */
+ErrStatus enet_txfifo_flush(void);
+/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */
+uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get);
+/* get the Tx or Rx descriptor information */
+uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get);
+/* get the number of missed frames during receiving */
+void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop);
+
+/* descriptor function */
+/* get the bit flag of ENET dma descriptor */
+FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag);
+/* set the bit flag of ENET dma tx descriptor */
+void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag);
+/* clear the bit flag of ENET dma tx descriptor */
+void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); 
+/* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */
+void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc);
+/* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */
+void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc);
+/* drop current receive frame */
+void enet_rxframe_drop(void);
+/* enable DMA feature */
+void enet_dma_feature_enable(uint32_t feature);
+/* disable DMA feature */
+void enet_dma_feature_disable(uint32_t feature);
+
+/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */
+void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab);
+/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */
+void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab);
+/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */
+ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]);
+/* handle current received frame but without data copy to application buffer in PTP normal mode */
+#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr)             enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr))
+/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */
+ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]);
+/* handle current transmit frame but without data copy from application buffer in PTP normal mode */
+#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr)       enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr))
+
+/* WUM function */
+/* wakeup frame filter register pointer reset */
+void enet_wum_filter_register_pointer_reset(void);
+/* set the remote wakeup frame registers */
+void enet_wum_filter_config(uint32_t pdata[]);
+/* enable wakeup management features */
+void enet_wum_feature_enable(uint32_t feature);
+/* disable wakeup management features */
+void enet_wum_feature_disable(uint32_t feature);
+
+/* MSC function */
+/* reset the MAC statistics counters */
+void enet_msc_counters_reset(void);
+/* enable the MAC statistics counter features */ 
+void enet_msc_feature_enable(uint32_t feature);
+/* disable the MAC statistics counter features */ 
+void enet_msc_feature_disable(uint32_t feature);
+/* get MAC statistics counter */                   
+uint32_t enet_msc_counters_get(enet_msc_counter_enum counter);
+
+/* PTP function */
+/* change subsecond to nanosecond */
+uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond);
+/* change nanosecond to subsecond */
+uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond);
+/* enable the PTP features */
+void enet_ptp_feature_enable(uint32_t feature);
+/* disable the PTP features */
+void enet_ptp_feature_disable(uint32_t feature);
+/* configure the PTP timestamp function */
+ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func);
+/* configure the PTP system time subsecond increment value */
+void enet_ptp_subsecond_increment_config(uint32_t subsecond);
+/* adjusting the PTP clock frequency only in fine update mode */
+void enet_ptp_timestamp_addend_config(uint32_t add);
+/* initializing or adding/subtracting to second of the PTP system time */
+void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond);
+/* configure the PTP expected target time */
+void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond);
+/* get the PTP current system time */
+void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct);
+/* configure and start PTP timestamp counter */
+void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg);
+/* adjust frequency in fine method by configure addend register */
+void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg);
+/* update system time in coarse method */
+void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct);
+/* set system time in fine method */
+void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct);
+/* get the ptp flag status */
+FlagStatus enet_ptp_flag_get(uint32_t flag);
+
+/* internal function */
+/* reset the ENET initpara struct, call it before using enet_initpara_config() */
+void enet_initpara_reset(void);
+/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */
+static void enet_default_init(void);
+#ifdef USE_DELAY
+/* user can provide more timing precise _ENET_DELAY_ function */
+#define _ENET_DELAY_                              delay_ms 
+#else
+/* insert a delay time */
+static void enet_delay(uint32_t ncount);
+/* default _ENET_DELAY_ function with less precise timing */
+#define _ENET_DELAY_                              enet_delay
+#endif
+
+#endif /* GD32F10X_ENET_H */

+ 431 - 0
Library/Include/gd32f10x_exmc.h

@@ -0,0 +1,431 @@
+/*!
+    \file  gd32f10x_exmc.h
+    \brief definitions for the EXMC
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_EXMC_H
+#define GD32F10X_EXMC_H
+
+#include "gd32f10x.h"
+
+/* EXMC definitions */
+#define EXMC                              (EXMC_BASE)                   /*!< EXMC register base address */
+
+/* registers definitions */
+/* NOR/PSRAM */
+#define EXMC_SNCTL0                       REG32(EXMC + 0x00U)           /*!< EXMC SRAM/NOR flash control register 0 */
+#define EXMC_SNTCFG0                      REG32(EXMC + 0x04U)           /*!< EXMC SRAM/NOR flash timing configuration register 0 */
+#define EXMC_SNWTCFG0                     REG32(EXMC + 0x104U)          /*!< EXMC SRAM/NOR flash write timing configuration register 0 */
+
+#define EXMC_SNCTL1                       REG32(EXMC + 0x08U)           /*!< EXMC SRAM/NOR flash control register 1 */
+#define EXMC_SNTCFG1                      REG32(EXMC + 0x0CU)           /*!< EXMC SRAM/NOR flash timing configuration register 1 */
+#define EXMC_SNWTCFG1                     REG32(EXMC + 0x10CU)          /*!< EXMC SRAM/NOR flash write timing configuration register 1 */
+
+#define EXMC_SNCTL2                       REG32(EXMC + 0x10U)           /*!< EXMC SRAM/NOR flash control register 2 */
+#define EXMC_SNTCFG2                      REG32(EXMC + 0x14U)           /*!< EXMC SRAM/NOR flash timing configuration register 2 */
+#define EXMC_SNWTCFG2                     REG32(EXMC + 0x114U)          /*!< EXMC SRAM/NOR flash write timing configuration register 2 */
+
+#define EXMC_SNCTL3                       REG32(EXMC + 0x18U)           /*!< EXMC SRAM/NOR flash control register 3 */
+#define EXMC_SNTCFG3                      REG32(EXMC + 0x1CU)           /*!< EXMC SRAM/NOR flash timing configuration register 3 */
+#define EXMC_SNWTCFG3                     REG32(EXMC + 0x11CU)          /*!< EXMC SRAM/NOR flash write timing configuration register 3 */
+
+/* NAND/PC card */
+#define EXMC_NPCTL1                       REG32(EXMC + 0x60U)           /*!< EXMC NAND/PC card control register 1 */
+#define EXMC_NPINTEN1                     REG32(EXMC + 0x64U)           /*!< EXMC NAND/PC card interrupt enable register 1 */
+#define EXMC_NPCTCFG1                     REG32(EXMC + 0x68U)           /*!< EXMC NAND/PC card common space timing configuration register 1 */
+#define EXMC_NPATCFG1                     REG32(EXMC + 0x6CU)           /*!< EXMC NAND/PC card attribute space timing configuration register 1 */
+#define EXMC_NECC1                        REG32(EXMC + 0x74U)           /*!< EXMC NAND ECC register 1 */
+
+#define EXMC_NPCTL2                       REG32(EXMC + 0x80U)           /*!< EXMC NAND/PC card control register 2 */
+#define EXMC_NPINTEN2                     REG32(EXMC + 0x84U)           /*!< EXMC NAND/PC card interrupt enable register 2 */
+#define EXMC_NPCTCFG2                     REG32(EXMC + 0x88U)           /*!< EXMC NAND/PC card common space timing configuration register 2 */
+#define EXMC_NPATCFG2                     REG32(EXMC + 0x8CU)           /*!< EXMC NAND/PC card attribute space timing configuration register 2 */
+#define EXMC_NECC2                        REG32(EXMC + 0x94U)           /*!< EXMC NAND ECC register 2 */
+
+#define EXMC_NPCTL3                       REG32(EXMC + 0xA0U)           /*!< EXMC NAND/PC card control register 3 */
+#define EXMC_NPINTEN3                     REG32(EXMC + 0xA4U)           /*!< EXMC NAND/PC card interrupt enable register 3 */
+#define EXMC_NPCTCFG3                     REG32(EXMC + 0xA8U)           /*!< EXMC NAND/PC card common space timing configuration register 3 */
+#define EXMC_NPATCFG3                     REG32(EXMC + 0xACU)           /*!< EXMC NAND/PC card attribute space timing configuration register 3 */
+#define EXMC_PIOTCFG3                     REG32(EXMC + 0xB0U)           /*!< EXMC PC card I/O space timing configuration register */
+
+/* bits definitions */
+/* NOR/PSRAM */
+/* EXMC_SNCTLx,x=0..3 */
+#define EXMC_SNCTL_NRBKEN                 BIT(0)                        /*!< NOR bank enable */
+#define EXMC_SNCTL_NRMUX                  BIT(1)                        /*!< NOR bank memory address/data multiplexing */
+#define EXMC_SNCTL_NRTP                   BITS(2,3)                     /*!< NOR bank memory type */
+#define EXMC_SNCTL_NRW                    BITS(4,5)                     /*!< NOR bank memory data bus width */
+#define EXMC_SNCTL_NREN                   BIT(6)                        /*!< NOR flash access enable */
+#define EXMC_SNCTL_SBRSTEN                BIT(8)                        /*!< synchronous burst enable */
+#define EXMC_SNCTL_NRWTPOL                BIT(9)                        /*!< NWAIT signal polarity */
+#define EXMC_SNCTL_WRAPEN                 BIT(10)                       /*!< wrapped burst mode enable */
+#define EXMC_SNCTL_NRWTCFG                BIT(11)                       /*!< NWAIT signal configuration, only work in synchronous mode  */
+#define EXMC_SNCTL_WREN                   BIT(12)                       /*!< write enable */
+#define EXMC_SNCTL_NRWTEN                 BIT(13)                       /*!< NWAIT signal enable */
+#define EXMC_SNCTL_EXMODEN                BIT(14)                       /*!< extended mode enable */
+#define EXMC_SNCTL_ASYNCWAIT              BIT(15)                       /*!< asynchronous wait */
+#define EXMC_SNCTL_SYNCWR                 BIT(19)                       /*!< synchronous write */
+
+/* EXMC_SNTCFGx,x=0..3 */
+#define EXMC_SNTCFG_ASET                  BITS(0,3)                     /*!< address setup time */
+#define EXMC_SNTCFG_AHLD                  BITS(4,7)                     /*!< address hold time */
+#define EXMC_SNTCFG_DSET                  BITS(8,15)                    /*!< data setup time */
+#define EXMC_SNTCFG_BUSLAT                BITS(16,19)                   /*!< bus latency */
+#define EXMC_SNTCFG_CKDIV                 BITS(20,23)                   /*!< synchronous clock divide ratio */
+#define EXMC_SNTCFG_DLAT                  BITS(24,27)                   /*!< data latency for NOR flash */
+#define EXMC_SNTCFG_ASYNCMOD              BITS(28,29)                   /*!< asynchronous access mode */
+
+/* EXMC_SNWTCFGx,x=0..3 */
+#define EXMC_SNWTCFG_WASET                BITS(0,3)                     /*!< address setup time */
+#define EXMC_SNWTCFG_WAHLD                BITS(4,7)                     /*!< address hold time */
+#define EXMC_SNWTCFG_WDSET                BITS(8,15)                    /*!< data setup time */
+#define EXMC_SNWTCFG_CKDIV                BITS(20,23)                   /*!< synchronous clock divide ratio */
+#define EXMC_SNWTCFG_DLAT                 BITS(24,27)                   /*!< data latency for NOR flash */
+#define EXMC_SNWTCFG_WASYNCMOD            BITS(28,29)                   /*!< asynchronous access mode */
+
+/* NAND/PC card */
+/* EXMC_NPCTLx,x=1..3 */
+#define EXMC_NPCTL_NDWTEN                 BIT(1)                        /*!< wait feature enable */
+#define EXMC_NPCTL_NDBKEN                 BIT(2)                        /*!< NAND bank enable */
+#define EXMC_NPCTL_NDTP                   BIT(3)                        /*!< NAND bank memory type */
+#define EXMC_NPCTL_NDW                    BITS(4,5)                     /*!< NAND bank memory data bus width */
+#define EXMC_NPCTL_ECCEN                  BIT(6)                        /*!< ECC enable */
+#define EXMC_NPCTL_CTR                    BITS(9,12)                    /*!< CLE to RE delay */
+#define EXMC_NPCTL_ATR                    BITS(13,16)                   /*!< ALE to RE delay */
+#define EXMC_NPCTL_ECCSZ                  BITS(17,19)                   /*!< ECC size */
+
+/* EXMC_NPINTENx,x=1..3 */
+#define EXMC_NPINTEN_INTRS                BIT(0)                        /*!< interrupt rising edge status */
+#define EXMC_NPINTEN_INTHS                BIT(1)                        /*!< interrupt high-level status */
+#define EXMC_NPINTEN_INTFS                BIT(2)                        /*!< interrupt falling edge status */
+#define EXMC_NPINTEN_INTREN               BIT(3)                        /*!< interrupt rising edge detection enable */
+#define EXMC_NPINTEN_INTHEN               BIT(4)                        /*!< interrupt high-level detection enable */
+#define EXMC_NPINTEN_INTFEN               BIT(5)                        /*!< interrupt falling edge detection enable */
+#define EXMC_NPINTEN_FFEPT                BIT(6)                        /*!< FIFO empty flag */
+
+/* EXMC_NPCTCFGx,x=1..3 */
+#define EXMC_NPCTCFG_COMSET               BITS(0,7)                     /*!< common memory setup time */
+#define EXMC_NPCTCFG_COMWAIT              BITS(8,15)                    /*!< common memory wait time */
+#define EXMC_NPCTCFG_COMHLD               BITS(16,23)                   /*!< common memory hold time */
+#define EXMC_NPCTCFG_COMHIZ               BITS(24,31)                   /*!< common memory data bus HiZ time */
+
+/* EXMC_NPATCFGx,x=1..3 */
+#define EXMC_NPATCFG_ATTSET               BITS(0,7)                     /*!< attribute memory setup time */
+#define EXMC_NPATCFG_ATTWAIT              BITS(8,15)                    /*!< attribute memory wait time */
+#define EXMC_NPATCFG_ATTHLD               BITS(16,23)                   /*!< attribute memory hold time */
+#define EXMC_NPATCFG_ATTHIZ               BITS(24,31)                   /*!< attribute memory data bus HiZ time */
+
+/* EXMC_PIOTCFG3 */
+#define EXMC_PIOTCFG3_IOSET               BITS(0,7)                     /*!< IO space setup time */
+#define EXMC_PIOTCFG3_IOWAIT              BITS(8,15)                    /*!< IO space wait time */
+#define EXMC_PIOTCFG3_IOHLD               BITS(16,23)                   /*!< IO space hold time */
+#define EXMC_PIOTCFG3_IOHIZ               BITS(24,31)                   /*!< IO space data bus HiZ time */
+
+/* EXMC_NECCx,x=1,2 */
+#define EXMC_NECC_ECC                     BITS(0,31)                    /*!< ECC result */
+
+/* constants definitions */
+/* EXMC NOR/SRAM timing initialize struct */
+typedef struct
+{
+    uint32_t asyn_access_mode;                                          /*!< asynchronous access mode */
+    uint32_t syn_data_latency;                                          /*!< configure the data latency */
+    uint32_t syn_clk_division;                                          /*!< configure the clock divide ratio */
+    uint32_t bus_latency;                                               /*!< configure the bus latency */
+    uint32_t asyn_data_setuptime;                                       /*!< configure the data setup time,asynchronous access mode valid */
+    uint32_t asyn_address_holdtime;                                     /*!< configure the address hold time,asynchronous access mode valid */
+    uint32_t asyn_address_setuptime;                                    /*!< configure the data setup time,asynchronous access mode valid */
+}exmc_norsram_timing_parameter_struct;
+
+/* EXMC NOR/SRAM initialize struct */
+typedef struct
+{
+    uint32_t norsram_region;                                            /*!< select the region of EXMC NOR/SRAM bank */
+    uint32_t write_mode;                                                /*!< the write mode, synchronous mode or asynchronous mode */
+    uint32_t extended_mode;                                             /*!< enable or disable the extended mode */
+    uint32_t asyn_wait;                                                 /*!< enable or disable the asynchronous wait function */
+    uint32_t nwait_signal;                                              /*!< enable or disable the NWAIT signal while in synchronous bust mode */
+    uint32_t memory_write;                                              /*!< enable or disable the write operation */
+    uint32_t nwait_config;                                              /*!< NWAIT signal configuration */
+    uint32_t wrap_burst_mode;                                           /*!< enable or disable the wrap burst mode */
+    uint32_t nwait_polarity;                                            /*!< specifies the polarity of NWAIT signal from memory */
+    uint32_t burst_mode;                                                /*!< enable or disable the burst mode */
+    uint32_t databus_width;                                             /*!< specifies the databus width of external memory */
+    uint32_t memory_type;                                               /*!< specifies the type of external memory */
+    uint32_t address_data_mux;                                          /*!< specifies whether the data bus and address bus are multiplexed */
+    exmc_norsram_timing_parameter_struct* read_write_timing;            /*!< timing parameters for read and write if the extended mode is not used or the timing 
+                                                                             parameters for read if the extended mode is used */
+    exmc_norsram_timing_parameter_struct* write_timing;                 /*!< timing parameters for write when the extended mode is used */
+}exmc_norsram_parameter_struct;
+
+/* EXMC NAND/PC card timing initialize struct */
+typedef struct
+{
+    uint32_t databus_hiztime;                                           /*!< configure the dadtabus HiZ time for write operation */
+    uint32_t holdtime;                                                  /*!< configure the address hold time(or the data hold time for write operation) */
+    uint32_t waittime;                                                  /*!< configure the minimum wait time */
+    uint32_t setuptime;                                                 /*!< configure the address setup time */
+}exmc_nand_pccard_timing_parameter_struct;
+
+/* EXMC NAND initialize struct */
+typedef struct
+{
+    uint32_t nand_bank;                                                 /*!< select the bank of NAND */ 
+    uint32_t ecc_size;                                                  /*!< the page size for the ECC calculation */
+    uint32_t atr_latency;                                               /*!< configure the latency of ALE low to RB low */
+    uint32_t ctr_latency;                                               /*!< configure the latency of CLE low to RB low */
+    uint32_t ecc_logic;                                                 /*!< enable or disable the ECC calculation logic */
+    uint32_t databus_width;                                             /*!< the NAND flash databus width */
+    uint32_t wait_feature;                                              /*!< enables or disables the wait feature */
+    exmc_nand_pccard_timing_parameter_struct* common_space_timing;      /*!< the timing parameters for NAND flash common space */
+    exmc_nand_pccard_timing_parameter_struct* attribute_space_timing;   /*!< the timing parameters for NAND flash attribute space */
+}exmc_nand_parameter_struct;
+
+/* EXMC PC card initialize struct */
+typedef struct
+{
+    uint32_t atr_latency;                                               /*!< configure the latency of ALE low to RB low */
+    uint32_t ctr_latency;                                               /*!< configure the latency of CLE low to RB low */
+    uint32_t wait_feature;                                              /*!< enables or disables the Wait feature */
+    exmc_nand_pccard_timing_parameter_struct*  common_space_timing;     /*!< the timing parameters for NAND flash common space */
+    exmc_nand_pccard_timing_parameter_struct*  attribute_space_timing;  /*!< the timing parameters for NAND flash attribute space */  
+    exmc_nand_pccard_timing_parameter_struct*  io_space_timing;         /*!< the timing parameters for NAND flash IO space */
+}exmc_pccard_parameter_struct;;
+
+/* EXMC register address */
+#define EXMC_SNCTL(region)                REG32(EXMC + 0x08U * (region))                  /*!< EXMC SRAM/NOR flash control register */
+#define EXMC_SNTCFG(region)               REG32(EXMC + 0x04U + 0x08U * (region))          /*!< EXMC SRAM/NOR flash timing configuration register */
+#define EXMC_SNWTCFG(region)              REG32(EXMC + 0x104U + 0x08U * (region))         /*!< EXMC SRAM/NOR flash write timing configuration register */
+
+#define EXMC_NPCTL(bank)                  REG32(EXMC + 0x40U + 0x20U * (bank))            /*!< EXMC NAND/PC card control register */
+#define EXMC_NPINTEN(bank)                REG32(EXMC + 0x44U + 0x20U * (bank))            /*!< EXMC NAND/PC card interrupt enable register */
+#define EXMC_NPCTCFG(bank)                REG32(EXMC + 0x48U + 0x20U * (bank))            /*!< EXMC NAND/PC card common space timing configuration register */
+#define EXMC_NPATCFG(bank)                REG32(EXMC + 0x4CU + 0x20U * (bank))            /*!< EXMC NAND/PC card attribute space timing configuration register */
+#define EXMC_NECC(bank)                   REG32(EXMC + 0x54U + 0x20U * (bank))            /*!< EXMC NAND ECC register */
+
+/* NOR bank memory data bus width */
+#define SNCTL_NRW(regval)                 (BITS(4,5) & ((uint32_t)(regval) << 4))
+#define EXMC_NOR_DATABUS_WIDTH_8B         SNCTL_NRW(0)                  /*!< NOR data width 8 bits */
+#define EXMC_NOR_DATABUS_WIDTH_16B        SNCTL_NRW(1)                  /*!< NOR data width 16 bits */
+
+/* NOR bank memory type */
+#define SNCTL_NRTP(regval)                (BITS(2,3) & ((uint32_t)(regval) << 2))
+#define EXMC_MEMORY_TYPE_SRAM             SNCTL_NRTP(0)                 /*!< SRAM,ROM */
+#define EXMC_MEMORY_TYPE_PSRAM            SNCTL_NRTP(1)                 /*!< PSRAM,CRAM */
+#define EXMC_MEMORY_TYPE_NOR              SNCTL_NRTP(2)                 /*!< NOR flash */
+
+/* asynchronous access mode */
+#define SNTCFG_ASYNCMOD(regval)           (BITS(28,29) & ((uint32_t)(regval) << 28))
+#define EXMC_ACCESS_MODE_A                SNTCFG_ASYNCMOD(0)            /*!< mode A access */
+#define EXMC_ACCESS_MODE_B                SNTCFG_ASYNCMOD(1)            /*!< mode B access */
+#define EXMC_ACCESS_MODE_C                SNTCFG_ASYNCMOD(2)            /*!< mode C access */
+#define EXMC_ACCESS_MODE_D                SNTCFG_ASYNCMOD(3)            /*!< mode D access */
+
+/* data latency for NOR flash */
+#define SNTCFG_DLAT(regval)               (BITS(24,27) & ((uint32_t)(regval) << 24))
+#define EXMC_DATALAT_2_CLK                SNTCFG_DLAT(0)                /*!< data latency 2 EXMC_CLK */
+#define EXMC_DATALAT_3_CLK                SNTCFG_DLAT(1)                /*!< data latency 3 EXMC_CLK */
+#define EXMC_DATALAT_4_CLK                SNTCFG_DLAT(2)                /*!< data latency 4 EXMC_CLK */
+#define EXMC_DATALAT_5_CLK                SNTCFG_DLAT(3)                /*!< data latency 5 EXMC_CLK */
+#define EXMC_DATALAT_6_CLK                SNTCFG_DLAT(4)                /*!< data latency 6 EXMC_CLK */
+#define EXMC_DATALAT_7_CLK                SNTCFG_DLAT(5)                /*!< data latency 7 EXMC_CLK */
+#define EXMC_DATALAT_8_CLK                SNTCFG_DLAT(6)                /*!< data latency 8 EXMC_CLK */
+#define EXMC_DATALAT_9_CLK                SNTCFG_DLAT(7)                /*!< data latency 9 EXMC_CLK */
+#define EXMC_DATALAT_10_CLK               SNTCFG_DLAT(8)                /*!< data latency 10 EXMC_CLK */
+#define EXMC_DATALAT_11_CLK               SNTCFG_DLAT(9)                /*!< data latency 11 EXMC_CLK */
+#define EXMC_DATALAT_12_CLK               SNTCFG_DLAT(10)               /*!< data latency 12 EXMC_CLK */
+#define EXMC_DATALAT_13_CLK               SNTCFG_DLAT(11)               /*!< data latency 13 EXMC_CLK */
+#define EXMC_DATALAT_14_CLK               SNTCFG_DLAT(12)               /*!< data latency 14 EXMC_CLK */
+#define EXMC_DATALAT_15_CLK               SNTCFG_DLAT(13)               /*!< data latency 15 EXMC_CLK */
+#define EXMC_DATALAT_16_CLK               SNTCFG_DLAT(14)               /*!< data latency 16 EXMC_CLK */
+#define EXMC_DATALAT_17_CLK               SNTCFG_DLAT(15)               /*!< data latency 17 EXMC_CLK */
+
+/* synchronous clock divide ratio */
+#define SNTCFG_CKDIV(regval)              (BITS(20,23) & ((uint32_t)(regval) << 20))
+#define EXMC_SYN_CLOCK_RATIO_DISABLE      SNTCFG_CKDIV(0)               /*!< EXMC_CLK disable */
+#define EXMC_SYN_CLOCK_RATIO_2_CLK        SNTCFG_CKDIV(1)               /*!< frequency EXMC_CLK = HCLK/2 */
+#define EXMC_SYN_CLOCK_RATIO_3_CLK        SNTCFG_CKDIV(2)               /*!< frequency EXMC_CLK = HCLK/3 */
+#define EXMC_SYN_CLOCK_RATIO_4_CLK        SNTCFG_CKDIV(3)               /*!< frequency EXMC_CLK = HCLK/4 */
+#define EXMC_SYN_CLOCK_RATIO_5_CLK        SNTCFG_CKDIV(4)               /*!< frequency EXMC_CLK = HCLK/5 */
+#define EXMC_SYN_CLOCK_RATIO_6_CLK        SNTCFG_CKDIV(5)               /*!< frequency EXMC_CLK = HCLK/6 */
+#define EXMC_SYN_CLOCK_RATIO_7_CLK        SNTCFG_CKDIV(6)               /*!< frequency EXMC_CLK = HCLK/7 */
+#define EXMC_SYN_CLOCK_RATIO_8_CLK        SNTCFG_CKDIV(7)               /*!< frequency EXMC_CLK = HCLK/8 */
+#define EXMC_SYN_CLOCK_RATIO_9_CLK        SNTCFG_CKDIV(8)               /*!< frequency EXMC_CLK = HCLK/9 */
+#define EXMC_SYN_CLOCK_RATIO_10_CLK       SNTCFG_CKDIV(9)               /*!< frequency EXMC_CLK = HCLK/10 */
+#define EXMC_SYN_CLOCK_RATIO_11_CLK       SNTCFG_CKDIV(10)              /*!< frequency EXMC_CLK = HCLK/11 */
+#define EXMC_SYN_CLOCK_RATIO_12_CLK       SNTCFG_CKDIV(11)              /*!< frequency EXMC_CLK = HCLK/12 */
+#define EXMC_SYN_CLOCK_RATIO_13_CLK       SNTCFG_CKDIV(12)              /*!< frequency EXMC_CLK = HCLK/13 */
+#define EXMC_SYN_CLOCK_RATIO_14_CLK       SNTCFG_CKDIV(13)              /*!< frequency EXMC_CLK = HCLK/14 */
+#define EXMC_SYN_CLOCK_RATIO_15_CLK       SNTCFG_CKDIV(14)              /*!< frequency EXMC_CLK = HCLK/15 */
+#define EXMC_SYN_CLOCK_RATIO_16_CLK       SNTCFG_CKDIV(15)              /*!< frequency EXMC_CLK = HCLK/16 */
+
+/* ECC size */
+#define NPCTL_ECCSZ(regval)               (BITS(17,19) & ((uint32_t)(regval) << 17))
+#define EXMC_ECC_SIZE_256BYTES            NPCTL_ECCSZ(0)                /* 256 bytes */
+#define EXMC_ECC_SIZE_512BYTES            NPCTL_ECCSZ(1)                /* 512 bytes */
+#define EXMC_ECC_SIZE_1024BYTES           NPCTL_ECCSZ(2)                /* 1024 bytes */
+#define EXMC_ECC_SIZE_2048BYTES           NPCTL_ECCSZ(3)                /* 2048 bytes */
+#define EXMC_ECC_SIZE_4096BYTES           NPCTL_ECCSZ(4)                /* 4096 bytes */
+#define EXMC_ECC_SIZE_8192BYTES           NPCTL_ECCSZ(5)                /* 8192 bytes */
+
+/* ALE to RE delay */
+#define NPCTL_ATR(regval)                 (BITS(13,16) & ((uint32_t)(regval) << 13))
+#define EXMC_ALE_RE_DELAY_1_HCLK          NPCTL_ATR(0)                  /* ALE to RE delay = 1*HCLK */
+#define EXMC_ALE_RE_DELAY_2_HCLK          NPCTL_ATR(1)                  /* ALE to RE delay = 2*HCLK */
+#define EXMC_ALE_RE_DELAY_3_HCLK          NPCTL_ATR(2)                  /* ALE to RE delay = 3*HCLK */
+#define EXMC_ALE_RE_DELAY_4_HCLK          NPCTL_ATR(3)                  /* ALE to RE delay = 4*HCLK */
+#define EXMC_ALE_RE_DELAY_5_HCLK          NPCTL_ATR(4)                  /* ALE to RE delay = 5*HCLK */
+#define EXMC_ALE_RE_DELAY_6_HCLK          NPCTL_ATR(5)                  /* ALE to RE delay = 6*HCLK */
+#define EXMC_ALE_RE_DELAY_7_HCLK          NPCTL_ATR(6)                  /* ALE to RE delay = 7*HCLK */
+#define EXMC_ALE_RE_DELAY_8_HCLK          NPCTL_ATR(7)                  /* ALE to RE delay = 8*HCLK */
+#define EXMC_ALE_RE_DELAY_9_HCLK          NPCTL_ATR(8)                  /* ALE to RE delay = 9*HCLK */
+#define EXMC_ALE_RE_DELAY_10_HCLK         NPCTL_ATR(9)                  /* ALE to RE delay = 10*HCLK */
+#define EXMC_ALE_RE_DELAY_11_HCLK         NPCTL_ATR(10)                 /* ALE to RE delay = 11*HCLK */
+#define EXMC_ALE_RE_DELAY_12_HCLK         NPCTL_ATR(11)                 /* ALE to RE delay = 12*HCLK */
+#define EXMC_ALE_RE_DELAY_13_HCLK         NPCTL_ATR(12)                 /* ALE to RE delay = 13*HCLK */
+#define EXMC_ALE_RE_DELAY_14_HCLK         NPCTL_ATR(13)                 /* ALE to RE delay = 14*HCLK */
+#define EXMC_ALE_RE_DELAY_15_HCLK         NPCTL_ATR(14)                 /* ALE to RE delay = 15*HCLK */
+#define EXMC_ALE_RE_DELAY_16_HCLK         NPCTL_ATR(15)                 /* ALE to RE delay = 16*HCLK */
+
+/* CLE to RE delay */
+#define NPCTL_CTR(regval)                 (BITS(9,12) & ((uint32_t)(regval) << 9))
+#define EXMC_CLE_RE_DELAY_1_HCLK          NPCTL_CTR(0)                  /* CLE to RE delay = 1*HCLK */
+#define EXMC_CLE_RE_DELAY_2_HCLK          NPCTL_CTR(1)                  /* CLE to RE delay = 2*HCLK */
+#define EXMC_CLE_RE_DELAY_3_HCLK          NPCTL_CTR(2)                  /* CLE to RE delay = 3*HCLK */
+#define EXMC_CLE_RE_DELAY_4_HCLK          NPCTL_CTR(3)                  /* CLE to RE delay = 4*HCLK */
+#define EXMC_CLE_RE_DELAY_5_HCLK          NPCTL_CTR(4)                  /* CLE to RE delay = 5*HCLK */
+#define EXMC_CLE_RE_DELAY_6_HCLK          NPCTL_CTR(5)                  /* CLE to RE delay = 6*HCLK */
+#define EXMC_CLE_RE_DELAY_7_HCLK          NPCTL_CTR(6)                  /* CLE to RE delay = 7*HCLK */
+#define EXMC_CLE_RE_DELAY_8_HCLK          NPCTL_CTR(7)                  /* CLE to RE delay = 8*HCLK */
+#define EXMC_CLE_RE_DELAY_9_HCLK          NPCTL_CTR(8)                  /* CLE to RE delay = 9*HCLK */
+#define EXMC_CLE_RE_DELAY_10_HCLK         NPCTL_CTR(9)                  /* CLE to RE delay = 10*HCLK */
+#define EXMC_CLE_RE_DELAY_11_HCLK         NPCTL_CTR(10)                 /* CLE to RE delay = 11*HCLK */
+#define EXMC_CLE_RE_DELAY_12_HCLK         NPCTL_CTR(11)                 /* CLE to RE delay = 12*HCLK */
+#define EXMC_CLE_RE_DELAY_13_HCLK         NPCTL_CTR(12)                 /* CLE to RE delay = 13*HCLK */
+#define EXMC_CLE_RE_DELAY_14_HCLK         NPCTL_CTR(13)                 /* CLE to RE delay = 14*HCLK */
+#define EXMC_CLE_RE_DELAY_15_HCLK         NPCTL_CTR(14)                 /* CLE to RE delay = 15*HCLK */
+#define EXMC_CLE_RE_DELAY_16_HCLK         NPCTL_CTR(15)                 /* CLE to RE delay = 16*HCLK */
+
+/* NAND bank memory data bus width */
+#define NPCTL_NDW(regval)                 (BITS(4,5) & ((uint32_t)(regval) << 4))
+#define EXMC_NAND_DATABUS_WIDTH_8B        NPCTL_NDW(0)                  /*!< NAND data width 8 bits */
+#define EXMC_NAND_DATABUS_WIDTH_16B       NPCTL_NDW(1)                  /*!< NAND data width 16 bits */
+
+/* EXMC NOR/SRAM bank region definition */
+#define EXMC_BANK0_NORSRAM_REGION0        ((uint32_t)0x00000000U)       /*!< bank0 NOR/SRAM region0 */
+#define EXMC_BANK0_NORSRAM_REGION1        ((uint32_t)0x00000001U)       /*!< bank0 NOR/SRAM region1 */
+#define EXMC_BANK0_NORSRAM_REGION2        ((uint32_t)0x00000002U)       /*!< bank0 NOR/SRAM region2 */
+#define EXMC_BANK0_NORSRAM_REGION3        ((uint32_t)0x00000003U)       /*!< bank0 NOR/SRAM region3 */
+
+/* EXMC NOR/SRAM write mode */
+#define EXMC_ASYN_WRITE                   ((uint32_t)0x00000000U)       /*!< asynchronous write mode */
+#define EXMC_SYN_WRITE                    ((uint32_t)0x00080000U)       /*!< synchronous write mode */
+
+/* EXMC NWAIT signal configuration */
+#define EXMC_NWAIT_CONFIG_BEFORE          ((uint32_t)0x00000000U)       /*!< NWAIT signal is active one data cycle before wait state */
+#define EXMC_NWAIT_CONFIG_DURING          ((uint32_t)0x00000800U)       /*!< NWAIT signal is active during wait state */
+
+/* EXMC NWAIT signal polarity configuration */
+#define EXMC_NWAIT_POLARITY_LOW           ((uint32_t)0x00000000U)       /*!< low level is active of NWAIT */
+#define EXMC_NWAIT_POLARITY_HIGH          ((uint32_t)0x00000200U)       /*!< high level is active of NWAIT */
+
+/* EXMC NAND/PC card bank definition */
+#define EXMC_BANK1_NAND                   ((uint32_t)0x00000001U)       /*!< bank1 NAND flash */
+#define EXMC_BANK2_NAND                   ((uint32_t)0x00000002U)       /*!< bank2 NAND flash */
+#define EXMC_BANK3_PCCARD                 ((uint32_t)0x00000003U)       /*!< bank3 PC card */
+
+/* EXMC flag bits */
+#define EXMC_NAND_PCCARD_FLAG_RISE        EXMC_NPINTEN_INTRS            /*!< interrupt rising edge status */
+#define EXMC_NAND_PCCARD_FLAG_LEVEL       EXMC_NPINTEN_INTHS            /*!< interrupt high-level status */
+#define EXMC_NAND_PCCARD_FLAG_FALL        EXMC_NPINTEN_INTFS            /*!< interrupt falling edge status */
+#define EXMC_NAND_PCCARD_FLAG_FIFOE       EXMC_NPINTEN_FFEPT            /*!< FIFO empty flag */
+
+/* EXMC interrupt flag bits */
+#define EXMC_NAND_PCCARD_INT_RISE         EXMC_NPINTEN_INTREN           /*!< interrupt rising edge detection enable */
+#define EXMC_NAND_PCCARD_INT_LEVEL        EXMC_NPINTEN_INTHEN           /*!< interrupt high-level detection enable */
+#define EXMC_NAND_PCCARD_INT_FALL         EXMC_NPINTEN_INTFEN           /*!< interrupt falling edge detection enable */
+
+/* function declarations */
+/* deinitialize EXMC NOR/SRAM region */
+void exmc_norsram_deinit(uint32_t norsram_region);
+/* exmc_norsram_parameter_struct parameter initialize */
+void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct);
+/* initialize EXMC NOR/SRAM region */
+void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct);
+/* EXMC NOR/SRAM bank enable */
+void exmc_norsram_enable(uint32_t norsram_region);
+/* EXMC NOR/SRAM bank disable */
+void exmc_norsram_disable(uint32_t norsram_region);
+
+/* deinitialize EXMC NAND bank */
+void exmc_nand_deinit(uint32_t nand_bank);
+/* initialize EXMC NAND bank */
+void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct);
+/* exmc_nand_init_struct parameter initialize */
+void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct);
+/* EXMC NAND bank enable */
+void exmc_nand_enable(uint32_t nand_bank);
+/* EXMC NAND bank disable */
+void exmc_nand_disable(uint32_t nand_bank);
+/* enable or disable the EXMC NAND ECC function */
+void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue);
+/* get the EXMC ECC value */
+uint32_t exmc_ecc_get(uint32_t nand_bank);
+
+/* deinitialize EXMC PC card bank */
+void exmc_pccard_deinit(void);
+/* initialize EXMC PC card bank */
+void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct);
+/* exmc_pccard_parameter_struct parameter initialize */
+void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct);
+/* EXMC PC card bank enable */
+void exmc_pccard_enable(void);
+/* EXMC PC card bank disable */
+void exmc_pccard_disable(void);
+
+/* enable EXMC interrupt */
+void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source);
+/* disable EXMC interrupt */
+void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source);
+/* check EXMC flag is set or not */
+FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag);
+/* clear EXMC flag */
+void exmc_flag_clear(uint32_t bank, uint32_t flag);
+/* check EXMC flag is set or not */
+FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source);
+/* clear EXMC flag */
+void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source);
+
+#endif /* GD32F10X_EXMC_H */

+ 258 - 0
Library/Include/gd32f10x_exti.h

@@ -0,0 +1,258 @@
+/*!
+    \file    gd32f10x_exti.h
+    \brief   definitions for the EXTI
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_EXTI_H
+#define GD32F10X_EXTI_H
+
+#include "gd32f10x.h"
+
+/* EXTI definitions */
+#define EXTI                         EXTI_BASE
+
+/* registers definitions */
+#define EXTI_INTEN                   REG32(EXTI + 0x00U)      /*!< interrupt enable register */
+#define EXTI_EVEN                    REG32(EXTI + 0x04U)      /*!< event enable register */
+#define EXTI_RTEN                    REG32(EXTI + 0x08U)      /*!< rising edge trigger enable register */
+#define EXTI_FTEN                    REG32(EXTI + 0x0CU)      /*!< falling trigger enable register */
+#define EXTI_SWIEV                   REG32(EXTI + 0x10U)      /*!< software interrupt event register */
+#define EXTI_PD                      REG32(EXTI + 0x14U)      /*!< pending register */
+
+/* bits definitions */
+/* EXTI_INTEN */
+#define EXTI_INTEN_INTEN0            BIT(0)                   /*!< interrupt from line 0 */
+#define EXTI_INTEN_INTEN1            BIT(1)                   /*!< interrupt from line 1 */
+#define EXTI_INTEN_INTEN2            BIT(2)                   /*!< interrupt from line 2 */
+#define EXTI_INTEN_INTEN3            BIT(3)                   /*!< interrupt from line 3 */
+#define EXTI_INTEN_INTEN4            BIT(4)                   /*!< interrupt from line 4 */
+#define EXTI_INTEN_INTEN5            BIT(5)                   /*!< interrupt from line 5 */
+#define EXTI_INTEN_INTEN6            BIT(6)                   /*!< interrupt from line 6 */
+#define EXTI_INTEN_INTEN7            BIT(7)                   /*!< interrupt from line 7 */
+#define EXTI_INTEN_INTEN8            BIT(8)                   /*!< interrupt from line 8 */
+#define EXTI_INTEN_INTEN9            BIT(9)                   /*!< interrupt from line 9 */
+#define EXTI_INTEN_INTEN10           BIT(10)                  /*!< interrupt from line 10 */
+#define EXTI_INTEN_INTEN11           BIT(11)                  /*!< interrupt from line 11 */
+#define EXTI_INTEN_INTEN12           BIT(12)                  /*!< interrupt from line 12 */
+#define EXTI_INTEN_INTEN13           BIT(13)                  /*!< interrupt from line 13 */
+#define EXTI_INTEN_INTEN14           BIT(14)                  /*!< interrupt from line 14 */
+#define EXTI_INTEN_INTEN15           BIT(15)                  /*!< interrupt from line 15 */
+#define EXTI_INTEN_INTEN16           BIT(16)                  /*!< interrupt from line 16 */
+#define EXTI_INTEN_INTEN17           BIT(17)                  /*!< interrupt from line 17 */
+#define EXTI_INTEN_INTEN18           BIT(18)                  /*!< interrupt from line 18 */
+#define EXTI_INTEN_INTEN19           BIT(19)                  /*!< interrupt from line 19 */
+
+/* EXTI_EVEN */
+#define EXTI_EVEN_EVEN0              BIT(0)                   /*!< event from line 0 */
+#define EXTI_EVEN_EVEN1              BIT(1)                   /*!< event from line 1 */
+#define EXTI_EVEN_EVEN2              BIT(2)                   /*!< event from line 2 */
+#define EXTI_EVEN_EVEN3              BIT(3)                   /*!< event from line 3 */
+#define EXTI_EVEN_EVEN4              BIT(4)                   /*!< event from line 4 */
+#define EXTI_EVEN_EVEN5              BIT(5)                   /*!< event from line 5 */
+#define EXTI_EVEN_EVEN6              BIT(6)                   /*!< event from line 6 */
+#define EXTI_EVEN_EVEN7              BIT(7)                   /*!< event from line 7 */
+#define EXTI_EVEN_EVEN8              BIT(8)                   /*!< event from line 8 */
+#define EXTI_EVEN_EVEN9              BIT(9)                   /*!< event from line 9 */
+#define EXTI_EVEN_EVEN10             BIT(10)                  /*!< event from line 10 */
+#define EXTI_EVEN_EVEN11             BIT(11)                  /*!< event from line 11 */
+#define EXTI_EVEN_EVEN12             BIT(12)                  /*!< event from line 12 */
+#define EXTI_EVEN_EVEN13             BIT(13)                  /*!< event from line 13 */
+#define EXTI_EVEN_EVEN14             BIT(14)                  /*!< event from line 14 */
+#define EXTI_EVEN_EVEN15             BIT(15)                  /*!< event from line 15 */
+#define EXTI_EVEN_EVEN16             BIT(16)                  /*!< event from line 16 */
+#define EXTI_EVEN_EVEN17             BIT(17)                  /*!< event from line 17 */
+#define EXTI_EVEN_EVEN18             BIT(18)                  /*!< event from line 18 */
+#define EXTI_EVEN_EVEN19             BIT(19)                  /*!< event from line 19 */
+
+/* EXTI_RTEN */
+#define EXTI_RTEN_RTEN0              BIT(0)                   /*!< rising edge from line 0 */
+#define EXTI_RTEN_RTEN1              BIT(1)                   /*!< rising edge from line 1 */
+#define EXTI_RTEN_RTEN2              BIT(2)                   /*!< rising edge from line 2 */
+#define EXTI_RTEN_RTEN3              BIT(3)                   /*!< rising edge from line 3 */
+#define EXTI_RTEN_RTEN4              BIT(4)                   /*!< rising edge from line 4 */
+#define EXTI_RTEN_RTEN5              BIT(5)                   /*!< rising edge from line 5 */
+#define EXTI_RTEN_RTEN6              BIT(6)                   /*!< rising edge from line 6 */
+#define EXTI_RTEN_RTEN7              BIT(7)                   /*!< rising edge from line 7 */
+#define EXTI_RTEN_RTEN8              BIT(8)                   /*!< rising edge from line 8 */
+#define EXTI_RTEN_RTEN9              BIT(9)                   /*!< rising edge from line 9 */
+#define EXTI_RTEN_RTEN10             BIT(10)                  /*!< rising edge from line 10 */
+#define EXTI_RTEN_RTEN11             BIT(11)                  /*!< rising edge from line 11 */
+#define EXTI_RTEN_RTEN12             BIT(12)                  /*!< rising edge from line 12 */
+#define EXTI_RTEN_RTEN13             BIT(13)                  /*!< rising edge from line 13 */
+#define EXTI_RTEN_RTEN14             BIT(14)                  /*!< rising edge from line 14 */
+#define EXTI_RTEN_RTEN15             BIT(15)                  /*!< rising edge from line 15 */
+#define EXTI_RTEN_RTEN16             BIT(16)                  /*!< rising edge from line 16 */
+#define EXTI_RTEN_RTEN17             BIT(17)                  /*!< rising edge from line 17 */
+#define EXTI_RTEN_RTEN18             BIT(18)                  /*!< rising edge from line 18 */
+#define EXTI_RTEN_RTEN19             BIT(19)                  /*!< rising edge from line 19 */
+
+/* EXTI_FTEN */
+#define EXTI_FTEN_FTEN0              BIT(0)                   /*!< falling edge from line 0 */
+#define EXTI_FTEN_FTEN1              BIT(1)                   /*!< falling edge from line 1 */
+#define EXTI_FTEN_FTEN2              BIT(2)                   /*!< falling edge from line 2 */
+#define EXTI_FTEN_FTEN3              BIT(3)                   /*!< falling edge from line 3 */
+#define EXTI_FTEN_FTEN4              BIT(4)                   /*!< falling edge from line 4 */
+#define EXTI_FTEN_FTEN5              BIT(5)                   /*!< falling edge from line 5 */
+#define EXTI_FTEN_FTEN6              BIT(6)                   /*!< falling edge from line 6 */
+#define EXTI_FTEN_FTEN7              BIT(7)                   /*!< falling edge from line 7 */
+#define EXTI_FTEN_FTEN8              BIT(8)                   /*!< falling edge from line 8 */
+#define EXTI_FTEN_FTEN9              BIT(9)                   /*!< falling edge from line 9 */
+#define EXTI_FTEN_FTEN10             BIT(10)                  /*!< falling edge from line 10 */
+#define EXTI_FTEN_FTEN11             BIT(11)                  /*!< falling edge from line 11 */
+#define EXTI_FTEN_FTEN12             BIT(12)                  /*!< falling edge from line 12 */
+#define EXTI_FTEN_FTEN13             BIT(13)                  /*!< falling edge from line 13 */
+#define EXTI_FTEN_FTEN14             BIT(14)                  /*!< falling edge from line 14 */
+#define EXTI_FTEN_FTEN15             BIT(15)                  /*!< falling edge from line 15 */
+#define EXTI_FTEN_FTEN16             BIT(16)                  /*!< falling edge from line 16 */
+#define EXTI_FTEN_FTEN17             BIT(17)                  /*!< falling edge from line 17 */
+#define EXTI_FTEN_FTEN18             BIT(18)                  /*!< falling edge from line 18 */
+#define EXTI_FTEN_FTEN19             BIT(19)                  /*!< falling edge from line 19 */
+
+/* EXTI_SWIEV */
+#define EXTI_SWIEV_SWIEV0            BIT(0)                   /*!< software interrupt/event request from line 0 */
+#define EXTI_SWIEV_SWIEV1            BIT(1)                   /*!< software interrupt/event request from line 1 */
+#define EXTI_SWIEV_SWIEV2            BIT(2)                   /*!< software interrupt/event request from line 2 */
+#define EXTI_SWIEV_SWIEV3            BIT(3)                   /*!< software interrupt/event request from line 3 */
+#define EXTI_SWIEV_SWIEV4            BIT(4)                   /*!< software interrupt/event request from line 4 */
+#define EXTI_SWIEV_SWIEV5            BIT(5)                   /*!< software interrupt/event request from line 5 */
+#define EXTI_SWIEV_SWIEV6            BIT(6)                   /*!< software interrupt/event request from line 6 */
+#define EXTI_SWIEV_SWIEV7            BIT(7)                   /*!< software interrupt/event request from line 7 */
+#define EXTI_SWIEV_SWIEV8            BIT(8)                   /*!< software interrupt/event request from line 8 */
+#define EXTI_SWIEV_SWIEV9            BIT(9)                   /*!< software interrupt/event request from line 9 */
+#define EXTI_SWIEV_SWIEV10           BIT(10)                  /*!< software interrupt/event request from line 10 */
+#define EXTI_SWIEV_SWIEV11           BIT(11)                  /*!< software interrupt/event request from line 11 */
+#define EXTI_SWIEV_SWIEV12           BIT(12)                  /*!< software interrupt/event request from line 12 */
+#define EXTI_SWIEV_SWIEV13           BIT(13)                  /*!< software interrupt/event request from line 13 */
+#define EXTI_SWIEV_SWIEV14           BIT(14)                  /*!< software interrupt/event request from line 14 */
+#define EXTI_SWIEV_SWIEV15           BIT(15)                  /*!< software interrupt/event request from line 15 */
+#define EXTI_SWIEV_SWIEV16           BIT(16)                  /*!< software interrupt/event request from line 16 */
+#define EXTI_SWIEV_SWIEV17           BIT(17)                  /*!< software interrupt/event request from line 17 */
+#define EXTI_SWIEV_SWIEV18           BIT(18)                  /*!< software interrupt/event request from line 18 */
+#define EXTI_SWIEV_SWIEV19           BIT(19)                  /*!< software interrupt/event request from line 19 */
+
+/* EXTI_PD */
+#define EXTI_PD_PD0                  BIT(0)                   /*!< interrupt/event pending status from line 0 */
+#define EXTI_PD_PD1                  BIT(1)                   /*!< interrupt/event pending status from line 1 */
+#define EXTI_PD_PD2                  BIT(2)                   /*!< interrupt/event pending status from line 2 */
+#define EXTI_PD_PD3                  BIT(3)                   /*!< interrupt/event pending status from line 3 */
+#define EXTI_PD_PD4                  BIT(4)                   /*!< interrupt/event pending status from line 4 */
+#define EXTI_PD_PD5                  BIT(5)                   /*!< interrupt/event pending status from line 5 */
+#define EXTI_PD_PD6                  BIT(6)                   /*!< interrupt/event pending status from line 6 */
+#define EXTI_PD_PD7                  BIT(7)                   /*!< interrupt/event pending status from line 7 */
+#define EXTI_PD_PD8                  BIT(8)                   /*!< interrupt/event pending status from line 8 */
+#define EXTI_PD_PD9                  BIT(9)                   /*!< interrupt/event pending status from line 9 */
+#define EXTI_PD_PD10                 BIT(10)                  /*!< interrupt/event pending status from line 10 */
+#define EXTI_PD_PD11                 BIT(11)                  /*!< interrupt/event pending status from line 11 */
+#define EXTI_PD_PD12                 BIT(12)                  /*!< interrupt/event pending status from line 12 */
+#define EXTI_PD_PD13                 BIT(13)                  /*!< interrupt/event pending status from line 13 */
+#define EXTI_PD_PD14                 BIT(14)                  /*!< interrupt/event pending status from line 14 */
+#define EXTI_PD_PD15                 BIT(15)                  /*!< interrupt/event pending status from line 15 */
+#define EXTI_PD_PD16                 BIT(16)                  /*!< interrupt/event pending status from line 16 */
+#define EXTI_PD_PD17                 BIT(17)                  /*!< interrupt/event pending status from line 17 */
+#define EXTI_PD_PD18                 BIT(18)                  /*!< interrupt/event pending status from line 18 */
+#define EXTI_PD_PD19                 BIT(19)                  /*!< interrupt/event pending status from line 19 */
+
+/* constants definitions */
+/* EXTI line number */
+typedef enum
+{ 
+    EXTI_0      = BIT(0),                                     /*!< EXTI line 0 */
+    EXTI_1      = BIT(1),                                     /*!< EXTI line 1 */
+    EXTI_2      = BIT(2),                                     /*!< EXTI line 2 */
+    EXTI_3      = BIT(3),                                     /*!< EXTI line 3 */
+    EXTI_4      = BIT(4),                                     /*!< EXTI line 4 */
+    EXTI_5      = BIT(5),                                     /*!< EXTI line 5 */
+    EXTI_6      = BIT(6),                                     /*!< EXTI line 6 */
+    EXTI_7      = BIT(7),                                     /*!< EXTI line 7 */
+    EXTI_8      = BIT(8),                                     /*!< EXTI line 8 */
+    EXTI_9      = BIT(9),                                     /*!< EXTI line 9 */
+    EXTI_10     = BIT(10),                                    /*!< EXTI line 10 */
+    EXTI_11     = BIT(11),                                    /*!< EXTI line 11 */
+    EXTI_12     = BIT(12),                                    /*!< EXTI line 12 */
+    EXTI_13     = BIT(13),                                    /*!< EXTI line 13 */
+    EXTI_14     = BIT(14),                                    /*!< EXTI line 14 */
+    EXTI_15     = BIT(15),                                    /*!< EXTI line 15 */
+    EXTI_16     = BIT(16),                                    /*!< EXTI line 16 */
+    EXTI_17     = BIT(17),                                    /*!< EXTI line 17 */
+    EXTI_18     = BIT(18),                                    /*!< EXTI line 18 */
+    EXTI_19     = BIT(19),                                    /*!< EXTI line 19 */
+}exti_line_enum;
+
+/* external interrupt and event  */
+typedef enum
+{
+    EXTI_INTERRUPT   = 0,                                     /*!< EXTI interrupt mode */
+    EXTI_EVENT                                                /*!< EXTI event mode */
+}exti_mode_enum;
+
+/* interrupt trigger mode */
+typedef enum
+{ 
+    EXTI_TRIG_RISING = 0,                                     /*!< EXTI rising edge trigger */
+    EXTI_TRIG_FALLING,                                        /*!< EXTI falling edge trigger */
+    EXTI_TRIG_BOTH,                                           /*!< EXTI rising and falling edge trigger */
+    EXTI_TRIG_NONE                                            /*!< without rising edge or falling edge trigger */
+}exti_trig_type_enum;
+
+/* function declarations */
+/* initialization, EXTI lines configuration functions */
+/* deinitialize the EXTI */
+void exti_deinit(void);
+/* enable the configuration of EXTI initialize */
+void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type);
+/* enable the interrupts from EXTI line x */
+void exti_interrupt_enable(exti_line_enum linex);
+/* enable the events from EXTI line x */
+void exti_event_enable(exti_line_enum linex);
+/* disable the interrupts from EXTI line x */
+void exti_interrupt_disable(exti_line_enum linex);
+/* disable the events from EXTI line x */
+void exti_event_disable(exti_line_enum linex);
+
+/* interrupt & flag functions */
+/* get EXTI lines pending flag */
+FlagStatus exti_flag_get(exti_line_enum linex);
+/* clear EXTI lines pending flag */
+void exti_flag_clear(exti_line_enum linex);
+/* get EXTI lines flag when the interrupt flag is set */
+FlagStatus exti_interrupt_flag_get(exti_line_enum linex);
+/* clear EXTI lines pending flag */
+void exti_interrupt_flag_clear(exti_line_enum linex);
+/* enable the EXTI software interrupt event  */
+void exti_software_interrupt_enable(exti_line_enum linex);
+/* disable the EXTI software interrupt event  */
+void exti_software_interrupt_disable(exti_line_enum linex);
+
+#endif /* GD32F10X_EXTI_H */

+ 370 - 0
Library/Include/gd32f10x_fmc.h

@@ -0,0 +1,370 @@
+/*!
+    \file    gd32f10x_fmc.h
+    \brief   definitions for the FMC
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_FMC_H
+#define GD32F10X_FMC_H
+
+#include "gd32f10x.h"
+
+/* FMC and option byte definition */
+#define FMC                        FMC_BASE                       /*!< FMC register base address */
+#define OB                         OB_BASE                        /*!< option bytes base address */
+
+/* registers definitions */
+#define FMC_WS                     REG32((FMC) + 0x00U)                          /*!< FMC wait state register */
+#define FMC_KEY0                   REG32((FMC) + 0x04U)                          /*!< FMC unlock key register 0 */
+#define FMC_OBKEY                  REG32((FMC) + 0x08U)                          /*!< FMC option bytes unlock key register */
+#define FMC_STAT0                  REG32((FMC) + 0x0CU)                          /*!< FMC status register 0 */
+#define FMC_CTL0                   REG32((FMC) + 0x10U)                          /*!< FMC control register 0 */
+#define FMC_ADDR0                  REG32((FMC) + 0x14U)                          /*!< FMC address register 0 */
+#define FMC_OBSTAT                 REG32((FMC) + 0x1CU)                          /*!< FMC option bytes status register */
+#define FMC_WP                     REG32((FMC) + 0x20U)                          /*!< FMC erase/program protection register */
+#define FMC_KEY1                   REG32((FMC) + 0x44U)                          /*!< FMC unlock key register 1 */
+#define FMC_STAT1                  REG32((FMC) + 0x4CU)                          /*!< FMC status register 1 */
+#define FMC_CTL1                   REG32((FMC) + 0x50U)                          /*!< FMC control register 1 */
+#define FMC_ADDR1                  REG32((FMC) + 0x54U)                          /*!< FMC address register 1 */
+#define FMC_WSEN                   REG32((FMC) + 0xFCU)                          /*!< FMC wait state enable register */
+#define FMC_PID                    REG32((FMC) + 0x100U)                         /*!< FMC product ID register */
+
+#define OB_SPC                     REG16((OB) + 0x00U)                           /*!< option byte security protection value */
+#define OB_USER                    REG16((OB) + 0x02U)                           /*!< option byte user value*/
+#define OB_WP0                     REG16((OB) + 0x08U)                           /*!< option byte write protection 0 */
+#define OB_WP1                     REG16((OB) + 0x0AU)                           /*!< option byte write protection 1 */
+#define OB_WP2                     REG16((OB) + 0x0CU)                           /*!< option byte write protection 2 */
+#define OB_WP3                     REG16((OB) + 0x0EU)                           /*!< option byte write protection 3 */
+
+/* bits definitions */
+/* FMC_WS */
+#define FMC_WS_WSCNT               BITS(0,2)                                     /*!< wait state counter */
+
+/* FMC_KEY0 */
+#define FMC_KEY0_KEY               BITS(0,31)                                    /*!< FMC_CTL0 unlock key bits */
+
+/* FMC_OBKEY */
+#define FMC_OBKEY_OBKEY            BITS(0,31)                                    /*!< option bytes unlock key bits */
+
+/* FMC_STAT0 */
+#define FMC_STAT0_BUSY             BIT(0)                                        /*!< flash busy flag bit */
+#define FMC_STAT0_PGERR            BIT(2)                                        /*!< flash program error flag bit */
+#define FMC_STAT0_WPERR            BIT(4)                                        /*!< erase/program protection error flag bit */
+#define FMC_STAT0_ENDF             BIT(5)                                        /*!< end of operation flag bit */
+
+/* FMC_CTL0 */
+#define FMC_CTL0_PG                BIT(0)                                        /*!< main flash program for bank0 command bit */
+#define FMC_CTL0_PER               BIT(1)                                        /*!< main flash page erase for bank0 command bit */
+#define FMC_CTL0_MER               BIT(2)                                        /*!< main flash mass erase for bank0 command bit */
+#define FMC_CTL0_OBPG              BIT(4)                                        /*!< option bytes program command bit */
+#define FMC_CTL0_OBER              BIT(5)                                        /*!< option bytes erase command bit */
+#define FMC_CTL0_START             BIT(6)                                        /*!< send erase command to FMC bit */
+#define FMC_CTL0_LK                BIT(7)                                        /*!< FMC_CTL0 lock bit */
+#define FMC_CTL0_OBWEN             BIT(9)                                        /*!< option bytes erase/program enable bit */
+#define FMC_CTL0_ERRIE             BIT(10)                                       /*!< error interrupt enable bit */
+#define FMC_CTL0_ENDIE             BIT(12)                                       /*!< end of operation interrupt enable bit */
+
+/* FMC_ADDR0 */
+#define FMC_ADDR0_ADDR             BITS(0,31)                                    /*!< flash erase/program command address bits */
+
+/* FMC_OBSTAT */
+#define FMC_OBSTAT_OBERR           BIT(0)                                        /*!< option bytes read error bit. */
+#define FMC_OBSTAT_SPC             BIT(1)                                        /*!< option bytes security protection code */
+#define FMC_OBSTAT_USER            BITS(2,9)                                     /*!< store USER of option bytes block after system reset */
+#define FMC_OBSTAT_DATA            BITS(10,25)                                   /*!< store DATA of option bytes block after system reset. */
+
+/* FMC_WP */
+#define FMC_WP_WP                  BITS(0,31)                                    /*!< store WP of option bytes block after system reset */
+
+/* FMC_KEY1 */
+#define FMC_KEY1_KEY               BITS(0,31)                                    /*!< FMC_CTL1 unlock key bits */
+
+/* FMC_STAT1 */
+#define FMC_STAT1_BUSY             BIT(0)                                        /*!< flash busy flag bit */
+#define FMC_STAT1_PGERR            BIT(2)                                        /*!< flash program error flag bit */
+#define FMC_STAT1_WPERR            BIT(4)                                        /*!< erase/program protection error flag bit */
+#define FMC_STAT1_ENDF             BIT(5)                                        /*!< end of operation flag bit */
+
+/* FMC_CTL1 */
+#define FMC_CTL1_PG                BIT(0)                                        /*!< main flash program for bank1 command bit */
+#define FMC_CTL1_PER               BIT(1)                                        /*!< main flash page erase for bank1 command bit */
+#define FMC_CTL1_MER               BIT(2)                                        /*!< main flash mass erase for bank1 command bit */
+#define FMC_CTL1_START             BIT(6)                                        /*!< send erase command to FMC bit */
+#define FMC_CTL1_LK                BIT(7)                                        /*!< FMC_CTL1 lock bit */
+#define FMC_CTL1_ERRIE             BIT(10)                                       /*!< error interrupt enable bit */
+#define FMC_CTL1_ENDIE             BIT(12)                                       /*!< end of operation interrupt enable bit */
+
+/* FMC_ADDR1 */
+#define FMC_ADDR1_ADDR             BITS(0,31)                                    /*!< flash erase/program command address bits */
+
+/* FMC_WSEN */
+#define FMC_WSEN_WSEN              BIT(0)                                        /*!< FMC wait state enable bit */
+
+/* FMC_PID */
+#define FMC_PID_PID                BITS(0,31)                                    /*!< product ID bits */
+
+/* constants definitions */
+/* define the FMC bit position and its register index offset */
+#define FMC_REGIDX_BIT(regidx, bitpos)              (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define FMC_REG_VAL(offset)                         (REG32(FMC + ((uint32_t)(offset) >> 6)))
+#define FMC_BIT_POS(val)                            ((uint32_t)(val) & 0x1FU)
+#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1)   (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1))
+#define FMC_REG_VALS(offset)                        (REG32(FMC + ((uint32_t)(offset) >> 12)))
+#define FMC_BIT_POS0(val)                           (((uint32_t)(val) >> 6) & 0x1FU)
+#define FMC_BIT_POS1(val)                           ((uint32_t)(val) & 0x1FU)
+#define FMC_REG_OFFSET_GET(flag)                    ((uint32_t)(flag) >> 12)
+
+/* configuration register */
+#define FMC_STAT0_REG_OFFSET             0x0CU                                   /*!< status register 0 offset */
+#define FMC_CTL0_REG_OFFSET              0x10U                                   /*!< control register 0 offset */
+#define FMC_STAT1_REG_OFFSET             0x4CU                                   /*!< status register 1 offset */
+#define FMC_CTL1_REG_OFFSET              0x50U                                   /*!< control register 1 offset */
+#define FMC_OBSTAT_REG_OFFSET            0x1CU                                   /*!< option byte status register offset */
+
+/* fmc state */
+typedef enum
+{
+    FMC_READY,                                                                   /*!< the operation has been completed */
+    FMC_BUSY,                                                                    /*!< the operation is in progress */
+    FMC_PGERR,                                                                   /*!< program error */
+    FMC_WPERR,                                                                   /*!< erase/program protection error */
+    FMC_TOERR,                                                                   /*!< timeout error */
+}fmc_state_enum;
+
+/* FMC interrupt enable */
+typedef enum
+{
+    FMC_INT_BANK0_END     = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U),            /*!< enable FMC end of program interrupt */
+    FMC_INT_BANK0_ERR     = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U),            /*!< enable FMC error interrupt */
+    FMC_INT_BANK1_END     = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U),            /*!< enable FMC bank1 end of program interrupt */
+    FMC_INT_BANK1_ERR     = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U),            /*!< enable FMC bank1 error interrupt */
+}fmc_int_enum;
+
+/* FMC flags */
+typedef enum
+{
+    FMC_FLAG_BANK0_BUSY   = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U),            /*!< FMC bank0 busy flag */
+    FMC_FLAG_BANK0_PGERR  = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U),            /*!< FMC bank0 operation error flag bit */
+    FMC_FLAG_BANK0_WPERR  = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U),            /*!< FMC bank0 erase/program protection error flag bit */
+    FMC_FLAG_BANK0_END    = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U),            /*!< FMC bank0 end of operation flag bit */
+    FMC_FLAG_OBERR        = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U),           /*!< FMC option bytes read error flag */
+    FMC_FLAG_BANK1_BUSY   = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U),            /*!< FMC bank1 busy flag */
+    FMC_FLAG_BANK1_PGERR  = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U),            /*!< FMC bank1 operation error flag bit */
+    FMC_FLAG_BANK1_WPERR  = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U),            /*!< FMC bank1 erase/program protection error flag bit */
+    FMC_FLAG_BANK1_END    = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U),            /*!< FMC bank1 end of operation flag bit */
+}fmc_flag_enum;
+
+/* FMC interrupt flags */
+typedef enum
+{
+    FMC_INT_FLAG_BANK0_PGERR  = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U),  /*!< FMC bank0 operation error interrupt flag bit */
+    FMC_INT_FLAG_BANK0_WPERR  = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U),  /*!< FMC bank0 erase/program protection error interrupt flag bit */
+    FMC_INT_FLAG_BANK0_END    = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U),  /*!< FMC bank0 end of operation interrupt flag bit */
+    FMC_INT_FLAG_BANK1_PGERR  = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U),  /*!< FMC bank1 operation error interrupt flag bit */
+    FMC_INT_FLAG_BANK1_WPERR  = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U),  /*!< FMC bank1 erase/program protection error interrupt flag bit */
+    FMC_INT_FLAG_BANK1_END    = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U),  /*!< FMC bank1 end of operation interrupt flag bit */
+}fmc_interrupt_flag_enum;
+
+/* unlock key */
+#define UNLOCK_KEY0                ((uint32_t)0x45670123U)                       /*!< unlock key 0 */
+#define UNLOCK_KEY1                ((uint32_t)0xCDEF89ABU)                       /*!< unlock key 1 */
+
+/* FMC wait state counter */
+#define WS_WSCNT(regval)           (BITS(0,2) & ((uint32_t)(regval)))
+#define WS_WSCNT_0                 WS_WSCNT(0)                                   /*!< FMC 0 wait */
+#define WS_WSCNT_1                 WS_WSCNT(1)                                   /*!< FMC 1 wait */
+#define WS_WSCNT_2                 WS_WSCNT(2)                                   /*!< FMC 2 wait */
+
+/* option bytes software/hardware free watch dog timer */  
+#define OB_FWDGT_SW                ((uint8_t)0x01U)                              /*!< software free watchdog */
+#define OB_FWDGT_HW                ((uint8_t)0x00U)                              /*!< hardware free watchdog */
+
+/* option bytes reset or not entering deep sleep mode */
+#define OB_DEEPSLEEP_NRST          ((uint8_t)0x02U)                              /*!< no reset when entering deepsleep mode */
+#define OB_DEEPSLEEP_RST           ((uint8_t)0x00U)                              /*!< generate a reset instead of entering deepsleep mode */
+
+/* option bytes reset or not entering standby mode */
+#define OB_STDBY_NRST              ((uint8_t)0x04U)                              /*!< no reset when entering deepsleep mode */
+#define OB_STDBY_RST               ((uint8_t)0x00U)                              /*!< generate a reset instead of entering standby mode */
+
+/* option bytes boot bank value */
+#define OB_BOOT_B0                 ((uint8_t)0x08U)                              /*!< boot from bank0 */
+#define OB_BOOT_B1                 ((uint8_t)0x00U)                              /*!< boot from bank1 */
+
+#define OB_USER_MASK               ((uint8_t)0xF0U)                              /*!< MASK value */
+
+/* read protect configure */
+#define FMC_NSPC                   ((uint8_t)0xA5U)                              /*!< no security protection */
+#define FMC_USPC                   ((uint8_t)0xBBU)                              /*!< under security protection */
+
+/* OB_SPC */
+#define OB_SPC_SPC                 ((uint32_t)0x000000FFU)                       /*!< option byte security protection value */
+#define OB_SPC_SPC_N               ((uint32_t)0x0000FF00U)                       /*!< option byte security protection complement value */
+
+/* OB_USER */
+#define OB_USER_USER               ((uint32_t)0x00FF0000U)                       /*!< user option value */
+#define OB_USER_USER_N             ((uint32_t)0xFF000000U)                       /*!< user option complement value */
+
+/* OB_WP0 */
+#define OB_WP0_WP0                 ((uint32_t)0x000000FFU)                       /*!< FMC write protection option value */
+
+/* OB_WP1 */
+#define OB_WP1_WP1                 ((uint32_t)0x0000FF00U)                       /*!< FMC write protection option complement value */
+
+/* OB_WP2 */
+#define OB_WP2_WP2                 ((uint32_t)0x00FF0000U)                       /*!< FMC write protection option value */
+
+/* OB_WP3 */
+#define OB_WP3_WP3                 ((uint32_t)0xFF000000U)                       /*!< FMC write protection option complement value */
+
+/* option bytes write protection */
+#define OB_WP_0                    ((uint32_t)0x00000001U)                       /*!< erase/program protection of sector 0  */
+#define OB_WP_1                    ((uint32_t)0x00000002U)                       /*!< erase/program protection of sector 1  */
+#define OB_WP_2                    ((uint32_t)0x00000004U)                       /*!< erase/program protection of sector 2  */
+#define OB_WP_3                    ((uint32_t)0x00000008U)                       /*!< erase/program protection of sector 3  */
+#define OB_WP_4                    ((uint32_t)0x00000010U)                       /*!< erase/program protection of sector 4  */
+#define OB_WP_5                    ((uint32_t)0x00000020U)                       /*!< erase/program protection of sector 5  */
+#define OB_WP_6                    ((uint32_t)0x00000040U)                       /*!< erase/program protection of sector 6  */
+#define OB_WP_7                    ((uint32_t)0x00000080U)                       /*!< erase/program protection of sector 7  */
+#define OB_WP_8                    ((uint32_t)0x00000100U)                       /*!< erase/program protection of sector 8  */
+#define OB_WP_9                    ((uint32_t)0x00000200U)                       /*!< erase/program protection of sector 9  */
+#define OB_WP_10                   ((uint32_t)0x00000400U)                       /*!< erase/program protection of sector 10 */
+#define OB_WP_11                   ((uint32_t)0x00000800U)                       /*!< erase/program protection of sector 11 */
+#define OB_WP_12                   ((uint32_t)0x00001000U)                       /*!< erase/program protection of sector 12 */
+#define OB_WP_13                   ((uint32_t)0x00002000U)                       /*!< erase/program protection of sector 13 */
+#define OB_WP_14                   ((uint32_t)0x00004000U)                       /*!< erase/program protection of sector 14 */
+#define OB_WP_15                   ((uint32_t)0x00008000U)                       /*!< erase/program protection of sector 15 */
+#define OB_WP_16                   ((uint32_t)0x00010000U)                       /*!< erase/program protection of sector 16 */
+#define OB_WP_17                   ((uint32_t)0x00020000U)                       /*!< erase/program protection of sector 17 */
+#define OB_WP_18                   ((uint32_t)0x00040000U)                       /*!< erase/program protection of sector 18 */
+#define OB_WP_19                   ((uint32_t)0x00080000U)                       /*!< erase/program protection of sector 19 */
+#define OB_WP_20                   ((uint32_t)0x00100000U)                       /*!< erase/program protection of sector 20 */
+#define OB_WP_21                   ((uint32_t)0x00200000U)                       /*!< erase/program protection of sector 21 */
+#define OB_WP_22                   ((uint32_t)0x00400000U)                       /*!< erase/program protection of sector 22 */
+#define OB_WP_23                   ((uint32_t)0x00800000U)                       /*!< erase/program protection of sector 23 */
+#define OB_WP_24                   ((uint32_t)0x01000000U)                       /*!< erase/program protection of sector 24 */
+#define OB_WP_25                   ((uint32_t)0x02000000U)                       /*!< erase/program protection of sector 25 */
+#define OB_WP_26                   ((uint32_t)0x04000000U)                       /*!< erase/program protection of sector 26 */
+#define OB_WP_27                   ((uint32_t)0x08000000U)                       /*!< erase/program protection of sector 27 */
+#define OB_WP_28                   ((uint32_t)0x10000000U)                       /*!< erase/program protection of sector 28 */
+#define OB_WP_29                   ((uint32_t)0x20000000U)                       /*!< erase/program protection of sector 29 */
+#define OB_WP_30                   ((uint32_t)0x40000000U)                       /*!< erase/program protection of sector 30 */
+#define OB_WP_31                   ((uint32_t)0x80000000U)                       /*!< erase/program protection of sector 31 */
+#define OB_WP_ALL                  ((uint32_t)0xFFFFFFFFU)                       /*!< erase/program protection of all sectors */
+
+/* FMC timeout */
+#define FMC_TIMEOUT_COUNT          ((uint32_t)0x000F0000U)                       /*!< FMC timeout count value */
+
+/* FMC BANK address */
+#define FMC_BANK0_END_ADDRESS      ((uint32_t)0x0807FFFFU)                       /*!< FMC bank0 end address */
+#define FMC_BANK0_SIZE             ((uint32_t)0x00000200U)                       /*!< FMC bank0 size */
+#define FMC_SIZE                   (*(uint16_t *)0x1FFFF7E0U)                    /*!< FMC size */
+
+/* function declarations */
+/* FMC main memory programming functions */
+/* set the FMC wait state counter */
+void fmc_wscnt_set(uint32_t wscnt);
+/* unlock the main FMC operation */
+void fmc_unlock(void);
+/* unlock the FMC bank0 operation */
+void fmc_bank0_unlock(void);
+/* unlock the FMC bank1 operation */
+void fmc_bank1_unlock(void);
+/* lock the main FMC operation */
+void fmc_lock(void);
+/* lock the bank0 FMC operation */
+void fmc_bank0_lock(void);
+/* lock the bank1 FMC operation */
+void fmc_bank1_lock(void);
+/* FMC erase page */
+fmc_state_enum fmc_page_erase(uint32_t page_address);
+/* FMC erase whole chip */
+fmc_state_enum fmc_mass_erase(void);
+/* FMC erase whole bank0 */
+fmc_state_enum fmc_bank0_erase(void);
+/* FMC erase whole bank1 */
+fmc_state_enum fmc_bank1_erase(void);
+/* FMC program a word at the corresponding address */
+fmc_state_enum fmc_word_program(uint32_t address, uint32_t data);
+/* FMC program a half word at the corresponding address */
+fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data);
+
+/* FMC option bytes programming functions */
+/* unlock the option byte operation */
+void ob_unlock(void);
+/* lock the option byte operation */
+void ob_lock(void);
+/* erase the option byte */
+fmc_state_enum ob_erase(void);
+/* enable write protect */
+fmc_state_enum ob_write_protection_enable(uint32_t ob_wp);
+/* configure the option byte security protection */
+fmc_state_enum ob_security_protection_config(uint8_t ob_spc);
+/* write the FMC option byte */
+fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot);
+/* program option bytes data */
+fmc_state_enum ob_data_program(uint32_t address, uint8_t data);
+/* get the FMC option byte user */
+uint8_t ob_user_get(void);
+/* get OB_DATA in register FMC_OBSTAT */
+uint16_t ob_data_get(void);
+/* get the FMC option byte write protection */
+uint32_t ob_write_protection_get(void);
+/* get option byte security protection code value */
+FlagStatus ob_spc_get(void);
+
+/* FMC interrupts and flags management functions */
+/* enable FMC interrupt */
+void fmc_interrupt_enable(uint32_t interrupt);
+/* disable FMC interrupt */
+void fmc_interrupt_disable(uint32_t interrupt);
+/* check flag is set or not */
+FlagStatus fmc_flag_get(uint32_t flag);
+/* clear the FMC flag */
+void fmc_flag_clear(uint32_t flag);
+/* get FMC interrupt flag state */
+FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag);
+/* clear FMC interrupt flag state */
+void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag);
+/* return the  FMC bank0 state */
+fmc_state_enum fmc_bank0_state_get(void);
+/* return the  FMC bank1 state */
+fmc_state_enum fmc_bank1_state_get(void);
+/* check FMC bank0 ready or not */
+fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout);
+/* check FMC bank1 ready or not */
+fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout);
+
+
+#endif /* GD32F10X_FMC_H */

+ 107 - 0
Library/Include/gd32f10x_fwdgt.h

@@ -0,0 +1,107 @@
+/*!
+    \file    gd32f10x_fwdgt.h
+    \brief   definitions for the FWDGT
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_FWDGT_H
+#define GD32F10X_FWDGT_H
+
+#include "gd32f10x.h"
+
+/* FWDGT definitions */
+#define FWDGT                       FWDGT_BASE                                /*!< FWDGT base address */
+
+/* registers definitions */
+#define FWDGT_CTL                   REG32((FWDGT) + 0x00U)                    /*!< FWDGT control register */
+#define FWDGT_PSC                   REG32((FWDGT) + 0x04U)                    /*!< FWDGT prescaler register */
+#define FWDGT_RLD                   REG32((FWDGT) + 0x08U)                    /*!< FWDGT reload register */
+#define FWDGT_STAT                  REG32((FWDGT) + 0x0CU)                    /*!< FWDGT status register */
+
+/* bits definitions */
+/* FWDGT_CTL */
+#define FWDGT_CTL_CMD               BITS(0,15)                                /*!< FWDGT command value */
+
+/* FWDGT_PSC */
+#define FWDGT_PSC_PSC               BITS(0,2)                                 /*!< FWDGT prescaler divider value */
+
+/* FWDGT_RLD */
+#define FWDGT_RLD_RLD               BITS(0,11)                                /*!< FWDGT counter reload value */
+
+/* FWDGT_STAT */
+#define FWDGT_STAT_PUD              BIT(0)                                    /*!< FWDGT prescaler divider value update */
+#define FWDGT_STAT_RUD              BIT(1)                                    /*!< FWDGT counter reload value update */
+
+/* constants definitions */
+/* psc register value */
+#define PSC_PSC(regval)             (BITS(0,2) & ((uint32_t)(regval) << 0))
+#define FWDGT_PSC_DIV4              ((uint8_t)PSC_PSC(0))                     /*!< FWDGT prescaler set to 4 */
+#define FWDGT_PSC_DIV8              ((uint8_t)PSC_PSC(1))                     /*!< FWDGT prescaler set to 8 */
+#define FWDGT_PSC_DIV16             ((uint8_t)PSC_PSC(2))                     /*!< FWDGT prescaler set to 16 */
+#define FWDGT_PSC_DIV32             ((uint8_t)PSC_PSC(3))                     /*!< FWDGT prescaler set to 32 */
+#define FWDGT_PSC_DIV64             ((uint8_t)PSC_PSC(4))                     /*!< FWDGT prescaler set to 64 */
+#define FWDGT_PSC_DIV128            ((uint8_t)PSC_PSC(5))                     /*!< FWDGT prescaler set to 128 */
+#define FWDGT_PSC_DIV256            ((uint8_t)PSC_PSC(6))                     /*!< FWDGT prescaler set to 256 */
+
+/* control value */
+#define FWDGT_WRITEACCESS_ENABLE    ((uint16_t)0x5555U)                       /*!< FWDGT_CTL bits write access enable value */
+#define FWDGT_WRITEACCESS_DISABLE   ((uint16_t)0x0000U)                       /*!< FWDGT_CTL bits write access disable value */
+#define FWDGT_KEY_RELOAD            ((uint16_t)0xAAAAU)                       /*!< FWDGT_CTL bits fwdgt counter reload value */
+#define FWDGT_KEY_ENABLE            ((uint16_t)0xCCCCU)                       /*!< FWDGT_CTL bits fwdgt counter enable value */
+
+/* FWDGT timeout value */
+#define FWDGT_PSC_TIMEOUT           ((uint32_t)0x000FFFFFU)                   /*!< FWDGT_PSC register write operation state flag timeout */
+#define FWDGT_RLD_TIMEOUT           ((uint32_t)0x000FFFFFU)                   /*!< FWDGT_RLD register write operation state flag timeout */
+
+/* FWDGT flag definitions */
+#define FWDGT_FLAG_PUD              FWDGT_STAT_PUD                            /*!< FWDGT prescaler divider value update flag */
+#define FWDGT_FLAG_RUD              FWDGT_STAT_RUD                            /*!< FWDGT counter reload value update flag */
+
+/* function declarations */
+/* enable write access to FWDGT_PSC and FWDGT_RLD */
+void fwdgt_write_enable(void);
+/* disable write access to FWDGT_PSC and FWDGT_RLD */
+void fwdgt_write_disable(void);
+/* start the free watchdog timer counter */
+void fwdgt_enable(void);
+
+/* reload the counter of FWDGT */
+void fwdgt_counter_reload(void);
+/* configure counter reload value, and prescaler divider value */
+ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div);
+
+/* get flag state of FWDGT */
+FlagStatus fwdgt_flag_get(uint16_t flag);
+
+#endif /* GD32F10X_FWDGT_H */

+ 498 - 0
Library/Include/gd32f10x_gpio.h

@@ -0,0 +1,498 @@
+/*!
+    \file    gd32f10x_gpio.h
+    \brief   definitions for the GPIO
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10x_GPIO_H
+#define GD32F10x_GPIO_H
+
+#include "gd32f10x.h"
+
+/* GPIOx(x=A,B,C,D,E,F,G) definitions */
+#define GPIOA                      (GPIO_BASE + 0x00000000U)
+#define GPIOB                      (GPIO_BASE + 0x00000400U)
+#define GPIOC                      (GPIO_BASE + 0x00000800U)
+#define GPIOD                      (GPIO_BASE + 0x00000C00U)
+#define GPIOE                      (GPIO_BASE + 0x00001000U)
+#define GPIOF                      (GPIO_BASE + 0x00001400U)
+#define GPIOG                      (GPIO_BASE + 0x00001800U)
+
+/* AFIO definitions */
+#define AFIO                       AFIO_BASE
+
+/* registers definitions */
+
+/* GPIO registers definitions */
+#define GPIO_CTL0(gpiox)           REG32((gpiox) + 0x00U)    /*!< GPIO port control register 0 */
+#define GPIO_CTL1(gpiox)           REG32((gpiox) + 0x04U)    /*!< GPIO port control register 1 */
+#define GPIO_ISTAT(gpiox)          REG32((gpiox) + 0x08U)    /*!< GPIO port input status register */
+#define GPIO_OCTL(gpiox)           REG32((gpiox) + 0x0CU)    /*!< GPIO port output control register */
+#define GPIO_BOP(gpiox)            REG32((gpiox) + 0x10U)    /*!< GPIO port bit operation register */
+#define GPIO_BC(gpiox)             REG32((gpiox) + 0x14U)    /*!< GPIO bit clear register */
+#define GPIO_LOCK(gpiox)           REG32((gpiox) + 0x18U)    /*!< GPIO port configuration lock register */
+
+/* AFIO registers definitions */
+#define AFIO_EC                    REG32(AFIO + 0x00U)       /*!< AFIO event control register */
+#define AFIO_PCF0                  REG32(AFIO + 0x04U)       /*!< AFIO port configuration register 0 */
+#define AFIO_EXTISS0               REG32(AFIO + 0x08U)       /*!< AFIO port EXTI sources selection register 0 */
+#define AFIO_EXTISS1               REG32(AFIO + 0x0CU)       /*!< AFIO port EXTI sources selection register 1 */
+#define AFIO_EXTISS2               REG32(AFIO + 0x10U)       /*!< AFIO port EXTI sources selection register 2 */
+#define AFIO_EXTISS3               REG32(AFIO + 0x14U)       /*!< AFIO port EXTI sources selection register 3 */
+#define AFIO_PCF1                  REG32(AFIO + 0x1CU)       /*!< AFIO port configuration register 1 */
+
+/* bits definitions */
+/* GPIO_CTL0 */
+#define GPIO_CTL0_MD0              BITS(0,1)                 /*!< port 0 mode bits */ 
+#define GPIO_CTL0_CTL0             BITS(2,3)                 /*!< pin 0 configuration bits */
+#define GPIO_CTL0_MD1              BITS(4,5)                 /*!< port 1 mode bits */
+#define GPIO_CTL0_CTL1             BITS(6,7)                 /*!< pin 1 configuration bits */
+#define GPIO_CTL0_MD2              BITS(8,9)                 /*!< port 2 mode bits */
+#define GPIO_CTL0_CTL2             BITS(10,11)               /*!< pin 2 configuration bits */
+#define GPIO_CTL0_MD3              BITS(12,13)               /*!< port 3 mode bits */
+#define GPIO_CTL0_CTL3             BITS(14,15)               /*!< pin 3 configuration bits */
+#define GPIO_CTL0_MD4              BITS(16,17)               /*!< port 4 mode bits */
+#define GPIO_CTL0_CTL4             BITS(18,19)               /*!< pin 4 configuration bits */
+#define GPIO_CTL0_MD5              BITS(20,21)               /*!< port 5 mode bits */
+#define GPIO_CTL0_CTL5             BITS(22,23)               /*!< pin 5 configuration bits */
+#define GPIO_CTL0_MD6              BITS(24,25)               /*!< port 6 mode bits */
+#define GPIO_CTL0_CTL6             BITS(26,27)               /*!< pin 6 configuration bits */
+#define GPIO_CTL0_MD7              BITS(28,29)               /*!< port 7 mode bits */
+#define GPIO_CTL0_CTL7             BITS(30,31)               /*!< pin 7 configuration bits */
+
+/* GPIO_CTL1 */
+#define GPIO_CTL1_MD8              BITS(0,1)                 /*!< port 8 mode bits */ 
+#define GPIO_CTL1_CTL8             BITS(2,3)                 /*!< pin 8 configuration bits */
+#define GPIO_CTL1_MD9              BITS(4,5)                 /*!< port 9 mode bits */
+#define GPIO_CTL1_CTL9             BITS(6,7)                 /*!< pin 9 configuration bits */
+#define GPIO_CTL1_MD10             BITS(8,9)                 /*!< port 10 mode bits */
+#define GPIO_CTL1_CTL10            BITS(10,11)               /*!< pin 10 configuration bits */
+#define GPIO_CTL1_MD11             BITS(12,13)               /*!< port 11 mode bits */
+#define GPIO_CTL1_CTL11            BITS(14,15)               /*!< pin 11 configuration bits */
+#define GPIO_CTL1_MD12             BITS(16,17)               /*!< port 12 mode bits */
+#define GPIO_CTL1_CTL12            BITS(18,19)               /*!< pin 12 configuration bits */
+#define GPIO_CTL1_MD13             BITS(20,21)               /*!< port 13 mode bits */
+#define GPIO_CTL1_CTL13            BITS(22,23)               /*!< pin 13 configuration bits */
+#define GPIO_CTL1_MD14             BITS(24,25)               /*!< port 14 mode bits */
+#define GPIO_CTL1_CTL14            BITS(26,27)               /*!< pin 14 configuration bits */
+#define GPIO_CTL1_MD15             BITS(28,29)               /*!< port 15 mode bits */
+#define GPIO_CTL1_CTL15            BITS(30,31)               /*!< pin 15 configuration bits */
+
+/* GPIO_ISTAT */
+#define GPIO_ISTAT_ISTAT0          BIT(0)                    /*!< pin 0 input status */
+#define GPIO_ISTAT_ISTAT1          BIT(1)                    /*!< pin 1 input status */
+#define GPIO_ISTAT_ISTAT2          BIT(2)                    /*!< pin 2 input status */
+#define GPIO_ISTAT_ISTAT3          BIT(3)                    /*!< pin 3 input status */
+#define GPIO_ISTAT_ISTAT4          BIT(4)                    /*!< pin 4 input status */
+#define GPIO_ISTAT_ISTAT5          BIT(5)                    /*!< pin 5 input status */
+#define GPIO_ISTAT_ISTAT6          BIT(6)                    /*!< pin 6 input status */
+#define GPIO_ISTAT_ISTAT7          BIT(7)                    /*!< pin 7 input status */
+#define GPIO_ISTAT_ISTAT8          BIT(8)                    /*!< pin 8 input status */
+#define GPIO_ISTAT_ISTAT9          BIT(9)                    /*!< pin 9 input status */
+#define GPIO_ISTAT_ISTAT10         BIT(10)                   /*!< pin 10 input status */
+#define GPIO_ISTAT_ISTAT11         BIT(11)                   /*!< pin 11 input status */
+#define GPIO_ISTAT_ISTAT12         BIT(12)                   /*!< pin 12 input status */
+#define GPIO_ISTAT_ISTAT13         BIT(13)                   /*!< pin 13 input status */
+#define GPIO_ISTAT_ISTAT14         BIT(14)                   /*!< pin 14 input status */
+#define GPIO_ISTAT_ISTAT15         BIT(15)                   /*!< pin 15 input status */
+
+/* GPIO_OCTL */
+#define GPIO_OCTL_OCTL0            BIT(0)                    /*!< pin 0 output bit */
+#define GPIO_OCTL_OCTL1            BIT(1)                    /*!< pin 1 output bit */
+#define GPIO_OCTL_OCTL2            BIT(2)                    /*!< pin 2 output bit */
+#define GPIO_OCTL_OCTL3            BIT(3)                    /*!< pin 3 output bit */
+#define GPIO_OCTL_OCTL4            BIT(4)                    /*!< pin 4 output bit */
+#define GPIO_OCTL_OCTL5            BIT(5)                    /*!< pin 5 output bit */
+#define GPIO_OCTL_OCTL6            BIT(6)                    /*!< pin 6 output bit */
+#define GPIO_OCTL_OCTL7            BIT(7)                    /*!< pin 7 output bit */
+#define GPIO_OCTL_OCTL8            BIT(8)                    /*!< pin 8 output bit */
+#define GPIO_OCTL_OCTL9            BIT(9)                    /*!< pin 9 output bit */
+#define GPIO_OCTL_OCTL10           BIT(10)                   /*!< pin 10 output bit */
+#define GPIO_OCTL_OCTL11           BIT(11)                   /*!< pin 11 output bit */
+#define GPIO_OCTL_OCTL12           BIT(12)                   /*!< pin 12 output bit */
+#define GPIO_OCTL_OCTL13           BIT(13)                   /*!< pin 13 output bit */
+#define GPIO_OCTL_OCTL14           BIT(14)                   /*!< pin 14 output bit */
+#define GPIO_OCTL_OCTL15           BIT(15)                   /*!< pin 15 output bit */
+
+/* GPIO_BOP */
+#define GPIO_BOP_BOP0              BIT(0)                    /*!< pin 0 set bit */
+#define GPIO_BOP_BOP1              BIT(1)                    /*!< pin 1 set bit */
+#define GPIO_BOP_BOP2              BIT(2)                    /*!< pin 2 set bit */
+#define GPIO_BOP_BOP3              BIT(3)                    /*!< pin 3 set bit */
+#define GPIO_BOP_BOP4              BIT(4)                    /*!< pin 4 set bit */
+#define GPIO_BOP_BOP5              BIT(5)                    /*!< pin 5 set bit */
+#define GPIO_BOP_BOP6              BIT(6)                    /*!< pin 6 set bit */
+#define GPIO_BOP_BOP7              BIT(7)                    /*!< pin 7 set bit */
+#define GPIO_BOP_BOP8              BIT(8)                    /*!< pin 8 set bit */
+#define GPIO_BOP_BOP9              BIT(9)                    /*!< pin 9 set bit */
+#define GPIO_BOP_BOP10             BIT(10)                   /*!< pin 10 set bit */
+#define GPIO_BOP_BOP11             BIT(11)                   /*!< pin 11 set bit */
+#define GPIO_BOP_BOP12             BIT(12)                   /*!< pin 12 set bit */
+#define GPIO_BOP_BOP13             BIT(13)                   /*!< pin 13 set bit */
+#define GPIO_BOP_BOP14             BIT(14)                   /*!< pin 14 set bit */
+#define GPIO_BOP_BOP15             BIT(15)                   /*!< pin 15 set bit */
+#define GPIO_BOP_CR0               BIT(16)                   /*!< pin 0 clear bit */
+#define GPIO_BOP_CR1               BIT(17)                   /*!< pin 1 clear bit */
+#define GPIO_BOP_CR2               BIT(18)                   /*!< pin 2 clear bit */
+#define GPIO_BOP_CR3               BIT(19)                   /*!< pin 3 clear bit */
+#define GPIO_BOP_CR4               BIT(20)                   /*!< pin 4 clear bit */
+#define GPIO_BOP_CR5               BIT(21)                   /*!< pin 5 clear bit */
+#define GPIO_BOP_CR6               BIT(22)                   /*!< pin 6 clear bit */
+#define GPIO_BOP_CR7               BIT(23)                   /*!< pin 7 clear bit */
+#define GPIO_BOP_CR8               BIT(24)                   /*!< pin 8 clear bit */
+#define GPIO_BOP_CR9               BIT(25)                   /*!< pin 9 clear bit */
+#define GPIO_BOP_CR10              BIT(26)                   /*!< pin 10 clear bit */
+#define GPIO_BOP_CR11              BIT(27)                   /*!< pin 11 clear bit */
+#define GPIO_BOP_CR12              BIT(28)                   /*!< pin 12 clear bit */
+#define GPIO_BOP_CR13              BIT(29)                   /*!< pin 13 clear bit */
+#define GPIO_BOP_CR14              BIT(30)                   /*!< pin 14 clear bit */
+#define GPIO_BOP_CR15              BIT(31)                   /*!< pin 15 clear bit */
+
+/* GPIO_BC */
+#define GPIO_BC_CR0                BIT(0)                    /*!< pin 0 clear bit */
+#define GPIO_BC_CR1                BIT(1)                    /*!< pin 1 clear bit */
+#define GPIO_BC_CR2                BIT(2)                    /*!< pin 2 clear bit */
+#define GPIO_BC_CR3                BIT(3)                    /*!< pin 3 clear bit */
+#define GPIO_BC_CR4                BIT(4)                    /*!< pin 4 clear bit */
+#define GPIO_BC_CR5                BIT(5)                    /*!< pin 5 clear bit */
+#define GPIO_BC_CR6                BIT(6)                    /*!< pin 6 clear bit */
+#define GPIO_BC_CR7                BIT(7)                    /*!< pin 7 clear bit */
+#define GPIO_BC_CR8                BIT(8)                    /*!< pin 8 clear bit */
+#define GPIO_BC_CR9                BIT(9)                    /*!< pin 9 clear bit */
+#define GPIO_BC_CR10               BIT(10)                   /*!< pin 10 clear bit */
+#define GPIO_BC_CR11               BIT(11)                   /*!< pin 11 clear bit */
+#define GPIO_BC_CR12               BIT(12)                   /*!< pin 12 clear bit */
+#define GPIO_BC_CR13               BIT(13)                   /*!< pin 13 clear bit */
+#define GPIO_BC_CR14               BIT(14)                   /*!< pin 14 clear bit */
+#define GPIO_BC_CR15               BIT(15)                   /*!< pin 15 clear bit */
+
+/* GPIO_LOCK */
+#define GPIO_LOCK_LK0              BIT(0)                    /*!< pin 0 lock bit */
+#define GPIO_LOCK_LK1              BIT(1)                    /*!< pin 1 lock bit */
+#define GPIO_LOCK_LK2              BIT(2)                    /*!< pin 2 lock bit */
+#define GPIO_LOCK_LK3              BIT(3)                    /*!< pin 3 lock bit */
+#define GPIO_LOCK_LK4              BIT(4)                    /*!< pin 4 lock bit */
+#define GPIO_LOCK_LK5              BIT(5)                    /*!< pin 5 lock bit */
+#define GPIO_LOCK_LK6              BIT(6)                    /*!< pin 6 lock bit */
+#define GPIO_LOCK_LK7              BIT(7)                    /*!< pin 7 lock bit */
+#define GPIO_LOCK_LK8              BIT(8)                    /*!< pin 8 lock bit */
+#define GPIO_LOCK_LK9              BIT(9)                    /*!< pin 9 lock bit */
+#define GPIO_LOCK_LK10             BIT(10)                   /*!< pin 10 lock bit */
+#define GPIO_LOCK_LK11             BIT(11)                   /*!< pin 11 lock bit */
+#define GPIO_LOCK_LK12             BIT(12)                   /*!< pin 12 lock bit */
+#define GPIO_LOCK_LK13             BIT(13)                   /*!< pin 13 lock bit */
+#define GPIO_LOCK_LK14             BIT(14)                   /*!< pin 14 lock bit */
+#define GPIO_LOCK_LK15             BIT(15)                   /*!< pin 15 lock bit */
+#define GPIO_LOCK_LKK              BIT(16)                   /*!< pin sequence lock key */
+
+/* AFIO_EC */
+#define AFIO_EC_PIN                BITS(0,3)                 /*!< event output pin selection */
+#define AFIO_EC_PORT               BITS(4,6)                 /*!< event output port selection */
+#define AFIO_EC_EOE                BIT(7)                    /*!< event output enable */
+
+/* AFIO_PCF0 */
+#ifdef GD32F10X_CL
+/* memory map and bit definitions for GD32F10X_CL devices */
+#define AFIO_PCF0_SPI0_REMAP             BIT(0)              /*!< SPI0 remapping */
+#define AFIO_PCF0_I2C0_REMAP             BIT(1)              /*!< I2C0 remapping */
+#define AFIO_PCF0_USART0_REMAP           BIT(2)              /*!< USART0 remapping */
+#define AFIO_PCF0_USART1_REMAP           BIT(3)              /*!< USART1 remapping */
+#define AFIO_PCF0_USART2_REMAP           BITS(4,5)           /*!< USART2 remapping */
+#define AFIO_PCF0_TIMER0_REMAP           BITS(6,7)           /*!< TIMER0 remapping */
+#define AFIO_PCF0_TIMER1_REMAP           BITS(8,9)           /*!< TIMER1 remapping */
+#define AFIO_PCF0_TIMER2_REMAP           BITS(10,11)         /*!< TIMER2 remapping */
+#define AFIO_PCF0_TIMER3_REMAP           BIT(12)             /*!< TIMER3 remapping */
+#define AFIO_PCF0_CAN0_REMAP             BITS(13,14)         /*!< CAN0 remapping */
+#define AFIO_PCF0_PD01_REMAP             BIT(15)             /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */
+#define AFIO_PCF0_TIMER4CH3_IREMAP       BIT(16)             /*!< TIMER3 channel3 internal remapping */
+#define AFIO_PCF0_ENET_REMAP             BIT(21)             /*!< ethernet MAC I/O remapping */
+#define AFIO_PCF0_CAN1_REMAP             BIT(22)             /*!< CAN1 remapping */
+#define AFIO_PCF0_ENET_PHY_SEL           BIT(23)             /*!< ethernet MII or RMII PHY selection */
+#define AFIO_PCF0_SWJ_CFG                BITS(24,26)         /*!< serial wire JTAG configuration */
+#define AFIO_PCF0_SPI2_REMAP             BIT(28)             /*!< SPI2/I2S2 remapping */
+#define AFIO_PCF0_TIMER1ITI1_REMAP       BIT(29)             /*!< TIMER1 internal trigger 1 remapping */
+#define AFIO_PCF0_PTP_PPS_REMAP          BIT(30)             /*!< ethernet PTP PPS remapping */
+
+#else 
+/* memory map and bit definitions for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices */
+#define AFIO_PCF0_SPI0_REMAP             BIT(0)              /*!< SPI0 remapping */
+#define AFIO_PCF0_I2C0_REMAP             BIT(1)              /*!< I2C0 remapping */
+#define AFIO_PCF0_USART0_REMAP           BIT(2)              /*!< USART0 remapping */
+#define AFIO_PCF0_USART1_REMAP           BIT(3)              /*!< USART1 remapping */
+#define AFIO_PCF0_USART2_REMAP           BITS(4,5)           /*!< USART2 remapping */
+#define AFIO_PCF0_TIMER0_REMAP           BITS(6,7)           /*!< TIMER0 remapping */
+#define AFIO_PCF0_TIMER1_REMAP           BITS(8,9)           /*!< TIMER1 remapping */
+#define AFIO_PCF0_TIMER2_REMAP           BITS(10,11)         /*!< TIMER2 remapping */
+#define AFIO_PCF0_TIMER3_REMAP           BIT(12)             /*!< TIMER3 remapping */
+#define AFIO_PCF0_CAN_REMAP              BITS(13,14)         /*!< CAN remapping */
+#define AFIO_PCF0_PD01_REMAP             BIT(15)             /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */
+#define AFIO_PCF0_TIMER4CH3_REMAP        BIT(16)             /*!< TIMER4 channel3 internal remapping */
+#define AFIO_PCF0_ADC0_ETRGINS_REMAP     BIT(17)             /*!< ADC 0 external trigger inserted conversion remapping */
+#define AFIO_PCF0_ADC0_ETRGREG_REMAP     BIT(18)             /*!< ADC 0 external trigger regular conversion remapping */
+#define AFIO_PCF0_ADC1_ETRGINS_REMAP     BIT(19)             /*!< ADC 1 external trigger inserted conversion remapping */
+#define AFIO_PCF0_ADC1_ETRGREG_REMAP     BIT(20)             /*!< ADC 1 external trigger regular conversion remapping */
+#define AFIO_PCF0_SWJ_CFG                BITS(24,26)         /*!< serial wire JTAG configuration */
+#endif /* GD32F10X_CL */
+
+/* AFIO_EXTISS0 */
+#define AFIO_EXTI0_SS                    BITS(0,3)           /*!< EXTI 0 sources selection */
+#define AFIO_EXTI1_SS                    BITS(4,7)           /*!< EXTI 1 sources selection */
+#define AFIO_EXTI2_SS                    BITS(8,11)          /*!< EXTI 2 sources selection */
+#define AFIO_EXTI3_SS                    BITS(12,15)         /*!< EXTI 3 sources selection */
+
+/* AFIO_EXTISS1 */
+#define AFIO_EXTI4_SS                    BITS(0,3)           /*!< EXTI 4 sources selection */
+#define AFIO_EXTI5_SS                    BITS(4,7)           /*!< EXTI 5 sources selection */
+#define AFIO_EXTI6_SS                    BITS(8,11)          /*!< EXTI 6 sources selection */
+#define AFIO_EXTI7_SS                    BITS(12,15)         /*!< EXTI 7 sources selection */
+
+/* AFIO_EXTISS2 */
+#define AFIO_EXTI8_SS                    BITS(0,3)           /*!< EXTI 8 sources selection */
+#define AFIO_EXTI9_SS                    BITS(4,7)           /*!< EXTI 9 sources selection */
+#define AFIO_EXTI10_SS                   BITS(8,11)          /*!< EXTI 10 sources selection */
+#define AFIO_EXTI11_SS                   BITS(12,15)         /*!< EXTI 11 sources selection */
+
+/* AFIO_EXTISS3 */
+#define AFIO_EXTI12_SS                   BITS(0,3)           /*!< EXTI 12 sources selection */
+#define AFIO_EXTI13_SS                   BITS(4,7)           /*!< EXTI 13 sources selection */
+#define AFIO_EXTI14_SS                   BITS(8,11)          /*!< EXTI 14 sources selection */
+#define AFIO_EXTI15_SS                   BITS(12,15)         /*!< EXTI 15 sources selection */
+
+/* AFIO_PCF1 */
+#define AFIO_PCF1_TIMER8_REMAP           BIT(5)             /*!< TIMER8 remapping */
+#define AFIO_PCF1_TIMER9_REMAP           BIT(6)             /*!< TIMER9 remapping */
+#define AFIO_PCF1_TIMER10_REMAP          BIT(7)             /*!< TIMER10 remapping */
+#define AFIO_PCF1_TIMER12_REMAP          BIT(8)             /*!< TIMER12 remapping */
+#define AFIO_PCF1_TIMER13_REMAP          BIT(9)             /*!< TIMER13 remapping */
+#define AFIO_PCF1_EXMC_NADV              BIT(10)            /*!< EXMC_NADV connect/disconnect */
+
+/* constants definitions */
+typedef FlagStatus bit_status;
+
+/* GPIO mode values set */
+#define GPIO_MODE_SET(n, mode)           ((uint32_t)((uint32_t)(mode) << (4U * (n))))
+#define GPIO_MODE_MASK(n)                (0xFU << (4U * (n)))
+
+/* GPIO mode definitions */
+#define GPIO_MODE_AIN                    ((uint8_t)0x00U)          /*!< analog input mode */
+#define GPIO_MODE_IN_FLOATING            ((uint8_t)0x04U)          /*!< floating input mode */
+#define GPIO_MODE_IPD                    ((uint8_t)0x28U)          /*!< pull-down input mode */
+#define GPIO_MODE_IPU                    ((uint8_t)0x48U)          /*!< pull-up input mode */
+#define GPIO_MODE_OUT_OD                 ((uint8_t)0x14U)          /*!< GPIO output with open-drain */
+#define GPIO_MODE_OUT_PP                 ((uint8_t)0x10U)          /*!< GPIO output with push-pull */
+#define GPIO_MODE_AF_OD                  ((uint8_t)0x1CU)          /*!< AFIO output with open-drain */
+#define GPIO_MODE_AF_PP                  ((uint8_t)0x18U)          /*!< AFIO output with push-pull */
+
+/* GPIO output max speed value */
+#define GPIO_OSPEED_10MHZ                ((uint8_t)0x01U)          /*!< output max speed 10MHz */
+#define GPIO_OSPEED_2MHZ                 ((uint8_t)0x02U)          /*!< output max speed 2MHz */
+#define GPIO_OSPEED_50MHZ                ((uint8_t)0x03U)          /*!< output max speed 50MHz */
+
+/* GPIO event output port definitions */
+#define GPIO_EVENT_PORT_GPIOA            ((uint8_t)0x00U)          /*!< event output port A */
+#define GPIO_EVENT_PORT_GPIOB            ((uint8_t)0x01U)          /*!< event output port B */
+#define GPIO_EVENT_PORT_GPIOC            ((uint8_t)0x02U)          /*!< event output port C */
+#define GPIO_EVENT_PORT_GPIOD            ((uint8_t)0x03U)          /*!< event output port D */
+#define GPIO_EVENT_PORT_GPIOE            ((uint8_t)0x04U)          /*!< event output port E */
+
+/* GPIO output port source definitions */
+#define GPIO_PORT_SOURCE_GPIOA           ((uint8_t)0x00U)          /*!< output port source A */
+#define GPIO_PORT_SOURCE_GPIOB           ((uint8_t)0x01U)          /*!< output port source B */
+#define GPIO_PORT_SOURCE_GPIOC           ((uint8_t)0x02U)          /*!< output port source C */
+#define GPIO_PORT_SOURCE_GPIOD           ((uint8_t)0x03U)          /*!< output port source D */
+#define GPIO_PORT_SOURCE_GPIOE           ((uint8_t)0x04U)          /*!< output port source E */
+#define GPIO_PORT_SOURCE_GPIOF           ((uint8_t)0x05U)          /*!< output port source F */
+#define GPIO_PORT_SOURCE_GPIOG           ((uint8_t)0x06U)          /*!< output port source G */
+
+/* GPIO event output pin definitions */
+#define GPIO_EVENT_PIN_0                 ((uint8_t)0x00U)          /*!< GPIO event pin 0 */
+#define GPIO_EVENT_PIN_1                 ((uint8_t)0x01U)          /*!< GPIO event pin 1 */
+#define GPIO_EVENT_PIN_2                 ((uint8_t)0x02U)          /*!< GPIO event pin 2 */
+#define GPIO_EVENT_PIN_3                 ((uint8_t)0x03U)          /*!< GPIO event pin 3 */
+#define GPIO_EVENT_PIN_4                 ((uint8_t)0x04U)          /*!< GPIO event pin 4 */
+#define GPIO_EVENT_PIN_5                 ((uint8_t)0x05U)          /*!< GPIO event pin 5 */
+#define GPIO_EVENT_PIN_6                 ((uint8_t)0x06U)          /*!< GPIO event pin 6 */
+#define GPIO_EVENT_PIN_7                 ((uint8_t)0x07U)          /*!< GPIO event pin 7 */
+#define GPIO_EVENT_PIN_8                 ((uint8_t)0x08U)          /*!< GPIO event pin 8 */
+#define GPIO_EVENT_PIN_9                 ((uint8_t)0x09U)          /*!< GPIO event pin 9 */
+#define GPIO_EVENT_PIN_10                ((uint8_t)0x0AU)          /*!< GPIO event pin 10 */
+#define GPIO_EVENT_PIN_11                ((uint8_t)0x0BU)          /*!< GPIO event pin 11 */
+#define GPIO_EVENT_PIN_12                ((uint8_t)0x0CU)          /*!< GPIO event pin 12 */
+#define GPIO_EVENT_PIN_13                ((uint8_t)0x0DU)          /*!< GPIO event pin 13 */
+#define GPIO_EVENT_PIN_14                ((uint8_t)0x0EU)          /*!< GPIO event pin 14 */
+#define GPIO_EVENT_PIN_15                ((uint8_t)0x0FU)          /*!< GPIO event pin 15 */
+
+/* GPIO output pin source definitions */
+#define GPIO_PIN_SOURCE_0                ((uint8_t)0x00U)          /*!< GPIO pin source 0 */
+#define GPIO_PIN_SOURCE_1                ((uint8_t)0x01U)          /*!< GPIO pin source 1 */
+#define GPIO_PIN_SOURCE_2                ((uint8_t)0x02U)          /*!< GPIO pin source 2 */
+#define GPIO_PIN_SOURCE_3                ((uint8_t)0x03U)          /*!< GPIO pin source 3 */
+#define GPIO_PIN_SOURCE_4                ((uint8_t)0x04U)          /*!< GPIO pin source 4 */
+#define GPIO_PIN_SOURCE_5                ((uint8_t)0x05U)          /*!< GPIO pin source 5 */
+#define GPIO_PIN_SOURCE_6                ((uint8_t)0x06U)          /*!< GPIO pin source 6 */
+#define GPIO_PIN_SOURCE_7                ((uint8_t)0x07U)          /*!< GPIO pin source 7 */
+#define GPIO_PIN_SOURCE_8                ((uint8_t)0x08U)          /*!< GPIO pin source 8 */
+#define GPIO_PIN_SOURCE_9                ((uint8_t)0x09U)          /*!< GPIO pin source 9 */
+#define GPIO_PIN_SOURCE_10               ((uint8_t)0x0AU)          /*!< GPIO pin source 10 */
+#define GPIO_PIN_SOURCE_11               ((uint8_t)0x0BU)          /*!< GPIO pin source 11 */
+#define GPIO_PIN_SOURCE_12               ((uint8_t)0x0CU)          /*!< GPIO pin source 12 */
+#define GPIO_PIN_SOURCE_13               ((uint8_t)0x0DU)          /*!< GPIO pin source 13 */
+#define GPIO_PIN_SOURCE_14               ((uint8_t)0x0EU)          /*!< GPIO pin source 14 */
+#define GPIO_PIN_SOURCE_15               ((uint8_t)0x0FU)          /*!< GPIO pin source 15 */
+
+/* GPIO pin definitions */
+#define GPIO_PIN_0                       BIT(0)                    /*!< GPIO pin 0 */
+#define GPIO_PIN_1                       BIT(1)                    /*!< GPIO pin 1 */
+#define GPIO_PIN_2                       BIT(2)                    /*!< GPIO pin 2 */
+#define GPIO_PIN_3                       BIT(3)                    /*!< GPIO pin 3 */
+#define GPIO_PIN_4                       BIT(4)                    /*!< GPIO pin 4 */
+#define GPIO_PIN_5                       BIT(5)                    /*!< GPIO pin 5 */
+#define GPIO_PIN_6                       BIT(6)                    /*!< GPIO pin 6 */
+#define GPIO_PIN_7                       BIT(7)                    /*!< GPIO pin 7 */
+#define GPIO_PIN_8                       BIT(8)                    /*!< GPIO pin 8 */
+#define GPIO_PIN_9                       BIT(9)                    /*!< GPIO pin 9 */
+#define GPIO_PIN_10                      BIT(10)                   /*!< GPIO pin 10 */
+#define GPIO_PIN_11                      BIT(11)                   /*!< GPIO pin 11 */
+#define GPIO_PIN_12                      BIT(12)                   /*!< GPIO pin 12 */
+#define GPIO_PIN_13                      BIT(13)                   /*!< GPIO pin 13 */
+#define GPIO_PIN_14                      BIT(14)                   /*!< GPIO pin 14 */
+#define GPIO_PIN_15                      BIT(15)                   /*!< GPIO pin 15 */
+#define GPIO_PIN_ALL                     BITS(0,15)                /*!< GPIO pin all */
+
+/* GPIO remap definitions */
+#define GPIO_SPI0_REMAP                  ((uint32_t)0x00000001U)   /*!< SPI0 remapping */
+#define GPIO_I2C0_REMAP                  ((uint32_t)0x00000002U)   /*!< I2C0 remapping */
+#define GPIO_USART0_REMAP                ((uint32_t)0x00000004U)   /*!< USART0 remapping */
+#define GPIO_USART1_REMAP                ((uint32_t)0x00000008U)   /*!< USART1 remapping */
+#define GPIO_USART2_PARTIAL_REMAP        ((uint32_t)0x00140010U)   /*!< USART2 partial remapping */
+#define GPIO_USART2_FULL_REMAP           ((uint32_t)0x00140030U)   /*!< USART2 full remapping */
+#define GPIO_TIMER0_PARTIAL_REMAP        ((uint32_t)0x00160040U)   /*!< TIMER0 partial remapping */
+#define GPIO_TIMER0_FULL_REMAP           ((uint32_t)0x001600C0U)   /*!< TIMER0 full remapping */
+#define GPIO_TIMER1_PARTIAL_REMAP0       ((uint32_t)0x00180100U)   /*!< TIMER1 partial remapping */
+#define GPIO_TIMER1_PARTIAL_REMAP1       ((uint32_t)0x00180200U)   /*!< TIMER1 partial remapping */
+#define GPIO_TIMER1_FULL_REMAP           ((uint32_t)0x00180300U)   /*!< TIMER1 full remapping */
+#define GPIO_TIMER2_PARTIAL_REMAP        ((uint32_t)0x001A0800U)   /*!< TIMER2 partial remapping */
+#define GPIO_TIMER2_FULL_REMAP           ((uint32_t)0x001A0C00U)   /*!< TIMER2 full remapping */
+#define GPIO_TIMER3_REMAP                ((uint32_t)0x00001000U)   /*!< TIMER3 remapping */
+#define GPIO_PD01_REMAP                  ((uint32_t)0x00008000U)   /*!< PD01 remapping */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define GPIO_CAN_PARTIAL_REMAP           ((uint32_t)0x001D4000U)   /*!< CAN partial remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#define GPIO_CAN_FULL_REMAP              ((uint32_t)0x001D6000U)   /*!< CAN full remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */
+#if (defined(GD32F10X_CL) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define GPIO_SPI2_REMAP                  ((uint32_t)0x00201100U)   /*!< SPI2 remapping(only for GD32F10X_CL devices) */
+#endif /* GD32F10X_CL||GD32F10X_HD */
+#if (defined(GD32F10X_CL) || defined(GD32F10X_HD))
+#define GPIO_TIMER4CH3_IREMAP            ((uint32_t)0x00200001U)   /*!< TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices) */
+#endif /* GD32F10X_CL||GD32F10X_HD */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define GPIO_ADC0_ETRGINS_REMAP          ((uint32_t)0x00200002U)   /*!< ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#define GPIO_ADC0_ETRGREG_REMAP          ((uint32_t)0x00200004U)   /*!< ADC0 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#define GPIO_ADC1_ETRGINS_REMAP          ((uint32_t)0x00200008U)   /*!< ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#define GPIO_ADC1_ETRGREG_REMAP          ((uint32_t)0x00200010U)   /*!< ADC1 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */
+#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */
+#define GPIO_SWJ_NONJTRST_REMAP          ((uint32_t)0x00300100U)   /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */
+#define GPIO_SWJ_SWDPENABLE_REMAP        ((uint32_t)0x00300200U)   /*!< JTAG-DP disabled and SW-DP enabled */
+#define GPIO_SWJ_DISABLE_REMAP           ((uint32_t)0x00300400U)   /*!< JTAG-DP disabled and SW-DP disabled */
+#ifdef GD32F10X_CL
+#define GPIO_CAN0_PARTIAL_REMAP          ((uint32_t)0x001D4000U)   /*!< CAN0 partial remapping(only for GD32F10X_CL devices) */
+#define GPIO_CAN0_FULL_REMAP             ((uint32_t)0x001D6000U)   /*!< CAN0 full remapping(only for GD32F10X_CL devices) */
+#define GPIO_ENET_REMAP                  ((uint32_t)0x00200020U)   /*!< ENET remapping(only for GD32F10X_CL devices) */
+#define GPIO_CAN1_REMAP                  ((uint32_t)0x00200040U)   /*!< CAN1 remapping(only for GD32F10X_CL devices) */
+#define GPIO_TIMER1ITI1_REMAP            ((uint32_t)0x00202000U)   /*!< TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) */
+#define GPIO_PTP_PPS_REMAP               ((uint32_t)0x00204000U)   /*!< ethernet PTP PPS remapping(only for GD32F10X_CL devices) */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+#define GPIO_TIMER8_REMAP                ((uint32_t)0x80000020U)   /*!< TIMER8 remapping */
+#define GPIO_TIMER9_REMAP                ((uint32_t)0x80000040U)   /*!< TIMER9 remapping */
+#define GPIO_TIMER10_REMAP               ((uint32_t)0x80000080U)   /*!< TIMER10 remapping */
+#define GPIO_TIMER12_REMAP               ((uint32_t)0x80000100U)   /*!< TIMER12 remapping */
+#define GPIO_TIMER13_REMAP               ((uint32_t)0x80000200U)   /*!< TIMER13 remapping */
+#define GPIO_EXMC_NADV_REMAP             ((uint32_t)0x80000400U)   /*!< EXMC_NADV connect/disconnect */
+#endif /* GD32F10X_XD */
+
+#ifdef GD32F10X_CL
+/* ethernet MII or RMII PHY selection */
+#define GPIO_ENET_PHY_MII                ((uint32_t)0x00000000U)   /*!< configure ethernet MAC for connection with an MII PHY */
+#define GPIO_ENET_PHY_RMII               AFIO_PCF0_ENET_PHY_SEL    /*!< configure ethernet MAC for connection with an RMII PHY */
+#endif /* GD32F10X_CL */
+
+/* function declarations */
+/* reset GPIO port */
+void gpio_deinit(uint32_t gpio_periph);
+/* reset alternate function I/O(AFIO) */
+void gpio_afio_deinit(void);
+/* GPIO parameter initialization */
+void gpio_init(uint32_t gpio_periph,uint32_t mode,uint32_t speed,uint32_t pin);
+
+/* set GPIO pin bit */
+void gpio_bit_set(uint32_t gpio_periph, uint32_t pin);
+/* reset GPIO pin bit */
+void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin);
+/* write data to the specified GPIO pin */
+void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value);
+/* write data to the specified GPIO port */
+void gpio_port_write(uint32_t gpio_periph, uint16_t data);
+
+/* get GPIO pin input status */
+FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin);
+/* get GPIO port input status */
+uint16_t gpio_input_port_get(uint32_t gpio_periph);
+/* get GPIO pin output status */
+FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin);
+/* get GPIO port output status */
+uint16_t gpio_output_port_get(uint32_t gpio_periph);
+
+/* configure GPIO pin remap */
+void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue);
+
+/* select GPIO pin exti sources */
+void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin);
+/* configure GPIO pin event output */
+void gpio_event_output_config(uint8_t output_port, uint8_t output_pin);
+/* enable GPIO pin event output */
+void gpio_event_output_enable(void);
+/* disable GPIO pin event output */
+void gpio_event_output_disable(void);
+
+/* lock GPIO pin bit */
+void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin);
+
+#ifdef GD32F10X_CL
+/* select ethernet MII or RMII PHY */
+void gpio_ethernet_phy_select(uint32_t gpio_enetsel);
+#endif /* GD32F10X_CL */
+
+
+#endif /* GD32F10x_GPIO_H */

+ 347 - 0
Library/Include/gd32f10x_i2c.h

@@ -0,0 +1,347 @@
+/*!
+    \file    gd32f10x_i2c.h
+    \brief   definitions for the I2C
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-04-16, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_I2C_H
+#define GD32F10X_I2C_H
+
+#include "gd32f10x.h"
+
+/* I2Cx(x=0,1) definitions */
+#define I2C0                          I2C_BASE                   /*!< I2C0 base address */
+#define I2C1                          (I2C_BASE + 0x00000400U)   /*!< I2C1 base address */
+
+/* registers definitions */
+#define I2C_CTL0(i2cx)                REG32((i2cx) + 0x00U)      /*!< I2C control register 0 */
+#define I2C_CTL1(i2cx)                REG32((i2cx) + 0x04U)      /*!< I2C control register 1 */
+#define I2C_SADDR0(i2cx)              REG32((i2cx) + 0x08U)      /*!< I2C slave address register 0*/
+#define I2C_SADDR1(i2cx)              REG32((i2cx) + 0x0CU)      /*!< I2C slave address register */
+#define I2C_DATA(i2cx)                REG32((i2cx) + 0x10U)      /*!< I2C transfer buffer register */
+#define I2C_STAT0(i2cx)               REG32((i2cx) + 0x14U)      /*!< I2C transfer status register 0 */
+#define I2C_STAT1(i2cx)               REG32((i2cx) + 0x18U)      /*!< I2C transfer status register */
+#define I2C_CKCFG(i2cx)               REG32((i2cx) + 0x1CU)      /*!< I2C clock configure register */
+#define I2C_RT(i2cx)                  REG32((i2cx) + 0x20U)      /*!< I2C rise time register */
+
+/* bits definitions */
+/* I2Cx_CTL0 */
+#define I2C_CTL0_I2CEN                BIT(0)        /*!< peripheral enable */
+#define I2C_CTL0_SMBEN                BIT(1)        /*!< SMBus mode */
+#define I2C_CTL0_SMBSEL               BIT(3)        /*!< SMBus type */
+#define I2C_CTL0_ARPEN                BIT(4)        /*!< ARP enable */
+#define I2C_CTL0_PECEN                BIT(5)        /*!< PEC enable */
+#define I2C_CTL0_GCEN                 BIT(6)        /*!< general call enable */
+#define I2C_CTL0_SS                   BIT(7)        /*!< clock stretching disable (slave mode) */
+#define I2C_CTL0_START                BIT(8)        /*!< start generation */
+#define I2C_CTL0_STOP                 BIT(9)        /*!< stop generation */
+#define I2C_CTL0_ACKEN                BIT(10)       /*!< acknowledge enable */
+#define I2C_CTL0_POAP                 BIT(11)       /*!< acknowledge/PEC position (for data reception) */
+#define I2C_CTL0_PECTRANS             BIT(12)       /*!< packet error checking */
+#define I2C_CTL0_SALT                 BIT(13)       /*!< SMBus alert */
+#define I2C_CTL0_SRESET               BIT(15)       /*!< software reset */
+
+/* I2Cx_CTL1 */
+#define I2C_CTL1_I2CCLK               BITS(0,5)     /*!< I2CCLK[5:0] bits (peripheral clock frequency) */
+#define I2C_CTL1_ERRIE                BIT(8)        /*!< error interrupt enable */
+#define I2C_CTL1_EVIE                 BIT(9)        /*!< event interrupt enable */
+#define I2C_CTL1_BUFIE                BIT(10)       /*!< buffer interrupt enable */
+#define I2C_CTL1_DMAON                BIT(11)       /*!< DMA requests enable */
+#define I2C_CTL1_DMALST               BIT(12)       /*!< DMA last transfer */
+
+/* I2Cx_SADDR0 */
+#define I2C_SADDR0_ADDRESS0           BIT(0)        /*!< bit 0 of a 10-bit address */
+#define I2C_SADDR0_ADDRESS            BITS(1,7)     /*!< 7-bit address or bits 7:1 of a 10-bit address */
+#define I2C_SADDR0_ADDRESS_H          BITS(8,9)     /*!< highest two bits of a 10-bit address */
+#define I2C_SADDR0_ADDFORMAT          BIT(15)       /*!< address mode for the I2C slave */
+
+/* I2Cx_SADDR1 */
+#define I2C_SADDR1_DUADEN             BIT(0)        /*!< aual-address mode switch */
+#define I2C_SADDR1_ADDRESS2           BITS(1,7)     /*!< second I2C address for the slave in dual-address mode */
+
+/* I2Cx_DATA */
+#define I2C_DATA_TRB                  BITS(0,7)     /*!< 8-bit data register */
+
+/* I2Cx_STAT0 */
+#define I2C_STAT0_SBSEND              BIT(0)        /*!< start bit (master mode) */
+#define I2C_STAT0_ADDSEND             BIT(1)        /*!< address sent (master mode)/matched (slave mode) */
+#define I2C_STAT0_BTC                 BIT(2)        /*!< byte transfer finished */
+#define I2C_STAT0_ADD10SEND           BIT(3)        /*!< 10-bit header sent (master mode) */
+#define I2C_STAT0_STPDET              BIT(4)        /*!< stop detection (slave mode) */
+#define I2C_STAT0_RBNE                BIT(6)        /*!< data register not empty (receivers) */
+#define I2C_STAT0_TBE                 BIT(7)        /*!< data register empty (transmitters) */
+#define I2C_STAT0_BERR                BIT(8)        /*!< bus error */
+#define I2C_STAT0_LOSTARB             BIT(9)        /*!< arbitration lost (master mode) */
+#define I2C_STAT0_AERR                BIT(10)       /*!< acknowledge failure */
+#define I2C_STAT0_OUERR               BIT(11)       /*!< overrun/underrun */
+#define I2C_STAT0_PECERR              BIT(12)       /*!< PEC error in reception */
+#define I2C_STAT0_SMBTO               BIT(14)       /*!< timeout signal in SMBus mode */
+#define I2C_STAT0_SMBALT              BIT(15)       /*!< SMBus alert status */
+
+/* I2Cx_STAT1 */
+#define I2C_STAT1_MASTER              BIT(0)        /*!< master/slave */
+#define I2C_STAT1_I2CBSY              BIT(1)        /*!< bus busy */
+#define I2C_STAT1_TR                  BIT(2)        /*!< transmitter/receiver */
+#define I2C_STAT1_RXGC                BIT(4)        /*!< general call address (slave mode) */
+#define I2C_STAT1_DEFSMB              BIT(5)        /*!< SMBus device default address (slave mode) */
+#define I2C_STAT1_HSTSMB              BIT(6)        /*!< SMBus host header (slave mode) */
+#define I2C_STAT1_DUMODF              BIT(7)        /*!< dual flag (slave mode) */
+#define I2C_STAT1_PECV                BITS(8,15)    /*!< packet error checking value */
+
+/* I2Cx_CKCFG */
+#define I2C_CKCFG_CLKC                BITS(0,11)    /*!< clock control register in fast/standard mode (master mode) */
+#define I2C_CKCFG_DTCY                BIT(14)       /*!< fast mode duty cycle */
+#define I2C_CKCFG_FAST                BIT(15)       /*!< I2C speed selection in master mode */
+
+/* I2Cx_RT */
+#define I2C_RT_RISETIME               BITS(0,5)     /*!< maximum rise time in fast/standard mode (Master mode) */
+
+/* constants definitions */
+/* define the I2C bit position and its register index offset */
+#define I2C_REGIDX_BIT(regidx, bitpos)  (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define I2C_REG_VAL(i2cx, offset)       (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6)))
+#define I2C_BIT_POS(val)                ((uint32_t)(val) & 0x1FU)
+#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2)   (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\
+                                                              | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)))
+#define I2C_REG_VAL2(i2cx, offset)      (REG32((i2cx) + ((uint32_t)(offset) >> 22)))
+#define I2C_BIT_POS2(val)               (((uint32_t)(val) & 0x1F0000U) >> 16)
+
+/* register offset */
+#define I2C_CTL1_REG_OFFSET           0x04U         /*!< CTL1 register offset */
+#define I2C_STAT0_REG_OFFSET          0x14U         /*!< STAT0 register offset */
+#define I2C_STAT1_REG_OFFSET          0x18U         /*!< STAT1 register offset */
+
+/* I2C flags */
+typedef enum
+{
+    /* flags in STAT0 register */
+    I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U),                /*!< start condition sent out in master mode */
+    I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U),               /*!< address is sent in master mode or received and matches in slave mode */
+    I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U),                   /*!< byte transmission finishes */
+    I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U),             /*!< header of 10-bit address is sent in master mode */
+    I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U),                /*!< stop condition detected in slave mode */
+    I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U),                  /*!< I2C_DATA is not Empty during receiving */
+    I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U),                   /*!< I2C_DATA is empty during transmitting */
+    I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U),                  /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */
+    I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U),               /*!< arbitration lost in master mode */
+    I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U),                 /*!< acknowledge error */
+    I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U),                /*!< over-run or under-run situation occurs in slave mode */
+    I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U),               /*!< PEC error when receiving data */
+    I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U),                /*!< timeout signal in SMBus mode */
+    I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U),               /*!< SMBus alert status */
+    /* flags in STAT1 register */
+    I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U),                /*!< a flag indicating whether I2C block is in master or slave mode */
+    I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U),                /*!< busy flag */
+    I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U),                   /*!< whether the I2C is a transmitter or a receiver */
+    I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U),                  /*!< general call address (00h) received */
+    I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U),                /*!< default address of SMBus device */
+    I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U),                /*!< SMBus host header detected in slave mode */
+    I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U),                 /*!< dual flag in slave mode indicating which address is matched in dual-address mode */
+}i2c_flag_enum;
+
+/* I2C interrupt flags */
+typedef enum
+{
+    /* interrupt flags in CTL1 register */
+    I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U),        /*!< start condition sent out in master mode interrupt flag */
+    I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U),       /*!< address is sent in master mode or received and matches in slave mode interrupt flag */
+    I2C_INT_FLAG_BTC =  I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U),          /*!< byte transmission finishes */
+    I2C_INT_FLAG_ADD10SEND =  I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U),    /*!< header of 10-bit address is sent in master mode interrupt flag */
+    I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U),        /*!< stop condition detected in slave mode interrupt flag */
+    I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U),          /*!< I2C_DATA is not Empty during receiving interrupt flag */
+    I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U),           /*!< I2C_DATA is empty during transmitting interrupt flag */    
+    I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U),          /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */
+    I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U),       /*!< arbitration lost in master mode interrupt flag */
+    I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U),         /*!< acknowledge error interrupt flag */
+    I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U),        /*!< over-run or under-run situation occurs in slave mode interrupt flag */
+    I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U),       /*!< PEC error when receiving data interrupt flag */
+    I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U),        /*!< timeout signal in SMBus mode interrupt flag */
+    I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U),       /*!< SMBus Alert status interrupt flag */
+}i2c_interrupt_flag_enum;
+
+/* I2C interrupt enable or disable */
+typedef enum
+{
+    /* interrupt in CTL1 register */
+    I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U),                     /*!< error interrupt enable */
+    I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U),                      /*!< event interrupt enable */
+    I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U),                    /*!< buffer interrupt enable */
+}i2c_interrupt_enum;
+
+/* SMBus/I2C mode switch and SMBus type selection */
+#define I2C_I2CMODE_ENABLE            ((uint32_t)0x00000000U)                  /*!< I2C mode */
+#define I2C_SMBUSMODE_ENABLE          I2C_CTL0_SMBEN                           /*!< SMBus mode */
+
+/* SMBus/I2C mode switch and SMBus type selection */
+#define I2C_SMBUS_DEVICE              ((uint32_t)0x00000000U)                  /*!< SMBus mode device type */
+#define I2C_SMBUS_HOST                I2C_CTL0_SMBSEL                          /*!< SMBus mode host type */
+
+/* I2C transfer direction */
+#define I2C_RECEIVER                  ((uint32_t)0x00000001U)                  /*!< receiver */
+#define I2C_TRANSMITTER               ((uint32_t)0xFFFFFFFEU)                  /*!< transmitter */
+
+/* whether or not to send an ACK */
+#define I2C_ACK_DISABLE               ((uint32_t)0x00000000U)                  /*!< ACK will be not sent */
+#define I2C_ACK_ENABLE                ((uint32_t)0x00000001U)                  /*!< ACK will be sent */
+
+/* I2C POAP position*/
+#define I2C_ACKPOS_NEXT               ((uint32_t)0x00000000U)                  /*!< ACKEN bit decides whether or not to send ACK for the next byte */
+#define I2C_ACKPOS_CURRENT            ((uint32_t)0x00000001U)                  /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */
+
+/* I2C dual-address mode switch */
+#define I2C_DUADEN_DISABLE            ((uint32_t)0x00000000U)                  /*!< dual-address mode disabled */
+#define I2C_DUADEN_ENABLE             ((uint32_t)0x00000001U)                  /*!< dual-address mode enabled */
+
+/* whether or not to stretch SCL low */
+#define I2C_SCLSTRETCH_ENABLE         ((uint32_t)0x00000000U)                  /*!< SCL stretching is enabled */
+#define I2C_SCLSTRETCH_DISABLE        I2C_CTL0_SS                              /*!< SCL stretching is disabled */
+
+/* whether or not to response to a general call */
+#define I2C_GCEN_ENABLE               I2C_CTL0_GCEN                            /*!< slave will response to a general call */
+#define I2C_GCEN_DISABLE              ((uint32_t)0x00000000U)                  /*!< slave will not response to a general call */
+
+/* software reset I2C */
+#define I2C_SRESET_SET                I2C_CTL0_SRESET                          /*!< I2C is under reset */
+#define I2C_SRESET_RESET              ((uint32_t)0x00000000U)                  /*!< I2C is not under reset */
+
+/* I2C DMA mode configure */
+/* DMA mode switch */
+#define I2C_DMA_ON                    I2C_CTL1_DMAON                           /*!< DMA mode enabled */
+#define I2C_DMA_OFF                   ((uint32_t)0x00000000U)                  /*!< DMA mode disabled */
+
+/* flag indicating DMA last transfer */
+#define I2C_DMALST_ON                 I2C_CTL1_DMALST                          /*!< next DMA EOT is the last transfer */
+#define I2C_DMALST_OFF                ((uint32_t)0x00000000U)                  /*!< next DMA EOT is not the last transfer */
+
+/* I2C PEC configure */
+/* PEC enable */
+#define I2C_PEC_ENABLE                I2C_CTL0_PECEN                           /*!< PEC calculation on */
+#define I2C_PEC_DISABLE               ((uint32_t)0x00000000U)                  /*!< PEC calculation off */
+
+/* PEC transfer */
+#define I2C_PECTRANS_ENABLE           I2C_CTL0_PECTRANS                        /*!< transfer PEC */
+#define I2C_PECTRANS_DISABLE          ((uint32_t)0x00000000U)                  /*!< not transfer PEC value */
+
+/* I2C SMBus configure */
+/* issue or not alert through SMBA pin */
+#define I2C_SALTSEND_ENABLE           I2C_CTL0_SALT                            /*!< issue alert through SMBA pin */
+#define I2C_SALTSEND_DISABLE          ((uint32_t)0x00000000U)                  /*!< not issue alert through SMBA */
+
+/* ARP protocol in SMBus switch */
+#define I2C_ARP_ENABLE                I2C_CTL0_ARPEN                           /*!< ARP is enabled */
+#define I2C_ARP_DISABLE               ((uint32_t)0x00000000U)                  /*!< ARP is disabled */
+
+/* transmit I2C data */
+#define DATA_TRANS(regval)            (BITS(0,7) & ((uint32_t)(regval) << 0))
+
+/* receive I2C data */
+#define DATA_RECV(regval)             GET_BITS((uint32_t)(regval), 0, 7)
+
+/* I2C duty cycle in fast mode */
+#define I2C_DTCY_2                    ((uint32_t)0x00000000U)                  /*!< I2C fast mode Tlow/Thigh = 2 */
+#define I2C_DTCY_16_9                 I2C_CKCFG_DTCY                           /*!< I2C fast mode Tlow/Thigh = 16/9 */
+
+/* address mode for the I2C slave */
+#define I2C_ADDFORMAT_7BITS           ((uint32_t)0x00000000U)                  /*!< address:7 bits */
+#define I2C_ADDFORMAT_10BITS          I2C_SADDR0_ADDFORMAT                     /*!< address:10 bits */
+
+/* function declarations */
+/* reset I2C */
+void i2c_deinit(uint32_t i2c_periph);
+/* configure I2C clock */
+void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc);
+/* configure I2C address */
+void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr);
+/* SMBus type selection */
+void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type);
+/* whether or not to send an ACK */
+void i2c_ack_config(uint32_t i2c_periph, uint32_t ack);
+/* configure I2C POAP position */
+void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos);
+/* master sends slave address */
+void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection);
+/* enable dual-address mode */
+void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr);
+/* disable dual-address mode */
+void i2c_dualaddr_disable(uint32_t i2c_periph);
+/* enable I2C */
+void i2c_enable(uint32_t i2c_periph);
+/* disable I2C */
+void i2c_disable(uint32_t i2c_periph);
+
+/* generate a START condition on I2C bus */
+void i2c_start_on_bus(uint32_t i2c_periph);
+/* generate a STOP condition on I2C bus */
+void i2c_stop_on_bus(uint32_t i2c_periph);
+/* I2C transmit data function */
+void i2c_data_transmit(uint32_t i2c_periph, uint8_t data);
+/* I2C receive data function */
+uint8_t i2c_data_receive(uint32_t i2c_periph);
+/* enable I2C DMA mode */
+void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate);
+/* configure whether next DMA EOT is DMA last transfer or not */
+void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast);
+/* whether to stretch SCL low when data is not ready in slave mode */
+void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara);
+/* whether or not to response to a general call */
+void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara);
+/* software reset I2C */
+void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset);
+
+/* I2C PEC calculation on or off */
+void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate);
+/* I2C whether to transfer PEC value */
+void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara);
+/* packet error checking value */
+uint8_t i2c_pec_value_get(uint32_t i2c_periph);
+/* I2C issue alert through SMBA pin */
+void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara);
+/* I2C ARP protocol in SMBus switch */
+void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate);
+
+/* check I2C flag is set or not */
+FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag);
+/* clear I2C flag */
+void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag);
+/* enable I2C interrupt */
+void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt);
+/* disable I2C interrupt */
+void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt);
+/* check I2C interrupt flag */
+FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag);
+/* clear I2C interrupt flag */
+void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag);
+
+#endif /* GD32E10X_I2C_H */

+ 94 - 0
Library/Include/gd32f10x_misc.h

@@ -0,0 +1,94 @@
+/*!
+    \file    gd32f10x_misc.h
+    \brief   definitions for the MISC
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_MISC_H
+#define GD32F10X_MISC_H
+
+#include "gd32f10x.h"
+
+/* constants definitions */
+/* set the RAM and FLASH base address */
+#define NVIC_VECTTAB_RAM            ((uint32_t)0x20000000) /*!< RAM base address */
+#define NVIC_VECTTAB_FLASH          ((uint32_t)0x08000000) /*!< Flash base address */
+
+/* set the NVIC vector table offset mask */
+#define NVIC_VECTTAB_OFFSET_MASK    ((uint32_t)0x1FFFFF80)
+
+/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */
+#define NVIC_AIRCR_VECTKEY_MASK     ((uint32_t)0x05FA0000)
+
+/* priority group - define the pre-emption priority and the subpriority */
+#define NVIC_PRIGROUP_PRE0_SUB4     ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */
+#define NVIC_PRIGROUP_PRE1_SUB3     ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */
+#define NVIC_PRIGROUP_PRE2_SUB2     ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */
+#define NVIC_PRIGROUP_PRE3_SUB1     ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */
+#define NVIC_PRIGROUP_PRE4_SUB0     ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */
+
+/* choose the method to enter or exit the lowpower mode */
+#define SCB_SCR_SLEEPONEXIT         ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */
+#define SCB_SCR_SLEEPDEEP           ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */
+#define SCB_SCR_SEVONPEND           ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */
+
+#define SCB_LPM_SLEEP_EXIT_ISR      SCB_SCR_SLEEPONEXIT
+#define SCB_LPM_DEEPSLEEP           SCB_SCR_SLEEPDEEP
+#define SCB_LPM_WAKE_BY_ALL_INT     SCB_SCR_SEVONPEND
+
+/* choose the systick clock source */
+#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */
+#define SYSTICK_CLKSOURCE_HCLK      ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */
+
+/* function declarations */
+/* set the priority group */
+void nvic_priority_group_set(uint32_t nvic_prigroup);
+
+/* enable NVIC request */
+void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority);
+/* disable NVIC request */
+void nvic_irq_disable(uint8_t nvic_irq);
+
+/* set the NVIC vector table base address */
+void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset);
+
+/* set the state of the low power mode */
+void system_lowpower_set(uint8_t lowpower_mode);
+/* reset the state of the low power mode */
+void system_lowpower_reset(uint8_t lowpower_mode);
+
+/* set the systick clock source */
+void systick_clksource_set(uint32_t systick_clksource);
+
+#endif /* GD32F10X_MISC_H */

+ 128 - 0
Library/Include/gd32f10x_pmu.h

@@ -0,0 +1,128 @@
+/*!
+    \file    gd32f10x_pmu.h
+    \brief   definitions for the PMU
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_PMU_H
+#define GD32F10X_PMU_H
+
+#include "gd32f10x.h"
+
+/* PMU definitions */
+#define PMU                           PMU_BASE                 /*!< PMU base address */
+
+/* registers definitions */
+#define PMU_CTL                       REG32((PMU) + 0x00U)     /*!< PMU control register */
+#define PMU_CS                        REG32((PMU) + 0x04U)     /*!< PMU control and status register */
+
+/* bits definitions */
+/* PMU_CTL */
+#define PMU_CTL_LDOLP                 BIT(0)                   /*!< LDO low power mode */
+#define PMU_CTL_STBMOD                BIT(1)                   /*!< standby mode */
+#define PMU_CTL_WURST                 BIT(2)                   /*!< wakeup flag reset */
+#define PMU_CTL_STBRST                BIT(3)                   /*!< standby flag reset */
+#define PMU_CTL_LVDEN                 BIT(4)                   /*!< low voltage detector enable */
+#define PMU_CTL_LVDT                  BITS(5,7)                /*!< low voltage detector threshold */
+#define PMU_CTL_BKPWEN                BIT(8)                   /*!< backup domain write enable */
+
+/* PMU_CS */
+#define PMU_CS_WUF                    BIT(0)                   /*!< wakeup flag */
+#define PMU_CS_STBF                   BIT(1)                   /*!< standby flag */
+#define PMU_CS_LVDF                   BIT(2)                   /*!< low voltage detector status flag */
+#define PMU_CS_WUPEN                  BIT(8)                   /*!< wakeup pin enable */
+
+/* constants definitions */
+/* PMU low voltage detector threshold definitions */
+#define CTL_LVDT(regval)              (BITS(5,7)&((uint32_t)(regval) << 5))
+#define PMU_LVDT_0                    CTL_LVDT(0)              /*!< voltage threshold is 2.2V */
+#define PMU_LVDT_1                    CTL_LVDT(1)              /*!< voltage threshold is 2.3V */
+#define PMU_LVDT_2                    CTL_LVDT(2)              /*!< voltage threshold is 2.4V */
+#define PMU_LVDT_3                    CTL_LVDT(3)              /*!< voltage threshold is 2.5V */
+#define PMU_LVDT_4                    CTL_LVDT(4)              /*!< voltage threshold is 2.6V */
+#define PMU_LVDT_5                    CTL_LVDT(5)              /*!< voltage threshold is 2.7V */
+#define PMU_LVDT_6                    CTL_LVDT(6)              /*!< voltage threshold is 2.8V */
+#define PMU_LVDT_7                    CTL_LVDT(7)              /*!< voltage threshold is 2.9V */
+
+/* PMU flag definitions */
+#define PMU_FLAG_WAKEUP               PMU_CS_WUF               /*!< wakeup flag status */
+#define PMU_FLAG_STANDBY              PMU_CS_STBF              /*!< standby flag status */
+#define PMU_FLAG_LVD                  PMU_CS_LVDF              /*!< lvd flag status */
+
+/* PMU ldo definitions */
+#define PMU_LDO_NORMAL                ((uint32_t)0x00000000U)  /*!< LDO normal work when PMU enter deepsleep mode */
+#define PMU_LDO_LOWPOWER              PMU_CTL_LDOLP            /*!< LDO work at low power status when PMU enter deepsleep mode */
+
+/* PMU flag reset definitions */
+#define PMU_FLAG_RESET_WAKEUP         ((uint8_t)0x00U)         /*!< wakeup flag reset */
+#define PMU_FLAG_RESET_STANDBY        ((uint8_t)0x01U)         /*!< standby flag reset */
+
+/* PMU command constants definitions */
+#define WFI_CMD                       ((uint8_t)0x00U)         /*!< use WFI command */
+#define WFE_CMD                       ((uint8_t)0x01U)         /*!< use WFE command */
+
+/* function declarations */
+/* reset PMU registers */
+void pmu_deinit(void);
+
+/* select low voltage detector threshold */
+void pmu_lvd_select(uint32_t lvdt_n);
+/* disable PMU lvd */
+void pmu_lvd_disable(void);
+
+/* set PMU mode */
+/* PMU work at sleep mode */
+void pmu_to_sleepmode(uint8_t sleepmodecmd);
+/* PMU work at deepsleep mode */
+void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd);
+/* PMU work at standby mode */
+void pmu_to_standbymode(uint8_t standbymodecmd);
+/* enable PMU wakeup pin */
+void pmu_wakeup_pin_enable(void);
+/* disable PMU wakeup pin */
+void pmu_wakeup_pin_disable(void);
+
+/* backup related functions */
+/* enable write access to the registers in backup domain */
+void pmu_backup_write_enable(void);
+/* disable write access to the registers in backup domain */
+void pmu_backup_write_disable(void);
+
+/* flag functions */
+/* get flag state */
+FlagStatus pmu_flag_get(uint32_t flag);
+/* clear flag bit */
+void pmu_flag_clear(uint32_t flag_reset);
+
+#endif /* GD32F10X_PMU_H */

+ 923 - 0
Library/Include/gd32f10x_rcu.h

@@ -0,0 +1,923 @@
+/*!
+    \file    gd32f10x_rcu.h
+    \brief   definitions for the RCU
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_RCU_H
+#define GD32F10X_RCU_H
+
+#include "gd32f10x.h"
+
+/* RCU definitions */
+#define RCU                             RCU_BASE
+
+/* registers definitions */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_CTL                         REG32(RCU + 0x00U)        /*!< control register */
+#define RCU_CFG0                        REG32(RCU + 0x04U)        /*!< clock configuration register 0 */
+#define RCU_INT                         REG32(RCU + 0x08U)        /*!< clock interrupt register */
+#define RCU_APB2RST                     REG32(RCU + 0x0CU)        /*!< APB2 reset register */
+#define RCU_APB1RST                     REG32(RCU + 0x10U)        /*!< APB1 reset register */
+#define RCU_AHBEN                       REG32(RCU + 0x14U)        /*!< AHB enable register */
+#define RCU_APB2EN                      REG32(RCU + 0x18U)        /*!< APB2 enable register */
+#define RCU_APB1EN                      REG32(RCU + 0x1CU)        /*!< APB1 enable register */
+#define RCU_BDCTL                       REG32(RCU + 0x20U)        /*!< backup domain control register */
+#define RCU_RSTSCK                      REG32(RCU + 0x24U)        /*!< reset source / clock register */
+#define RCU_DSV                         REG32(RCU + 0x34U)        /*!< deep-sleep mode voltage register */
+#elif defined(GD32F10X_CL)
+#define RCU_CTL                         REG32(RCU + 0x00U)        /*!< control register */
+#define RCU_CFG0                        REG32(RCU + 0x04U)        /*!< clock configuration register 0 */
+#define RCU_INT                         REG32(RCU + 0x08U)        /*!< clock interrupt register */
+#define RCU_APB2RST                     REG32(RCU + 0x0CU)        /*!< APB2 reset register */
+#define RCU_APB1RST                     REG32(RCU + 0x10U)        /*!< APB1 reset register */
+#define RCU_AHBEN                       REG32(RCU + 0x14U)        /*!< AHB1 enable register */
+#define RCU_APB2EN                      REG32(RCU + 0x18U)        /*!< APB2 enable register */
+#define RCU_APB1EN                      REG32(RCU + 0x1CU)        /*!< APB1 enable register */
+#define RCU_BDCTL                       REG32(RCU + 0x20U)        /*!< backup domain control register */
+#define RCU_RSTSCK                      REG32(RCU + 0x24U)        /*!< reset source / clock register */
+#define RCU_AHBRST                      REG32(RCU + 0x28U)        /*!< AHB reset register */
+#define RCU_CFG1                        REG32(RCU + 0x2CU)        /*!< clock configuration register 1 */
+#define RCU_DSV                         REG32(RCU + 0x34U)        /*!< deep-sleep mode voltage register */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* bits definitions */
+/* RCU_CTL */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_CTL_IRC8MEN                 BIT(0)                    /*!< internal high speed oscillator enable */
+#define RCU_CTL_IRC8MSTB                BIT(1)                    /*!< IRC8M high speed internal oscillator stabilization flag */
+#define RCU_CTL_IRC8MADJ                BITS(3,7)                 /*!< high speed internal oscillator clock trim adjust value */
+#define RCU_CTL_IRC8MCALIB              BITS(8,15)                /*!< high speed internal oscillator calibration value register */
+#define RCU_CTL_HXTALEN                 BIT(16)                   /*!< external high speed oscillator enable */
+#define RCU_CTL_HXTALSTB                BIT(17)                   /*!< external crystal oscillator clock stabilization flag */
+#define RCU_CTL_HXTALBPS                BIT(18)                   /*!< external crystal oscillator clock bypass mode enable */
+#define RCU_CTL_CKMEN                   BIT(19)                   /*!< HXTAL clock monitor enable */
+#define RCU_CTL_PLLEN                   BIT(24)                   /*!< PLL enable */
+#define RCU_CTL_PLLSTB                  BIT(25)                   /*!< PLL clock stabilization flag */
+#elif defined(GD32F10X_CL)
+#define RCU_CTL_IRC8MEN                 BIT(0)                    /*!< internal high speed oscillator enable */
+#define RCU_CTL_IRC8MSTB                BIT(1)                    /*!< IRC8M high speed internal oscillator stabilization flag */
+#define RCU_CTL_IRC8MADJ                BITS(3,7)                 /*!< high speed internal oscillator clock trim adjust value */
+#define RCU_CTL_IRC8MCALIB              BITS(8,15)                /*!< high speed internal oscillator calibration value register */
+#define RCU_CTL_HXTALEN                 BIT(16)                   /*!< external high speed oscillator enable */
+#define RCU_CTL_HXTALSTB                BIT(17)                   /*!< external crystal oscillator clock stabilization flag */
+#define RCU_CTL_HXTALBPS                BIT(18)                   /*!< external crystal oscillator clock bypass mode enable */
+#define RCU_CTL_CKMEN                   BIT(19)                   /*!< HXTAL clock monitor enable */
+#define RCU_CTL_PLLEN                   BIT(24)                   /*!< PLL enable */
+#define RCU_CTL_PLLSTB                  BIT(25)                   /*!< PLL clock stabilization flag */
+#define RCU_CTL_PLL1EN                  BIT(26)                   /*!< PLL1 enable */
+#define RCU_CTL_PLL1STB                 BIT(27)                   /*!< PLL1 clock stabilization flag */
+#define RCU_CTL_PLL2EN                  BIT(28)                   /*!< PLL2 enable */
+#define RCU_CTL_PLL2STB                 BIT(29)                   /*!< PLL2 clock stabilization flag */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* RCU_CFG0 */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_CFG0_SCS                    BITS(0,1)                 /*!< system clock switch */
+#define RCU_CFG0_SCSS                   BITS(2,3)                 /*!< system clock switch status */
+#define RCU_CFG0_AHBPSC                 BITS(4,7)                 /*!< AHB prescaler selection */
+#define RCU_CFG0_APB1PSC                BITS(8,10)                /*!< APB1 prescaler selection */
+#define RCU_CFG0_APB2PSC                BITS(11,13)               /*!< APB2 prescaler selection */
+#define RCU_CFG0_ADCPSC                 BITS(14,15)               /*!< ADC prescaler selection */
+#define RCU_CFG0_PLLSEL                 BIT(16)                   /*!< PLL clock source selection */
+#define RCU_CFG0_PREDV0                 BIT(17)                   /*!< PREDV0 division factor */
+#define RCU_CFG0_PLLMF                  BITS(18,21)               /*!< PLL clock multiplication factor */
+#define RCU_CFG0_USBDPSC                BITS(22,23)               /*!< USBD clock prescaler selection */
+#define RCU_CFG0_CKOUT0SEL              BITS(24,26)               /*!< CKOUT0 clock source selection */
+#define RCU_CFG0_PLLMF_4                BIT(27)                   /*!< bit 4 of PLLMF */
+#define RCU_CFG0_ADCPSC_2               BIT(28)                   /*!< bit 2 of ADCPSC */
+#elif defined(GD32F10X_CL)
+#define RCU_CFG0_SCS                    BITS(0,1)                 /*!< system clock switch */
+#define RCU_CFG0_SCSS                   BITS(2,3)                 /*!< system clock switch status */
+#define RCU_CFG0_AHBPSC                 BITS(4,7)                 /*!< AHB prescaler selection */
+#define RCU_CFG0_APB1PSC                BITS(8,10)                /*!< APB1 prescaler selection */
+#define RCU_CFG0_APB2PSC                BITS(11,13)               /*!< APB2 prescaler selection */
+#define RCU_CFG0_ADCPSC                 BITS(14,15)               /*!< ADC prescaler selection */
+#define RCU_CFG0_PLLSEL                 BIT(16)                   /*!< PLL clock source selection */
+#define RCU_CFG0_PREDV0_LSB             BIT(17)                   /*!< the LSB of PREDV0 division factor */
+#define RCU_CFG0_PLLMF                  BITS(18,21)               /*!< PLL clock multiplication factor */
+#define RCU_CFG0_USBFSPSC               BITS(22,23)               /*!< USBFS clock prescaler selection */
+#define RCU_CFG0_CKOUT0SEL              BITS(24,27)               /*!< CKOUT0 clock source selection */
+#define RCU_CFG0_ADCPSC_2               BIT(28)                   /*!< bit 2 of ADCPSC */
+#define RCU_CFG0_PLLMF_4                BIT(29)                   /*!< bit 4 of PLLMF */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* RCU_INT */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_INT_IRC40KSTBIF             BIT(0)                    /*!< IRC40K stabilization interrupt flag */
+#define RCU_INT_LXTALSTBIF              BIT(1)                    /*!< LXTAL stabilization interrupt flag */
+#define RCU_INT_IRC8MSTBIF              BIT(2)                    /*!< IRC8M stabilization interrupt flag */
+#define RCU_INT_HXTALSTBIF              BIT(3)                    /*!< HXTAL stabilization interrupt flag */
+#define RCU_INT_PLLSTBIF                BIT(4)                    /*!< PLL stabilization interrupt flag */
+#define RCU_INT_CKMIF                   BIT(7)                    /*!< HXTAL clock stuck interrupt flag */
+#define RCU_INT_IRC40KSTBIE             BIT(8)                    /*!< IRC40K stabilization interrupt enable */
+#define RCU_INT_LXTALSTBIE              BIT(9)                    /*!< LXTAL stabilization interrupt enable */
+#define RCU_INT_IRC8MSTBIE              BIT(10)                   /*!< IRC8M stabilization interrupt enable */
+#define RCU_INT_HXTALSTBIE              BIT(11)                   /*!< HXTAL stabilization interrupt enable */
+#define RCU_INT_PLLSTBIE                BIT(12)                   /*!< PLL stabilization interrupt enable */
+#define RCU_INT_IRC40KSTBIC             BIT(16)                   /*!< IRC40K Stabilization interrupt clear */
+#define RCU_INT_LXTALSTBIC              BIT(17)                   /*!< LXTAL Stabilization interrupt clear */
+#define RCU_INT_IRC8MSTBIC              BIT(18)                   /*!< IRC8M Stabilization interrupt clear */
+#define RCU_INT_HXTALSTBIC              BIT(19)                   /*!< HXTAL Stabilization interrupt clear */
+#define RCU_INT_PLLSTBIC                BIT(20)                   /*!< PLL stabilization interrupt clear */
+#define RCU_INT_CKMIC                   BIT(23)                   /*!< HXTAL clock stuck interrupt clear */
+#elif defined(GD32F10X_CL)
+#define RCU_INT_IRC40KSTBIF             BIT(0)                    /*!< IRC40K stabilization interrupt flag */
+#define RCU_INT_LXTALSTBIF              BIT(1)                    /*!< LXTAL stabilization interrupt flag */
+#define RCU_INT_IRC8MSTBIF              BIT(2)                    /*!< IRC8M stabilization interrupt flag */
+#define RCU_INT_HXTALSTBIF              BIT(3)                    /*!< HXTAL stabilization interrupt flag */
+#define RCU_INT_PLLSTBIF                BIT(4)                    /*!< PLL stabilization interrupt flag */
+#define RCU_INT_PLL1STBIF               BIT(5)                    /*!< PLL1 stabilization interrupt flag */
+#define RCU_INT_PLL2STBIF               BIT(6)                    /*!< PLL2 stabilization interrupt flag */
+#define RCU_INT_CKMIF                   BIT(7)                    /*!< HXTAL clock stuck interrupt flag */
+#define RCU_INT_IRC40KSTBIE             BIT(8)                    /*!< IRC40K stabilization interrupt enable */
+#define RCU_INT_LXTALSTBIE              BIT(9)                    /*!< LXTAL stabilization interrupt enable */
+#define RCU_INT_IRC8MSTBIE              BIT(10)                   /*!< IRC8M stabilization interrupt enable */
+#define RCU_INT_HXTALSTBIE              BIT(11)                   /*!< HXTAL stabilization interrupt enable */
+#define RCU_INT_PLLSTBIE                BIT(12)                   /*!< PLL stabilization interrupt enable */
+#define RCU_INT_PLL1STBIE               BIT(13)                   /*!< PLL1 stabilization interrupt enable */
+#define RCU_INT_PLL2STBIE               BIT(14)                   /*!< PLL2 stabilization interrupt enable */
+#define RCU_INT_IRC40KSTBIC             BIT(16)                   /*!< IRC40K stabilization interrupt clear */
+#define RCU_INT_LXTALSTBIC              BIT(17)                   /*!< LXTAL stabilization interrupt clear */
+#define RCU_INT_IRC8MSTBIC              BIT(18)                   /*!< IRC8M stabilization interrupt clear */
+#define RCU_INT_HXTALSTBIC              BIT(19)                   /*!< HXTAL stabilization interrupt clear */
+#define RCU_INT_PLLSTBIC                BIT(20)                   /*!< PLL stabilization interrupt clear */
+#define RCU_INT_PLL1STBIC               BIT(21)                   /*!< PLL1 stabilization interrupt clear */
+#define RCU_INT_PLL2STBIC               BIT(22)                   /*!< PLL2 stabilization interrupt clear */
+#define RCU_INT_CKMIC                   BIT(23)                   /*!< HXTAL clock stuck interrupt clear */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* RCU_APB2RST */
+#define RCU_APB2RST_AFRST               BIT(0)                    /*!< alternate function I/O reset */
+#define RCU_APB2RST_PARST               BIT(2)                    /*!< GPIO port A reset */
+#define RCU_APB2RST_PBRST               BIT(3)                    /*!< GPIO port B reset */
+#define RCU_APB2RST_PCRST               BIT(4)                    /*!< GPIO port C reset */
+#define RCU_APB2RST_PDRST               BIT(5)                    /*!< GPIO port D reset */
+#define RCU_APB2RST_PERST               BIT(6)                    /*!< GPIO port E reset */
+#define RCU_APB2RST_PFRST               BIT(7)                    /*!< GPIO port F reset */
+#define RCU_APB2RST_PGRST               BIT(8)                    /*!< GPIO port G reset */
+#define RCU_APB2RST_ADC0RST             BIT(9)                    /*!< ADC0 reset */
+#define RCU_APB2RST_ADC1RST             BIT(10)                   /*!< ADC1 reset */
+#define RCU_APB2RST_TIMER0RST           BIT(11)                   /*!< TIMER0 reset */
+#define RCU_APB2RST_SPI0RST             BIT(12)                   /*!< SPI0 reset */
+#define RCU_APB2RST_TIMER7RST           BIT(13)                   /*!< TIMER7 reset */
+#define RCU_APB2RST_USART0RST           BIT(14)                   /*!< USART0 reset */
+#ifndef GD32F10X_CL
+#define RCU_APB2RST_ADC2RST             BIT(15)                   /*!< ADC2 reset */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+#define RCU_APB2RST_TIMER8RST           BIT(19)                   /*!< TIMER8 reset */
+#define RCU_APB2RST_TIMER9RST           BIT(20)                   /*!< TIMER9 reset */
+#define RCU_APB2RST_TIMER10RST          BIT(21)                   /*!< TIMER10 reset */
+#endif /* GD32F10X_XD */
+
+/* RCU_APB1RST */
+#define RCU_APB1RST_TIMER1RST           BIT(0)                    /*!< TIMER1 reset */
+#define RCU_APB1RST_TIMER2RST           BIT(1)                    /*!< TIMER2 reset */
+#define RCU_APB1RST_TIMER3RST           BIT(2)                    /*!< TIMER3 reset */
+#define RCU_APB1RST_TIMER4RST           BIT(3)                    /*!< TIMER4 reset */
+#define RCU_APB1RST_TIMER5RST           BIT(4)                    /*!< TIMER5 reset */
+#define RCU_APB1RST_TIMER6RST           BIT(5)                    /*!< TIMER6 reset */
+#ifdef GD32F10X_XD
+#define RCU_APB1RST_TIMER11RST          BIT(6)                    /*!< TIMER11 reset */
+#define RCU_APB1RST_TIMER12RST          BIT(7)                    /*!< TIMER12 reset */
+#define RCU_APB1RST_TIMER13RST          BIT(8)                    /*!< TIMER13 reset */
+#endif /* GD32F10X_XD */
+#define RCU_APB1RST_WWDGTRST            BIT(11)                   /*!< WWDGT reset */
+#define RCU_APB1RST_SPI1RST             BIT(14)                   /*!< SPI1 reset */
+#define RCU_APB1RST_SPI2RST             BIT(15)                   /*!< SPI2 reset */
+#define RCU_APB1RST_USART1RST           BIT(17)                   /*!< USART1 reset */
+#define RCU_APB1RST_USART2RST           BIT(18)                   /*!< USART2 reset */
+#define RCU_APB1RST_UART3RST            BIT(19)                   /*!< UART3 reset */
+#define RCU_APB1RST_UART4RST            BIT(20)                   /*!< UART4 reset */
+#define RCU_APB1RST_I2C0RST             BIT(21)                   /*!< I2C0 reset */
+#define RCU_APB1RST_I2C1RST             BIT(22)                   /*!< I2C1 reset */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_APB1RST_USBDRST             BIT(23)                   /*!< USBD reset */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+#define RCU_APB1RST_CAN0RST             BIT(25)                   /*!< CAN0 reset */
+#ifdef GD32F10X_CL
+#define RCU_APB1RST_CAN1RST             BIT(26)                   /*!< CAN1 reset */
+#endif /* GD32F10X_CL */
+#define RCU_APB1RST_BKPIRST             BIT(27)                   /*!< backup interface reset */
+#define RCU_APB1RST_PMURST              BIT(28)                   /*!< PMU reset */
+#define RCU_APB1RST_DACRST              BIT(29)                   /*!< DAC reset */
+
+/* RCU_AHBEN */
+#define RCU_AHBEN_DMA0EN                BIT(0)                    /*!< DMA0 clock enable */
+#define RCU_AHBEN_DMA1EN                BIT(1)                    /*!< DMA1 clock enable */
+#define RCU_AHBEN_SRAMSPEN              BIT(2)                    /*!< SRAM clock enable when sleep mode */
+#define RCU_AHBEN_FMCSPEN               BIT(4)                    /*!< FMC clock enable when sleep mode */
+#define RCU_AHBEN_CRCEN                 BIT(6)                    /*!< CRC clock enable */
+#define RCU_AHBEN_EXMCEN                BIT(8)                    /*!< EXMC clock enable */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_AHBEN_SDIOEN                BIT(10)                   /*!< SDIO clock enable */
+#elif defined(GD32F10X_CL)
+#define RCU_AHBEN_USBFSEN               BIT(12)                   /*!< USBFS clock enable */
+#define RCU_AHBEN_ENETEN                BIT(14)                   /*!< ENET clock enable */
+#define RCU_AHBEN_ENETTXEN              BIT(15)                   /*!< Ethernet TX clock enable */
+#define RCU_AHBEN_ENETRXEN              BIT(16)                   /*!< Ethernet RX clock enable */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* RCU_APB2EN */
+#define RCU_APB2EN_AFEN                 BIT(0)                    /*!< alternate function IO clock enable */
+#define RCU_APB2EN_PAEN                 BIT(2)                    /*!< GPIO port A clock enable */
+#define RCU_APB2EN_PBEN                 BIT(3)                    /*!< GPIO port B clock enable */
+#define RCU_APB2EN_PCEN                 BIT(4)                    /*!< GPIO port C clock enable */
+#define RCU_APB2EN_PDEN                 BIT(5)                    /*!< GPIO port D clock enable */
+#define RCU_APB2EN_PEEN                 BIT(6)                    /*!< GPIO port E clock enable */
+#define RCU_APB2EN_PFEN                 BIT(7)                    /*!< GPIO port F clock enable */
+#define RCU_APB2EN_PGEN                 BIT(8)                    /*!< GPIO port G clock enable */
+#define RCU_APB2EN_ADC0EN               BIT(9)                    /*!< ADC0 clock enable */
+#define RCU_APB2EN_ADC1EN               BIT(10)                   /*!< ADC1 clock enable */
+#define RCU_APB2EN_TIMER0EN             BIT(11)                   /*!< TIMER0 clock enable */
+#define RCU_APB2EN_SPI0EN               BIT(12)                   /*!< SPI0 clock enable */
+#define RCU_APB2EN_TIMER7EN             BIT(13)                   /*!< TIMER7 clock enable */
+#define RCU_APB2EN_USART0EN             BIT(14)                   /*!< USART0 clock enable */
+#ifndef GD32F10X_CL
+#define RCU_APB2EN_ADC2EN               BIT(15)                   /*!< ADC2 clock enable */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+#define RCU_APB2EN_TIMER8EN             BIT(19)                   /*!< TIMER8 clock enable */
+#define RCU_APB2EN_TIMER9EN             BIT(20)                   /*!< TIMER9 clock enable */
+#define RCU_APB2EN_TIMER10EN            BIT(21)                   /*!< TIMER10 clock enable */
+#endif /* GD32F10X_XD */
+
+/* RCU_APB1EN */
+#define RCU_APB1EN_TIMER1EN             BIT(0)                    /*!< TIMER1 clock enable */
+#define RCU_APB1EN_TIMER2EN             BIT(1)                    /*!< TIMER2 clock enable */
+#define RCU_APB1EN_TIMER3EN             BIT(2)                    /*!< TIMER3 clock enable */
+#define RCU_APB1EN_TIMER4EN             BIT(3)                    /*!< TIMER4 clock enable */
+#define RCU_APB1EN_TIMER5EN             BIT(4)                    /*!< TIMER5 clock enable */
+#define RCU_APB1EN_TIMER6EN             BIT(5)                    /*!< TIMER6 clock enable */
+#ifdef GD32F10X_XD
+#define RCU_APB1EN_TIMER11EN            BIT(6)                    /*!< TIMER11 clock enable */
+#define RCU_APB1EN_TIMER12EN            BIT(7)                    /*!< TIMER12 clock enable */
+#define RCU_APB1EN_TIMER13EN            BIT(8)                    /*!< TIMER13 clock enable */
+#endif /* GD32F10X_XD */
+#define RCU_APB1EN_WWDGTEN              BIT(11)                   /*!< WWDGT clock enable */
+#define RCU_APB1EN_SPI1EN               BIT(14)                   /*!< SPI1 clock enable */
+#define RCU_APB1EN_SPI2EN               BIT(15)                   /*!< SPI2 clock enable */
+#define RCU_APB1EN_USART1EN             BIT(17)                   /*!< USART1 clock enable */
+#define RCU_APB1EN_USART2EN             BIT(18)                   /*!< USART2 clock enable */
+#define RCU_APB1EN_UART3EN              BIT(19)                   /*!< UART3 clock enable */
+#define RCU_APB1EN_UART4EN              BIT(20)                   /*!< UART4 clock enable */
+#define RCU_APB1EN_I2C0EN               BIT(21)                   /*!< I2C0 clock enable */
+#define RCU_APB1EN_I2C1EN               BIT(22)                   /*!< I2C1 clock enable */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_APB1EN_USBDEN               BIT(23)                   /*!< USBD clock enable */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+#define RCU_APB1EN_CAN0EN               BIT(25)                   /*!< CAN0 clock enable */
+#ifdef GD32F10X_CL
+#define RCU_APB1EN_CAN1EN               BIT(26)                   /*!< CAN1 clock enable */
+#endif /* GD32F10X_CL */
+#define RCU_APB1EN_BKPIEN               BIT(27)                   /*!< backup interface clock enable */
+#define RCU_APB1EN_PMUEN                BIT(28)                   /*!< PMU clock enable */
+#define RCU_APB1EN_DACEN                BIT(29)                   /*!< DAC clock enable */
+
+/* RCU_BDCTL */
+#define RCU_BDCTL_LXTALEN               BIT(0)                    /*!< LXTAL enable */
+#define RCU_BDCTL_LXTALSTB              BIT(1)                    /*!< low speed crystal oscillator stabilization flag */
+#define RCU_BDCTL_LXTALBPS              BIT(2)                    /*!< LXTAL bypass mode enable */
+#define RCU_BDCTL_RTCSRC                BITS(8,9)                 /*!< RTC clock entry selection */
+#define RCU_BDCTL_RTCEN                 BIT(15)                   /*!< RTC clock enable */
+#define RCU_BDCTL_BKPRST                BIT(16)                   /*!< backup domain reset */
+
+/* RCU_RSTSCK */
+#define RCU_RSTSCK_IRC40KEN             BIT(0)                    /*!< IRC40K enable */
+#define RCU_RSTSCK_IRC40KSTB            BIT(1)                    /*!< IRC40K stabilization flag */
+#define RCU_RSTSCK_RSTFC                BIT(24)                   /*!< reset flag clear */
+#define RCU_RSTSCK_EPRSTF               BIT(26)                   /*!< external pin reset flag */
+#define RCU_RSTSCK_PORRSTF              BIT(27)                   /*!< power reset flag */
+#define RCU_RSTSCK_SWRSTF               BIT(28)                   /*!< software reset flag */
+#define RCU_RSTSCK_FWDGTRSTF            BIT(29)                   /*!< free watchdog timer reset flag */
+#define RCU_RSTSCK_WWDGTRSTF            BIT(30)                   /*!< window watchdog timer reset flag */
+#define RCU_RSTSCK_LPRSTF               BIT(31)                   /*!< low-power reset flag */
+
+#ifdef GD32F10X_CL
+/* RCU_AHBRST */
+#define RCU_AHBRST_USBFSRST             BIT(12)                   /*!< USBFS reset */
+#define RCU_AHBRST_ENETRST              BIT(14)                   /*!< ENET reset */
+#endif /* GD32F10X_CL */
+
+#if defined(GD32F10X_CL)
+/* RCU_CFG1 */
+#define RCU_CFG1_PREDV0                 BITS(0,3)                 /*!< PREDV0 division factor */
+#define RCU_CFG1_PREDV1                 BITS(4,7)                 /*!< PREDV1 division factor */
+#define RCU_CFG1_PLL1MF                 BITS(8,11)                /*!< PLL1 clock multiplication factor */
+#define RCU_CFG1_PLL2MF                 BITS(12,15)               /*!< PLL2 clock multiplication factor */
+#define RCU_CFG1_PREDV0SEL              BIT(16)                   /*!< PREDV0 input clock source selection */
+#define RCU_CFG1_I2S1SEL                BIT(17)                   /*!< I2S1 clock source selection */
+#define RCU_CFG1_I2S2SEL                BIT(18)                   /*!< I2S2 clock source selection  */
+#endif /* GD32F10X_CL */
+
+/* RCU_DSV */
+#define RCU_DSV_DSLPVS                  BITS(0,2)                 /*!< deep-sleep mode voltage select */
+
+/* constants definitions */
+/* define the peripheral clock enable bit position and its register index offset */
+#define RCU_REGIDX_BIT(regidx, bitpos)      (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define RCU_REG_VAL(periph)                 (REG32(RCU + ((uint32_t)(periph) >> 6)))
+#define RCU_BIT_POS(val)                    ((uint32_t)(val) & 0x1FU)
+
+/* register offset */
+/* peripherals enable */
+#define AHBEN_REG_OFFSET                0x14U                     /*!< AHB enable register offset */
+#define APB1EN_REG_OFFSET               0x1CU                     /*!< APB1 enable register offset */
+#define APB2EN_REG_OFFSET               0x18U                     /*!< APB2 enable register offset */
+
+/* peripherals reset */
+#define AHBRST_REG_OFFSET               0x28U                     /*!< AHB reset register offset */
+#define APB1RST_REG_OFFSET              0x10U                     /*!< APB1 reset register offset */
+#define APB2RST_REG_OFFSET              0x0CU                     /*!< APB2 reset register offset */
+#define RSTSCK_REG_OFFSET               0x24U                     /*!< reset source/clock register offset */
+
+/* clock control */
+#define CTL_REG_OFFSET                  0x00U                     /*!< control register offset */
+#define BDCTL_REG_OFFSET                0x20U                     /*!< backup domain control register offset */
+
+/* clock stabilization and stuck interrupt */
+#define INT_REG_OFFSET                  0x08U                     /*!< clock interrupt register offset */
+
+/* configuration register */
+#define CFG0_REG_OFFSET                 0x04U                     /*!< clock configuration register 0 offset */
+#define CFG1_REG_OFFSET                 0x2CU                     /*!< clock configuration register 1 offset */
+
+/* peripheral clock enable */
+typedef enum
+{
+    /* AHB peripherals */
+    RCU_DMA0      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U),                   /*!< DMA0 clock */
+    RCU_DMA1      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U),                   /*!< DMA1 clock */
+    RCU_CRC       = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U),                   /*!< CRC clock */
+    RCU_EXMC      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U),                   /*!< EXMC clock */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    RCU_SDIO      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U),                  /*!< SDIO clock */
+#elif defined(GD32F10X_CL)
+    RCU_USBFS     = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U),                  /*!< USBFS clock */
+    RCU_ENET      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U),                  /*!< ENET clock */
+    RCU_ENETTX    = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U),                  /*!< ENETTX clock */
+    RCU_ENETRX    = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U),                  /*!< ENETRX clock */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+    
+    /* APB1 peripherals */
+    RCU_TIMER1    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U),                  /*!< TIMER1 clock */
+    RCU_TIMER2    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U),                  /*!< TIMER2 clock */
+    RCU_TIMER3    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U),                  /*!< TIMER3 clock */
+    RCU_TIMER4    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U),                  /*!< TIMER4 clock */
+    RCU_TIMER5    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U),                  /*!< TIMER5 clock */
+    RCU_TIMER6    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U),                  /*!< TIMER6 clock */
+#if defined(GD32F10X_XD)
+    RCU_TIMER11   = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U),                  /*!< TIMER11 clock */
+    RCU_TIMER12   = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U),                  /*!< TIMER12 clock */
+    RCU_TIMER13   = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U),                  /*!< TIMER13 clock */
+#endif /* GD32F10X_XD */
+    RCU_WWDGT     = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U),                 /*!< WWDGT clock */
+    RCU_SPI1      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U),                 /*!< SPI1 clock */
+    RCU_SPI2      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U),                 /*!< SPI2 clock */
+    RCU_USART1    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U),                 /*!< USART1 clock */
+    RCU_USART2    = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U),                 /*!< USART2 clock */
+    RCU_UART3     = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U),                 /*!< UART3 clock */
+    RCU_UART4     = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U),                 /*!< UART4 clock */
+    RCU_I2C0      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U),                 /*!< I2C0 clock */
+    RCU_I2C1      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U),                 /*!< I2C1 clock */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    RCU_USBD      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U),                 /*!< USBD clock */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+    RCU_CAN0      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U),                 /*!< CAN0 clock */
+#ifdef GD32F10X_CL
+    RCU_CAN1      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U),                 /*!< CAN1 clock */
+#endif /* GD32F10X_CL */
+    RCU_BKPI      = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U),                 /*!< BKPI clock */
+    RCU_PMU       = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U),                 /*!< PMU clock */
+    RCU_DAC       = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U),                 /*!< DAC clock */
+    RCU_RTC       = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U),                  /*!< RTC clock */
+    
+    /* APB2 peripherals */
+    RCU_AF        = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U),                  /*!< alternate function clock */
+    RCU_GPIOA     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U),                  /*!< GPIOA clock */
+    RCU_GPIOB     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U),                  /*!< GPIOB clock */
+    RCU_GPIOC     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U),                  /*!< GPIOC clock */
+    RCU_GPIOD     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U),                  /*!< GPIOD clock */
+    RCU_GPIOE     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U),                  /*!< GPIOE clock */
+    RCU_GPIOF     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U),                  /*!< GPIOF clock */
+    RCU_GPIOG     = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U),                  /*!< GPIOG clock */
+    RCU_ADC0      = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U),                  /*!< ADC0 clock */
+    RCU_ADC1      = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U),                 /*!< ADC1 clock */
+    RCU_TIMER0    = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U),                 /*!< TIMER0 clock */
+    RCU_SPI0      = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U),                 /*!< SPI0 clock */
+    RCU_TIMER7    = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U),                 /*!< TIMER7 clock */
+    RCU_USART0    = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U),                 /*!< USART0 clock */
+#ifndef GD32F10X_CL
+    RCU_ADC2      = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U),                 /*!< ADC2 clock */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+    RCU_TIMER8    = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U),                 /*!< TIMER8 clock */
+    RCU_TIMER9    = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U),                 /*!< TIMER9 clock */
+    RCU_TIMER10   = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U),                 /*!< TIMER10 clock */
+#endif /* GD32F10X_XD */
+}rcu_periph_enum;
+
+/* peripheral clock enable when sleep mode*/
+typedef enum
+{
+    /* AHB peripherals */
+    RCU_SRAM_SLP     = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U),                /*!< SRAM clock */
+    RCU_FMC_SLP      = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U),                /*!< FMC clock */
+}rcu_periph_sleep_enum;
+
+/* peripherals reset */
+typedef enum
+{
+    /* AHB peripherals */
+#ifdef GD32F10X_CL
+    RCU_USBFSRST     = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U),              /*!< USBFS clock reset */
+    RCU_ENETRST      = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U),              /*!< ENET clock reset */
+#endif /* GD32F10X_CL */
+    
+    /* APB1 peripherals */
+    RCU_TIMER1RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U),              /*!< TIMER1 clock reset */
+    RCU_TIMER2RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U),              /*!< TIMER2 clock reset */
+    RCU_TIMER3RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U),              /*!< TIMER3 clock reset */
+    RCU_TIMER4RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U),              /*!< TIMER4 clock reset */
+    RCU_TIMER5RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U),              /*!< TIMER5 clock reset */
+    RCU_TIMER6RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U),              /*!< TIMER6 clock reset */
+#ifdef GD32F10X_XD
+    RCU_TIMER11RST   = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U),              /*!< TIMER11 clock reset */
+    RCU_TIMER12RST   = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U),              /*!< TIMER12 clock reset */
+    RCU_TIMER13RST   = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U),              /*!< TIMER13 clock reset */
+#endif /* GD32F10X_XD */
+    RCU_WWDGTRST     = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U),             /*!< WWDGT clock reset */
+    RCU_SPI1RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U),             /*!< SPI1 clock reset */
+    RCU_SPI2RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U),             /*!< SPI2 clock reset */
+    RCU_USART1RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U),             /*!< USART1 clock reset */
+    RCU_USART2RST    = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U),             /*!< USART2 clock reset */
+    RCU_UART3RST     = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U),             /*!< UART3 clock reset */
+    RCU_UART4RST     = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U),             /*!< UART4 clock reset */
+    RCU_I2C0RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U),             /*!< I2C0 clock reset */
+    RCU_I2C1RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U),             /*!< I2C1 clock reset */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    RCU_USBDRST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U),             /*!< USBD clock reset */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+    RCU_CAN0RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U),             /*!< CAN0 clock reset */
+#ifdef GD32F10X_CL
+    RCU_CAN1RST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U),             /*!< CAN1 clock reset */
+#endif /* GD32F10X_CL */
+    RCU_BKPIRST      = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U),             /*!< BKPI clock reset */
+    RCU_PMURST       = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U),             /*!< PMU clock reset */
+    RCU_DACRST       = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U),             /*!< DAC clock reset */
+    
+    /* APB2 peripherals */
+    RCU_AFRST        = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U),              /*!< alternate function clock reset */
+    RCU_GPIOARST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U),              /*!< GPIOA clock reset */
+    RCU_GPIOBRST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U),              /*!< GPIOB clock reset */
+    RCU_GPIOCRST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U),              /*!< GPIOC clock reset */
+    RCU_GPIODRST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U),              /*!< GPIOD clock reset */
+    RCU_GPIOERST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U),              /*!< GPIOE clock reset */
+    RCU_GPIOFRST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U),              /*!< GPIOF clock reset */
+    RCU_GPIOGRST     = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U),              /*!< GPIOG clock reset */
+    RCU_ADC0RST      = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U),              /*!< ADC0 clock reset */
+    RCU_ADC1RST      = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U),             /*!< ADC1 clock reset */
+    RCU_TIMER0RST    = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U),             /*!< TIMER0 clock reset */
+    RCU_SPI0RST      = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U),             /*!< SPI0 clock reset */
+    RCU_TIMER7RST    = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U),             /*!< TIMER7 clock reset */
+    RCU_USART0RST    = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U),             /*!< USART0 clock reset */
+#ifndef GD32F10X_CL
+    RCU_ADC2RST      = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U),             /*!< ADC2 clock reset */
+#endif /* GD32F10X_CL */
+#ifdef GD32F10X_XD
+    RCU_TIMER8RST    = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U),             /*!< TIMER8 clock reset */
+    RCU_TIMER9RST    = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U),             /*!< TIMER9 clock reset */
+    RCU_TIMER10RST   = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U),             /*!< TIMER10 clock reset */
+#endif /* GD32F10X_XD */
+}rcu_periph_reset_enum;
+
+/* clock stabilization and peripheral reset flags */
+typedef enum
+{
+    /* clock stabilization flags */
+    RCU_FLAG_IRC8MSTB      = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U),            /*!< IRC8M stabilization flags */
+    RCU_FLAG_HXTALSTB      = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U),           /*!< HXTAL stabilization flags */
+    RCU_FLAG_PLLSTB        = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U),           /*!< PLL stabilization flags */
+#ifdef GD32F10X_CL
+    RCU_FLAG_PLL1STB       = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U),           /*!< PLL1 stabilization flags */
+    RCU_FLAG_PLL2STB       = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U),           /*!< PLL2 stabilization flags */
+#endif /* GD32F10X_CL */
+    RCU_FLAG_LXTALSTB      = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U),          /*!< LXTAL stabilization flags */
+    RCU_FLAG_IRC40KSTB     = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U),         /*!< IRC40K stabilization flags */
+    /* reset source flags */
+    RCU_FLAG_EPRST         = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U),        /*!< external PIN reset flags */
+    RCU_FLAG_PORRST        = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U),        /*!< power reset flags */
+    RCU_FLAG_SWRST         = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U),        /*!< software reset flags */
+    RCU_FLAG_FWDGTRST      = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U),        /*!< FWDGT reset flags */
+    RCU_FLAG_WWDGTRST      = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U),        /*!< WWDGT reset flags */
+    RCU_FLAG_LPRST         = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U),        /*!< low-power reset flags */
+}rcu_flag_enum;
+
+/* clock stabilization and ckm interrupt flags */
+typedef enum
+{
+    RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U),            /*!< IRC40K stabilization interrupt flag */
+    RCU_INT_FLAG_LXTALSTB  = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U),            /*!< LXTAL stabilization interrupt flag */
+    RCU_INT_FLAG_IRC8MSTB  = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U),            /*!< IRC8M stabilization interrupt flag */
+    RCU_INT_FLAG_HXTALSTB  = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U),            /*!< HXTAL stabilization interrupt flag */
+    RCU_INT_FLAG_PLLSTB    = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U),            /*!< PLL stabilization interrupt flag */
+#ifdef GD32F10X_CL
+    RCU_INT_FLAG_PLL1STB   = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U),            /*!< PLL1 stabilization interrupt flag */
+    RCU_INT_FLAG_PLL2STB   = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U),            /*!< PLL2 stabilization interrupt flag */
+#endif /* GD32F10X_CL */
+    RCU_INT_FLAG_CKM       = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U),            /*!< HXTAL clock stuck interrupt flag */
+}rcu_int_flag_enum;
+
+/* clock stabilization and stuck interrupt flags clear */
+typedef enum
+{
+    RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U),       /*!< IRC40K stabilization interrupt flags clear */
+    RCU_INT_FLAG_LXTALSTB_CLR  = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U),       /*!< LXTAL stabilization interrupt flags clear */
+    RCU_INT_FLAG_IRC8MSTB_CLR  = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U),       /*!< IRC8M stabilization interrupt flags clear */
+    RCU_INT_FLAG_HXTALSTB_CLR  = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U),       /*!< HXTAL stabilization interrupt flags clear */
+    RCU_INT_FLAG_PLLSTB_CLR    = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U),       /*!< PLL stabilization interrupt flags clear */
+#ifdef GD32F10X_CL
+    RCU_INT_FLAG_PLL1STB_CLR   = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U),       /*!< PLL1 stabilization interrupt flags clear */
+    RCU_INT_FLAG_PLL2STB_CLR   = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U),       /*!< PLL2 stabilization interrupt flags clear */
+#endif /* GD32F10X_CL */
+    RCU_INT_FLAG_CKM_CLR       = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U),       /*!< CKM interrupt flags clear */
+}rcu_int_flag_clear_enum;
+
+/* clock stabilization interrupt enable or disable */
+typedef enum
+{
+    RCU_INT_IRC40KSTB       = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U),           /*!< IRC40K stabilization interrupt */
+    RCU_INT_LXTALSTB        = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U),           /*!< LXTAL stabilization interrupt */
+    RCU_INT_IRC8MSTB        = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U),          /*!< IRC8M stabilization interrupt */
+    RCU_INT_HXTALSTB        = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U),          /*!< HXTAL stabilization interrupt */
+    RCU_INT_PLLSTB          = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U),          /*!< PLL stabilization interrupt */
+#ifdef GD32F10X_CL
+    RCU_INT_PLL1STB         = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U),          /*!< PLL1 stabilization interrupt */
+    RCU_INT_PLL2STB         = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U),          /*!< PLL2 stabilization interrupt */
+#endif /* GD32F10X_CL */
+}rcu_int_enum;
+
+/* oscillator types */
+typedef enum
+{
+    RCU_HXTAL      = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U),                   /*!< HXTAL */
+    RCU_LXTAL      = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U),                  /*!< LXTAL */
+    RCU_IRC8M      = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U),                    /*!< IRC8M */
+    RCU_IRC40K     = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U),                 /*!< IRC40K */
+    RCU_PLL_CK     = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U),                   /*!< PLL */
+#ifdef GD32F10X_CL
+    RCU_PLL1_CK    = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U),                   /*!< PLL1 */
+    RCU_PLL2_CK    = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U),                   /*!< PLL2 */
+#endif /* GD32F10X_CL */
+}rcu_osci_type_enum;
+
+/* rcu clock frequency */
+typedef enum
+{
+    CK_SYS      = 0,                                                        /*!< system clock */
+    CK_AHB,                                                                 /*!< AHB clock */
+    CK_APB1,                                                                /*!< APB1 clock */
+    CK_APB2,                                                                /*!< APB2 clock */
+}rcu_clock_freq_enum;
+
+/* RCU_CFG0 register bit define */
+/* system clock source select */
+#define CFG0_SCS(regval)                (BITS(0,1) & ((uint32_t)(regval) << 0))
+#define RCU_CKSYSSRC_IRC8M              CFG0_SCS(0)                         /*!< system clock source select IRC8M */
+#define RCU_CKSYSSRC_HXTAL              CFG0_SCS(1)                         /*!< system clock source select HXTAL */
+#define RCU_CKSYSSRC_PLL                CFG0_SCS(2)                         /*!< system clock source select PLL */
+
+/* system clock source select status */
+#define CFG0_SCSS(regval)               (BITS(2,3) & ((uint32_t)(regval) << 2))
+#define RCU_SCSS_IRC8M                  CFG0_SCSS(0)                        /*!< system clock source select IRC8M */
+#define RCU_SCSS_HXTAL                  CFG0_SCSS(1)                        /*!< system clock source select HXTAL */
+#define RCU_SCSS_PLL                    CFG0_SCSS(2)                        /*!< system clock source select PLLP */
+
+/* AHB prescaler selection */
+#define CFG0_AHBPSC(regval)             (BITS(4,7) & ((uint32_t)(regval) << 4))
+#define RCU_AHB_CKSYS_DIV1              CFG0_AHBPSC(0)                      /*!< AHB prescaler select CK_SYS */
+#define RCU_AHB_CKSYS_DIV2              CFG0_AHBPSC(8)                      /*!< AHB prescaler select CK_SYS/2 */
+#define RCU_AHB_CKSYS_DIV4              CFG0_AHBPSC(9)                      /*!< AHB prescaler select CK_SYS/4 */
+#define RCU_AHB_CKSYS_DIV8              CFG0_AHBPSC(10)                     /*!< AHB prescaler select CK_SYS/8 */
+#define RCU_AHB_CKSYS_DIV16             CFG0_AHBPSC(11)                     /*!< AHB prescaler select CK_SYS/16 */
+#define RCU_AHB_CKSYS_DIV64             CFG0_AHBPSC(12)                     /*!< AHB prescaler select CK_SYS/64 */
+#define RCU_AHB_CKSYS_DIV128            CFG0_AHBPSC(13)                     /*!< AHB prescaler select CK_SYS/128 */
+#define RCU_AHB_CKSYS_DIV256            CFG0_AHBPSC(14)                     /*!< AHB prescaler select CK_SYS/256 */
+#define RCU_AHB_CKSYS_DIV512            CFG0_AHBPSC(15)                     /*!< AHB prescaler select CK_SYS/512 */
+
+/* APB1 prescaler selection */
+#define CFG0_APB1PSC(regval)            (BITS(8,10) & ((uint32_t)(regval) << 8))
+#define RCU_APB1_CKAHB_DIV1             CFG0_APB1PSC(0)                     /*!< APB1 prescaler select CK_AHB */
+#define RCU_APB1_CKAHB_DIV2             CFG0_APB1PSC(4)                     /*!< APB1 prescaler select CK_AHB/2 */
+#define RCU_APB1_CKAHB_DIV4             CFG0_APB1PSC(5)                     /*!< APB1 prescaler select CK_AHB/4 */
+#define RCU_APB1_CKAHB_DIV8             CFG0_APB1PSC(6)                     /*!< APB1 prescaler select CK_AHB/8 */
+#define RCU_APB1_CKAHB_DIV16            CFG0_APB1PSC(7)                     /*!< APB1 prescaler select CK_AHB/16 */
+
+/* APB2 prescaler selection */
+#define CFG0_APB2PSC(regval)            (BITS(11,13) & ((uint32_t)(regval) << 11))
+#define RCU_APB2_CKAHB_DIV1             CFG0_APB2PSC(0)                     /*!< APB2 prescaler select CK_AHB */
+#define RCU_APB2_CKAHB_DIV2             CFG0_APB2PSC(4)                     /*!< APB2 prescaler select CK_AHB/2 */
+#define RCU_APB2_CKAHB_DIV4             CFG0_APB2PSC(5)                     /*!< APB2 prescaler select CK_AHB/4 */
+#define RCU_APB2_CKAHB_DIV8             CFG0_APB2PSC(6)                     /*!< APB2 prescaler select CK_AHB/8 */
+#define RCU_APB2_CKAHB_DIV16            CFG0_APB2PSC(7)                     /*!< APB2 prescaler select CK_AHB/16 */
+
+/* ADC prescaler select */
+#define RCU_CKADC_CKAPB2_DIV2           ((uint32_t)0x00000000U)             /*!< ADC prescaler select CK_APB2/2 */
+#define RCU_CKADC_CKAPB2_DIV4           ((uint32_t)0x00000001U)             /*!< ADC prescaler select CK_APB2/4 */
+#define RCU_CKADC_CKAPB2_DIV6           ((uint32_t)0x00000002U)             /*!< ADC prescaler select CK_APB2/6 */
+#define RCU_CKADC_CKAPB2_DIV8           ((uint32_t)0x00000003U)             /*!< ADC prescaler select CK_APB2/8 */
+#define RCU_CKADC_CKAPB2_DIV12          ((uint32_t)0x00000005U)             /*!< ADC prescaler select CK_APB2/12 */
+#define RCU_CKADC_CKAPB2_DIV16          ((uint32_t)0x00000007U)             /*!< ADC prescaler select CK_APB2/16 */
+
+/* PLL clock source selection */
+#define RCU_PLLSRC_IRC8M_DIV2           ((uint32_t)0x00000000U)             /*!< IRC8M/2 clock selected as source clock of PLL */
+#define RCU_PLLSRC_HXTAL                RCU_CFG0_PLLSEL                     /*!< HXTAL clock selected as source clock of PLL */
+
+/* PLL clock multiplication factor */
+#define PLLMF_4                         RCU_CFG0_PLLMF_4                    /* bit 4 of PLLMF */
+
+#define CFG0_PLLMF(regval)              (BITS(18,21) & ((uint32_t)(regval) << 18))
+#define RCU_PLL_MUL2                    CFG0_PLLMF(0)                       /*!< PLL source clock multiply by 2 */
+#define RCU_PLL_MUL3                    CFG0_PLLMF(1)                       /*!< PLL source clock multiply by 3 */
+#define RCU_PLL_MUL4                    CFG0_PLLMF(2)                       /*!< PLL source clock multiply by 4 */
+#define RCU_PLL_MUL5                    CFG0_PLLMF(3)                       /*!< PLL source clock multiply by 5 */
+#define RCU_PLL_MUL6                    CFG0_PLLMF(4)                       /*!< PLL source clock multiply by 6 */
+#define RCU_PLL_MUL7                    CFG0_PLLMF(5)                       /*!< PLL source clock multiply by 7 */
+#define RCU_PLL_MUL8                    CFG0_PLLMF(6)                       /*!< PLL source clock multiply by 8 */
+#define RCU_PLL_MUL9                    CFG0_PLLMF(7)                       /*!< PLL source clock multiply by 9 */
+#define RCU_PLL_MUL10                   CFG0_PLLMF(8)                       /*!< PLL source clock multiply by 10 */
+#define RCU_PLL_MUL11                   CFG0_PLLMF(9)                       /*!< PLL source clock multiply by 11 */
+#define RCU_PLL_MUL12                   CFG0_PLLMF(10)                      /*!< PLL source clock multiply by 12 */
+#define RCU_PLL_MUL13                   CFG0_PLLMF(11)                      /*!< PLL source clock multiply by 13 */
+#define RCU_PLL_MUL14                   CFG0_PLLMF(12)                      /*!< PLL source clock multiply by 14 */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+#define RCU_PLL_MUL15                   CFG0_PLLMF(13)                      /*!< PLL source clock multiply by 15 */
+#elif defined(GD32F10X_CL)
+#define RCU_PLL_MUL6_5                  CFG0_PLLMF(13)                      /*!< PLL source clock multiply by 6.5 */
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+#define RCU_PLL_MUL16                   CFG0_PLLMF(14)                      /*!< PLL source clock multiply by 16 */
+#define RCU_PLL_MUL17                   (PLLMF_4 | CFG0_PLLMF(0))           /*!< PLL source clock multiply by 17 */
+#define RCU_PLL_MUL18                   (PLLMF_4 | CFG0_PLLMF(1))           /*!< PLL source clock multiply by 18 */
+#define RCU_PLL_MUL19                   (PLLMF_4 | CFG0_PLLMF(2))           /*!< PLL source clock multiply by 19 */
+#define RCU_PLL_MUL20                   (PLLMF_4 | CFG0_PLLMF(3))           /*!< PLL source clock multiply by 20 */
+#define RCU_PLL_MUL21                   (PLLMF_4 | CFG0_PLLMF(4))           /*!< PLL source clock multiply by 21 */
+#define RCU_PLL_MUL22                   (PLLMF_4 | CFG0_PLLMF(5))           /*!< PLL source clock multiply by 22 */
+#define RCU_PLL_MUL23                   (PLLMF_4 | CFG0_PLLMF(6))           /*!< PLL source clock multiply by 23 */
+#define RCU_PLL_MUL24                   (PLLMF_4 | CFG0_PLLMF(7))           /*!< PLL source clock multiply by 24 */
+#define RCU_PLL_MUL25                   (PLLMF_4 | CFG0_PLLMF(8))           /*!< PLL source clock multiply by 25 */
+#define RCU_PLL_MUL26                   (PLLMF_4 | CFG0_PLLMF(9))           /*!< PLL source clock multiply by 26 */
+#define RCU_PLL_MUL27                   (PLLMF_4 | CFG0_PLLMF(10))          /*!< PLL source clock multiply by 27 */
+#define RCU_PLL_MUL28                   (PLLMF_4 | CFG0_PLLMF(11))          /*!< PLL source clock multiply by 28 */
+#define RCU_PLL_MUL29                   (PLLMF_4 | CFG0_PLLMF(12))          /*!< PLL source clock multiply by 29 */
+#define RCU_PLL_MUL30                   (PLLMF_4 | CFG0_PLLMF(13))          /*!< PLL source clock multiply by 30 */
+#define RCU_PLL_MUL31                   (PLLMF_4 | CFG0_PLLMF(14))          /*!< PLL source clock multiply by 31 */
+#define RCU_PLL_MUL32                   (PLLMF_4 | CFG0_PLLMF(15))          /*!< PLL source clock multiply by 32 */
+
+/* USBD/USBFS prescaler select */
+#define CFG0_USBPSC(regval)             (BITS(22,23) & ((uint32_t)(regval) << 22))
+#define RCU_CKUSB_CKPLL_DIV1_5          CFG0_USBPSC(0)                      /*!< USBD/USBFS prescaler select CK_PLL/1.5 */
+#define RCU_CKUSB_CKPLL_DIV1            CFG0_USBPSC(1)                      /*!< USBD/USBFS prescaler select CK_PLL/1 */
+#define RCU_CKUSB_CKPLL_DIV2_5          CFG0_USBPSC(2)                      /*!< USBD/USBFS prescaler select CK_PLL/2.5 */
+#define RCU_CKUSB_CKPLL_DIV2            CFG0_USBPSC(3)                      /*!< USBD/USBFS prescaler select CK_PLL/2 */
+
+/* CKOUT0 clock source selection */
+#define CFG0_CKOUT0SEL(regval)          (BITS(24,27) & ((uint32_t)(regval) << 24))
+#define RCU_CKOUT0SRC_NONE              CFG0_CKOUT0SEL(0)                   /*!< no clock selected */
+#define RCU_CKOUT0SRC_CKSYS             CFG0_CKOUT0SEL(4)                   /*!< system clock selected */
+#define RCU_CKOUT0SRC_IRC8M             CFG0_CKOUT0SEL(5)                   /*!< internal 8M RC oscillator clock selected */
+#define RCU_CKOUT0SRC_HXTAL             CFG0_CKOUT0SEL(6)                   /*!< high speed crystal oscillator clock (HXTAL) selected */
+#define RCU_CKOUT0SRC_CKPLL_DIV2        CFG0_CKOUT0SEL(7)                   /*!< CK_PLL/2 clock selected */
+#ifdef GD32F10X_CL
+#define RCU_CKOUT0SRC_CKPLL1            CFG0_CKOUT0SEL(8)                   /*!< CK_PLL1 clock selected */
+#define RCU_CKOUT0SRC_CKPLL2_DIV2       CFG0_CKOUT0SEL(9)                   /*!< CK_PLL2/2 clock selected */
+#define RCU_CKOUT0SRC_EXT1              CFG0_CKOUT0SEL(10)                  /*!< EXT1 selected, to provide the external clock for ENET */
+#define RCU_CKOUT0SRC_CKPLL2            CFG0_CKOUT0SEL(11)                  /*!< CK_PLL2 clock selected */
+#endif /* GD32F10X_CL */
+
+/* RTC clock entry selection */
+#define BDCTL_RTCSRC(regval)            (BITS(8,9) & ((uint32_t)(regval) << 8))
+#define RCU_RTCSRC_NONE                 BDCTL_RTCSRC(0)                     /*!< no clock selected */
+#define RCU_RTCSRC_LXTAL                BDCTL_RTCSRC(1)                     /*!< RTC source clock select LXTAL  */
+#define RCU_RTCSRC_IRC40K               BDCTL_RTCSRC(2)                     /*!< RTC source clock select IRC40K */
+#define RCU_RTCSRC_HXTAL_DIV_128        BDCTL_RTCSRC(3)                     /*!< RTC source clock select HXTAL/128 */
+
+/* PREDV0 division factor */
+#define CFG1_PREDV0(regval)             (BITS(0,3) & ((uint32_t)(regval) << 0))
+#define RCU_PREDV0_DIV1                CFG1_PREDV0(0)                       /*!< PREDV0 input source clock not divided */
+#define RCU_PREDV0_DIV2                CFG1_PREDV0(1)                       /*!< PREDV0 input source clock divided by 2 */
+#define RCU_PREDV0_DIV3                CFG1_PREDV0(2)                       /*!< PREDV0 input source clock divided by 3 */
+#define RCU_PREDV0_DIV4                CFG1_PREDV0(3)                       /*!< PREDV0 input source clock divided by 4 */
+#define RCU_PREDV0_DIV5                CFG1_PREDV0(4)                       /*!< PREDV0 input source clock divided by 5 */
+#define RCU_PREDV0_DIV6                CFG1_PREDV0(5)                       /*!< PREDV0 input source clock divided by 6 */
+#define RCU_PREDV0_DIV7                CFG1_PREDV0(6)                       /*!< PREDV0 input source clock divided by 7 */
+#define RCU_PREDV0_DIV8                CFG1_PREDV0(7)                       /*!< PREDV0 input source clock divided by 8 */
+#define RCU_PREDV0_DIV9                CFG1_PREDV0(8)                       /*!< PREDV0 input source clock divided by 9 */
+#define RCU_PREDV0_DIV10               CFG1_PREDV0(9)                       /*!< PREDV0 input source clock divided by 10 */
+#define RCU_PREDV0_DIV11               CFG1_PREDV0(10)                      /*!< PREDV0 input source clock divided by 11 */
+#define RCU_PREDV0_DIV12               CFG1_PREDV0(11)                      /*!< PREDV0 input source clock divided by 12 */
+#define RCU_PREDV0_DIV13               CFG1_PREDV0(12)                      /*!< PREDV0 input source clock divided by 13 */
+#define RCU_PREDV0_DIV14               CFG1_PREDV0(13)                      /*!< PREDV0 input source clock divided by 14 */
+#define RCU_PREDV0_DIV15               CFG1_PREDV0(14)                      /*!< PREDV0 input source clock divided by 15 */
+#define RCU_PREDV0_DIV16               CFG1_PREDV0(15)                      /*!< PREDV0 input source clock divided by 16 */
+
+/* PREDV1 division factor */
+#define CFG1_PREDV1(regval)             (BITS(4,7) & ((uint32_t)(regval) << 4))
+#define RCU_PREDV1_DIV1                CFG1_PREDV1(0)                       /*!< PREDV1 input source clock not divided */
+#define RCU_PREDV1_DIV2                CFG1_PREDV1(1)                       /*!< PREDV1 input source clock divided by 2 */
+#define RCU_PREDV1_DIV3                CFG1_PREDV1(2)                       /*!< PREDV1 input source clock divided by 3 */
+#define RCU_PREDV1_DIV4                CFG1_PREDV1(3)                       /*!< PREDV1 input source clock divided by 4 */
+#define RCU_PREDV1_DIV5                CFG1_PREDV1(4)                       /*!< PREDV1 input source clock divided by 5 */
+#define RCU_PREDV1_DIV6                CFG1_PREDV1(5)                       /*!< PREDV1 input source clock divided by 6 */
+#define RCU_PREDV1_DIV7                CFG1_PREDV1(6)                       /*!< PREDV1 input source clock divided by 7 */
+#define RCU_PREDV1_DIV8                CFG1_PREDV1(7)                       /*!< PREDV1 input source clock divided by 8 */
+#define RCU_PREDV1_DIV9                CFG1_PREDV1(8)                       /*!< PREDV1 input source clock divided by 9 */
+#define RCU_PREDV1_DIV10               CFG1_PREDV1(9)                       /*!< PREDV1 input source clock divided by 10 */
+#define RCU_PREDV1_DIV11               CFG1_PREDV1(10)                      /*!< PREDV1 input source clock divided by 11 */
+#define RCU_PREDV1_DIV12               CFG1_PREDV1(11)                      /*!< PREDV1 input source clock divided by 12 */
+#define RCU_PREDV1_DIV13               CFG1_PREDV1(12)                      /*!< PREDV1 input source clock divided by 13 */
+#define RCU_PREDV1_DIV14               CFG1_PREDV1(13)                      /*!< PREDV1 input source clock divided by 14 */
+#define RCU_PREDV1_DIV15               CFG1_PREDV1(14)                      /*!< PREDV1 input source clock divided by 15 */
+#define RCU_PREDV1_DIV16               CFG1_PREDV1(15)                      /*!< PREDV1 input source clock divided by 16 */
+
+/* PLL1 clock multiplication factor */
+#define CFG1_PLL1MF(regval)             (BITS(8,11) & ((uint32_t)(regval) << 8))
+#define RCU_PLL1_MUL8                   CFG1_PLL1MF(6)                      /*!< PLL1 source clock multiply by 8 */
+#define RCU_PLL1_MUL9                   CFG1_PLL1MF(7)                      /*!< PLL1 source clock multiply by 9 */
+#define RCU_PLL1_MUL10                  CFG1_PLL1MF(8)                      /*!< PLL1 source clock multiply by 10 */
+#define RCU_PLL1_MUL11                  CFG1_PLL1MF(9)                      /*!< PLL1 source clock multiply by 11 */
+#define RCU_PLL1_MUL12                  CFG1_PLL1MF(10)                     /*!< PLL1 source clock multiply by 12 */
+#define RCU_PLL1_MUL13                  CFG1_PLL1MF(11)                     /*!< PLL1 source clock multiply by 13 */
+#define RCU_PLL1_MUL14                  CFG1_PLL1MF(12)                     /*!< PLL1 source clock multiply by 14 */
+#define RCU_PLL1_MUL15                  CFG1_PLL1MF(13)                     /*!< PLL1 source clock multiply by 15 */
+#define RCU_PLL1_MUL16                  CFG1_PLL1MF(14)                     /*!< PLL1 source clock multiply by 16 */
+#define RCU_PLL1_MUL20                  CFG1_PLL1MF(15)                     /*!< PLL1 source clock multiply by 20 */
+
+/* PLL2 clock multiplication factor */
+#define CFG1_PLL2MF(regval)             (BITS(12,15) & ((uint32_t)(regval) << 12))
+#define RCU_PLL2_MUL8                   CFG1_PLL2MF(6)                      /*!< PLL2 source clock multiply by 8 */
+#define RCU_PLL2_MUL9                   CFG1_PLL2MF(7)                      /*!< PLL2 source clock multiply by 9 */
+#define RCU_PLL2_MUL10                  CFG1_PLL2MF(8)                      /*!< PLL2 source clock multiply by 10 */
+#define RCU_PLL2_MUL11                  CFG1_PLL2MF(9)                      /*!< PLL2 source clock multiply by 11 */
+#define RCU_PLL2_MUL12                  CFG1_PLL2MF(10)                     /*!< PLL2 source clock multiply by 12 */
+#define RCU_PLL2_MUL13                  CFG1_PLL2MF(11)                     /*!< PLL2 source clock multiply by 13 */
+#define RCU_PLL2_MUL14                  CFG1_PLL2MF(12)                     /*!< PLL2 source clock multiply by 14 */
+#define RCU_PLL2_MUL15                  CFG1_PLL2MF(13)                     /*!< PLL2 source clock multiply by 15 */
+#define RCU_PLL2_MUL16                  CFG1_PLL2MF(14)                     /*!< PLL2 source clock multiply by 16 */
+#define RCU_PLL2_MUL20                  CFG1_PLL2MF(15)                     /*!< PLL2 source clock multiply by 20 */
+
+#ifdef GD32F10X_CL
+/* PREDV0 input clock source selection */
+#define RCU_PREDV0SRC_HXTAL             ((uint32_t)0x00000000U)             /*!< HXTAL selected as PREDV0 input source clock */
+#define RCU_PREDV0SRC_CKPLL1            RCU_CFG1_PREDV0SEL                  /*!< CK_PLL1 selected as PREDV0 input source clock */
+
+/* I2S1 clock source selection */
+#define RCU_I2S1SRC_CKSYS               ((uint32_t)0x00000000U)             /*!< system clock selected as I2S1 source clock */
+#define RCU_I2S1SRC_CKPLL2_MUL2         RCU_CFG1_I2S1SEL                    /*!< (CK_PLL2 x 2) selected as I2S1 source clock */
+
+/* I2S2 clock source selection */
+#define RCU_I2S2SRC_CKSYS               ((uint32_t)0x00000000U)             /*!< system clock selected as I2S2 source clock */
+#define RCU_I2S2SRC_CKPLL2_MUL2         RCU_CFG1_I2S2SEL                    /*!< (CK_PLL2 x 2) selected as I2S2 source clock */
+#endif /* GD32F10X_CL */
+
+/* deep-sleep mode voltage */
+#define DSV_DSLPVS(regval)              (BITS(0,2) & ((uint32_t)(regval) << 0))
+#define RCU_DEEPSLEEP_V_1_2             DSV_DSLPVS(0)                       /*!< core voltage is 1.2V in deep-sleep mode */
+#define RCU_DEEPSLEEP_V_1_1             DSV_DSLPVS(1)                       /*!< core voltage is 1.1V in deep-sleep mode */
+#define RCU_DEEPSLEEP_V_1_0             DSV_DSLPVS(2)                       /*!< core voltage is 1.0V in deep-sleep mode */
+#define RCU_DEEPSLEEP_V_0_9             DSV_DSLPVS(3)                       /*!< core voltage is 0.9V in deep-sleep mode */
+
+/* function declarations */
+/* initialization, peripheral clock enable/disable functions */
+/* deinitialize the RCU */
+void rcu_deinit(void);
+/* enable the peripherals clock */
+void rcu_periph_clock_enable(rcu_periph_enum periph);
+/* disable the peripherals clock */
+void rcu_periph_clock_disable(rcu_periph_enum periph);
+/* enable the peripherals clock when sleep mode */
+void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph);
+/* disable the peripherals clock when sleep mode */
+void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph);
+/* reset the peripherals */
+void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset);
+/* disable reset the peripheral */
+void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset);
+/* reset the BKP domain */
+void rcu_bkp_reset_enable(void);
+/* disable the BKP domain reset */
+void rcu_bkp_reset_disable(void);
+
+/* clock configuration functions */
+/* configure the system clock source */
+void rcu_system_clock_source_config(uint32_t ck_sys);
+/* get the system clock source */
+uint32_t rcu_system_clock_source_get(void);
+/* configure the AHB prescaler selection */
+void rcu_ahb_clock_config(uint32_t ck_ahb);
+/* configure the APB1 prescaler selection */
+void rcu_apb1_clock_config(uint32_t ck_apb1);
+/* configure the APB2 prescaler selection */
+void rcu_apb2_clock_config(uint32_t ck_apb2);
+/* configure the CK_OUT0 clock source and divider */
+void rcu_ckout0_config(uint32_t ckout0_src);
+/* configure the PLL clock source selection and PLL multiply factor */
+void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul);
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+/* configure the PREDV0 division factor and clock source */
+void rcu_predv0_config(uint32_t predv0_div);
+#elif defined(GD32F10X_CL)
+/* configure the PREDV0 division factor and clock source */
+void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div);
+/* configure the PREDV1 division factor */
+void rcu_predv1_config(uint32_t predv1_div);
+/* configure the PLL1 clock */
+void rcu_pll1_config(uint32_t pll_mul);
+/* configure the PLL2 clock */
+void rcu_pll2_config(uint32_t pll_mul);
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/* peripheral clock configuration functions */
+/* configure the ADC division factor */
+void rcu_adc_clock_config(uint32_t adc_psc);
+/* configure the USBD/USBFS prescaler factor */
+void rcu_usb_clock_config(uint32_t usb_psc);
+/* configure the RTC clock source selection */
+void rcu_rtc_clock_config(uint32_t rtc_clock_source);
+#ifdef GD32F10X_CL
+/* configure the I2S1 clock source selection */
+void rcu_i2s1_clock_config(uint32_t i2s_clock_source);
+/* configure the I2S2 clock source selection */
+void rcu_i2s2_clock_config(uint32_t i2s_clock_source);
+#endif /* GD32F10X_CL */
+
+/* interrupt & flag functions */
+/* get the clock stabilization and periphral reset flags */
+FlagStatus rcu_flag_get(rcu_flag_enum flag);
+/* clear the reset flag */
+void rcu_all_reset_flag_clear(void);
+/* get the clock stabilization interrupt and ckm flags */
+FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag);
+/* clear the interrupt flags */
+void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear);
+/* enable the stabilization interrupt */
+void rcu_interrupt_enable(rcu_int_enum stab_int);
+/* disable the stabilization interrupt */
+void rcu_interrupt_disable(rcu_int_enum stab_int);
+
+/* oscillator configuration functions */
+/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */
+ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci);
+/* turn on the oscillator */
+void rcu_osci_on(rcu_osci_type_enum osci);
+/* turn off the oscillator */
+void rcu_osci_off(rcu_osci_type_enum osci);
+/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */
+void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci);
+/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */
+void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci);
+/* enable the HXTAL clock monitor */
+void rcu_hxtal_clock_monitor_enable(void);
+/* disable the HXTAL clock monitor */
+void rcu_hxtal_clock_monitor_disable(void);
+
+/* set the IRC8M adjust value */
+void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval);
+/* set the deep sleep mode voltage */
+void rcu_deepsleep_voltage_set(uint32_t dsvol);
+
+/* get the system clock, bus and peripheral clock frequency */
+uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock);
+
+#endif /* GD32F10X_RCU_H */

+ 151 - 0
Library/Include/gd32f10x_rtc.h

@@ -0,0 +1,151 @@
+/*!
+    \file    gd32f10x_rtc.h
+    \brief   definitions for the RTC
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_RTC_H
+#define GD32F10X_RTC_H
+
+#include "gd32f10x.h"
+
+/* RTC definitions */
+#define RTC                          RTC_BASE
+
+/* registers definitions */
+#define RTC_INTEN                    REG32(RTC + 0x00U)      /*!< interrupt enable register */
+#define RTC_CTL                      REG32(RTC + 0x04U)      /*!< control register */
+#define RTC_PSCH                     REG32(RTC + 0x08U)      /*!< prescaler high register */
+#define RTC_PSCL                     REG32(RTC + 0x0CU)      /*!< prescaler low register */
+#define RTC_DIVH                     REG32(RTC + 0x10U)      /*!< divider high register */
+#define RTC_DIVL                     REG32(RTC + 0x14U)      /*!< divider low register */
+#define RTC_CNTH                     REG32(RTC + 0x18U)      /*!< counter high register */
+#define RTC_CNTL                     REG32(RTC + 0x1CU)      /*!< counter low register */
+#define RTC_ALRMH                    REG32(RTC + 0x20U)      /*!< alarm high register */
+#define RTC_ALRML                    REG32(RTC + 0x24U)      /*!< alarm low register */
+
+/* bits definitions */
+/* RTC_INTEN */
+#define RTC_INTEN_SCIE               BIT(0)                   /*!< second interrupt enable */
+#define RTC_INTEN_ALRMIE             BIT(1)                   /*!< alarm interrupt enable */
+#define RTC_INTEN_OVIE               BIT(2)                   /*!< overflow interrupt enable */
+
+/* RTC_CTL */
+#define RTC_CTL_SCIF                 BIT(0)                   /*!< second interrupt flag */
+#define RTC_CTL_ALRMIF               BIT(1)                   /*!< alarm interrupt flag */
+#define RTC_CTL_OVIF                 BIT(2)                   /*!< overflow interrupt flag */
+#define RTC_CTL_RSYNF                BIT(3)                   /*!< registers synchronized flag */
+#define RTC_CTL_CMF                  BIT(4)                   /*!< configuration mode flag */
+#define RTC_CTL_LWOFF                BIT(5)                   /*!< last write operation finished flag */
+
+/* RTC_PSCH */
+#define RTC_PSCH_PSC                 BITS(0,3)                /*!< prescaler high value */
+
+/* RTC_PSCL */
+#define RTC_PSCL_PSC                 BITS(0,15)               /*!< prescaler low value */
+
+/* RTC_DIVH */
+#define RTC_DIVH_DIV                 BITS(0,3)                /*!< divider high value */
+
+/* RTC_DIVL */
+#define RTC_DIVL_DIV                 BITS(0,15)               /*!< divider low value */
+
+/* RTC_CNTH */
+#define RTC_CNTH_CNT                 BITS(0,15)               /*!< counter high value */
+
+/* RTC_CNTL */
+#define RTC_CNTL_CNT                 BITS(0,15)               /*!< counter low value */
+
+/* RTC_ALRMH */
+#define RTC_ALRMH_ALRM               BITS(0,15)               /*!< alarm high value */
+
+/* RTC_ALRML */
+#define RTC_ALRML_ALRM               BITS(0,15)               /*!< alarm low value */
+
+/* constants definitions */
+/* RTC interrupt enable or disable definitions */
+#define RTC_INT_SECOND               RTC_INTEN_SCIE           /*!< second interrupt enable */
+#define RTC_INT_ALARM                RTC_INTEN_ALRMIE         /*!< alarm interrupt enable */
+#define RTC_INT_OVERFLOW             RTC_INTEN_OVIE           /*!< overflow interrupt enable */
+
+/* RTC interrupt flag definitions */
+#define RTC_INT_FLAG_SECOND          RTC_CTL_SCIF             /*!< second interrupt flag */
+#define RTC_INT_FLAG_ALARM           RTC_CTL_ALRMIF           /*!< alarm interrupt flag */
+#define RTC_INT_FLAG_OVERFLOW        RTC_CTL_OVIF             /*!< overflow interrupt flag */
+
+/* RTC flag definitions */
+#define RTC_FLAG_SECOND              RTC_CTL_SCIF             /*!< second interrupt flag */
+#define RTC_FLAG_ALARM               RTC_CTL_ALRMIF           /*!< alarm interrupt flag */
+#define RTC_FLAG_OVERFLOW            RTC_CTL_OVIF             /*!< overflow interrupt flag */
+#define RTC_FLAG_RSYN                RTC_CTL_RSYNF            /*!< registers synchronized flag */
+#define RTC_FLAG_LWOF                RTC_CTL_LWOFF            /*!< last write operation finished flag */
+
+/* function declarations */
+/* initialization functions */
+/* enter RTC configuration mode */
+void rtc_configuration_mode_enter(void);
+/* exit RTC configuration mode */
+void rtc_configuration_mode_exit(void);
+/* set RTC counter value */
+void rtc_counter_set(uint32_t cnt);
+/* set RTC prescaler value */
+void rtc_prescaler_set(uint32_t psc);
+
+/* operation functions */
+/* wait RTC last write operation finished flag set */
+void rtc_lwoff_wait(void);
+/* wait RTC registers synchronized flag set */
+void rtc_register_sync_wait(void);
+/* set RTC alarm value */
+void rtc_alarm_config(uint32_t alarm);
+/* get RTC counter value */
+uint32_t rtc_counter_get(void);
+/* get RTC divider value */
+uint32_t rtc_divider_get(void);
+
+/* flag & interrupt functions */
+/* get RTC flag status */
+FlagStatus rtc_flag_get(uint32_t flag);
+/* clear RTC flag status */
+void rtc_flag_clear(uint32_t flag);
+/* get RTC interrupt flag status */
+FlagStatus rtc_interrupt_flag_get(uint32_t flag);
+/* clear RTC interrupt flag status */
+void rtc_interrupt_flag_clear(uint32_t flag);
+/* enable RTC interrupt */
+void rtc_interrupt_enable(uint32_t interrupt);
+/* disable RTC interrupt */
+void rtc_interrupt_disable(uint32_t interrupt);
+
+#endif /* GD32F10X_RTC_H */

+ 433 - 0
Library/Include/gd32f10x_sdio.h

@@ -0,0 +1,433 @@
+/*!
+    \file    gd32f10x_sdio.h
+    \brief   definitions for the SDIO 
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_SDIO_H
+#define GD32F10X_SDIO_H
+
+#include "gd32f10x.h"
+
+/* SDIO definitions */
+#define SDIO                            SDIO_BASE
+
+/* registers definitions */
+#define SDIO_PWRCTL                     REG32(SDIO + 0x00U)    /*!< SDIO power control register */
+#define SDIO_CLKCTL                     REG32(SDIO + 0x04U)    /*!< SDIO clock control register */
+#define SDIO_CMDAGMT                    REG32(SDIO + 0x08U)    /*!< SDIO command argument register */
+#define SDIO_CMDCTL                     REG32(SDIO + 0x0CU)    /*!< SDIO command control register */
+#define SDIO_RSPCMDIDX                  REG32(SDIO + 0x10U)    /*!< SDIO command index response register */
+#define SDIO_RESP0                      REG32(SDIO + 0x14U)    /*!< SDIO response register 0 */
+#define SDIO_RESP1                      REG32(SDIO + 0x18U)    /*!< SDIO response register 1 */
+#define SDIO_RESP2                      REG32(SDIO + 0x1CU)    /*!< SDIO response register 2 */
+#define SDIO_RESP3                      REG32(SDIO + 0x20U)    /*!< SDIO response register 3 */
+#define SDIO_DATATO                     REG32(SDIO + 0x24U)    /*!< SDIO data timeout register */
+#define SDIO_DATALEN                    REG32(SDIO + 0x28U)    /*!< SDIO data length register */
+#define SDIO_DATACTL                    REG32(SDIO + 0x2CU)    /*!< SDIO data control register */
+#define SDIO_DATACNT                    REG32(SDIO + 0x30U)    /*!< SDIO data counter register */
+#define SDIO_STAT                       REG32(SDIO + 0x34U)    /*!< SDIO status register */
+#define SDIO_INTC                       REG32(SDIO + 0x38U)    /*!< SDIO interrupt clear register */
+#define SDIO_INTEN                      REG32(SDIO + 0x3CU)    /*!< SDIO interrupt enable register */
+#define SDIO_FIFOCNT                    REG32(SDIO + 0x48U)    /*!< SDIO FIFO counter register */
+#define SDIO_FIFO                       REG32(SDIO + 0x80U)    /*!< SDIO FIFO data register */
+
+/* bits definitions */
+/* SDIO_PWRCTL */
+#define SDIO_PWRCTL_PWRCTL              BITS(0,1)              /*!< SDIO power control bits */
+
+/* SDIO_CLKCTL */
+#define SDIO_CLKCTL_DIV                 BITS(0,7)              /*!< clock division */
+#define SDIO_CLKCTL_CLKEN               BIT(8)                 /*!< SDIO_CLK clock output enable bit */
+#define SDIO_CLKCTL_CLKPWRSAV           BIT(9)                 /*!< SDIO_CLK clock dynamic switch on/off for power saving */
+#define SDIO_CLKCTL_CLKBYP              BIT(10)                /*!< clock bypass enable bit */
+#define SDIO_CLKCTL_BUSMODE             BITS(11,12)            /*!< SDIO card bus mode control bit */
+#define SDIO_CLKCTL_CLKEDGE             BIT(13)                /*!< SDIO_CLK clock edge selection bit */
+#define SDIO_CLKCTL_HWCLKEN             BIT(14)                /*!< hardware clock control enable bit */
+
+/* SDIO_CMDAGMT */
+#define SDIO_CMDAGMT_CMDAGMT            BITS(0,31)             /*!< SDIO card command argument */
+
+/* SDIO_CMDCTL */
+#define SDIO_CMDCTL_CMDIDX              BITS(0,5)              /*!< command index */
+#define SDIO_CMDCTL_CMDRESP             BITS(6,7)              /*!< command response type bits */
+#define SDIO_CMDCTL_INTWAIT             BIT(8)                 /*!< interrupt wait instead of timeout */
+#define SDIO_CMDCTL_WAITDEND            BIT(9)                 /*!< wait for ends of data transfer */
+#define SDIO_CMDCTL_CSMEN               BIT(10)                /*!< command state machine(CSM) enable bit */
+#define SDIO_CMDCTL_SUSPEND             BIT(11)                /*!< SD I/O suspend command(SD I/O only) */
+#define SDIO_CMDCTL_ENCMDC              BIT(12)                /*!< CMD completion signal enabled (CE-ATA only) */
+#define SDIO_CMDCTL_NINTEN              BIT(13)                /*!< no CE-ATA interrupt (CE-ATA only) */
+#define SDIO_CMDCTL_ATAEN               BIT(14)                /*!< CE-ATA command enable(CE-ATA only) */
+
+/* SDIO_DATATO */
+#define SDIO_DATATO_DATATO              BITS(0,31)             /*!< data timeout period */
+
+/* SDIO_DATALEN */
+#define SDIO_DATALEN_DATALEN            BITS(0,24)             /*!< data transfer length */
+
+/* SDIO_DATACTL */
+#define SDIO_DATACTL_DATAEN             BIT(0)                 /*!< data transfer enabled bit */
+#define SDIO_DATACTL_DATADIR            BIT(1)                 /*!< data transfer direction */
+#define SDIO_DATACTL_TRANSMOD           BIT(2)                 /*!< data transfer mode */
+#define SDIO_DATACTL_DMAEN              BIT(3)                 /*!< DMA enable bit */
+#define SDIO_DATACTL_BLKSZ              BITS(4,7)              /*!< data block size */
+#define SDIO_DATACTL_RWEN               BIT(8)                 /*!< read wait mode enabled(SD I/O only) */
+#define SDIO_DATACTL_RWSTOP             BIT(9)                 /*!< read wait stop(SD I/O only) */
+#define SDIO_DATACTL_RWTYPE             BIT(10)                /*!< read wait type(SD I/O only) */
+#define SDIO_DATACTL_IOEN               BIT(11)                /*!< SD I/O specific function enable(SD I/O only) */
+
+/* SDIO_STAT */
+#define SDIO_STAT_CCRCERR               BIT(0)                 /*!< command response received (CRC check failed) */
+#define SDIO_STAT_DTCRCERR              BIT(1)                 /*!< data block sent/received (CRC check failed) */
+#define SDIO_STAT_CMDTMOUT              BIT(2)                 /*!< command response timeout */
+#define SDIO_STAT_DTTMOUT               BIT(3)                 /*!< data timeout */
+#define SDIO_STAT_TXURE                 BIT(4)                 /*!< transmit FIFO underrun error occurs */
+#define SDIO_STAT_RXORE                 BIT(5)                 /*!< received FIFO overrun error occurs */
+#define SDIO_STAT_CMDRECV               BIT(6)                 /*!< command response received (CRC check passed) */
+#define SDIO_STAT_CMDSEND               BIT(7)                 /*!< command sent (no response required) */
+#define SDIO_STAT_DTEND                 BIT(8)                 /*!< data end (data counter, SDIO_DATACNT, is zero) */
+#define SDIO_STAT_STBITE                BIT(9)                 /*!< start bit error in the bus */
+#define SDIO_STAT_DTBLKEND              BIT(10)                /*!< data block sent/received (CRC check passed) */
+#define SDIO_STAT_CMDRUN                BIT(11)                /*!< command transmission in progress */
+#define SDIO_STAT_TXRUN                 BIT(12)                /*!< data transmission in progress */
+#define SDIO_STAT_RXRUN                 BIT(13)                /*!< data reception in progress */
+#define SDIO_STAT_TFH                   BIT(14)                /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */
+#define SDIO_STAT_RFH                   BIT(15)                /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */
+#define SDIO_STAT_TFF                   BIT(16)                /*!< transmit FIFO is full */
+#define SDIO_STAT_RFF                   BIT(17)                /*!< receive FIFO is full */
+#define SDIO_STAT_TFE                   BIT(18)                /*!< transmit FIFO is empty */
+#define SDIO_STAT_RFE                   BIT(19)                /*!< receive FIFO is empty */
+#define SDIO_STAT_TXDTVAL               BIT(20)                /*!< data is valid in transmit FIFO */
+#define SDIO_STAT_RXDTVAL               BIT(21)                /*!< data is valid in receive FIFO */
+#define SDIO_STAT_SDIOINT               BIT(22)                /*!< SD I/O interrupt received */
+#define SDIO_STAT_ATAEND                BIT(23)                /*!< CE-ATA command completion signal received (only for CMD61) */
+
+/* SDIO_INTC */
+#define SDIO_INTC_CCRCERRC              BIT(0)                 /*!< CCRCERR flag clear bit */
+#define SDIO_INTC_DTCRCERRC             BIT(1)                 /*!< DTCRCERR flag clear bit */
+#define SDIO_INTC_CMDTMOUTC             BIT(2)                 /*!< CMDTMOUT flag clear bit */
+#define SDIO_INTC_DTTMOUTC              BIT(3)                 /*!< DTTMOUT flag clear bit */
+#define SDIO_INTC_TXUREC                BIT(4)                 /*!< TXURE flag clear bit */
+#define SDIO_INTC_RXOREC                BIT(5)                 /*!< RXORE flag clear bit */
+#define SDIO_INTC_CMDRECVC              BIT(6)                 /*!< CMDRECV flag clear bit */
+#define SDIO_INTC_CMDSENDC              BIT(7)                 /*!< CMDSEND flag clear bit */
+#define SDIO_INTC_DTENDC                BIT(8)                 /*!< DTEND flag clear bit */
+#define SDIO_INTC_STBITEC               BIT(9)                 /*!< STBITE flag clear bit */
+#define SDIO_INTC_DTBLKENDC             BIT(10)                /*!< DTBLKEND flag clear bit */
+#define SDIO_INTC_SDIOINTC              BIT(22)                /*!< SDIOINT flag clear bit */
+#define SDIO_INTC_ATAENDC               BIT(23)                /*!< ATAEND flag clear bit */
+
+/* SDIO_INTEN */
+#define SDIO_INTEN_CCRCERRIE            BIT(0)                 /*!< command response CRC fail interrupt enable */
+#define SDIO_INTEN_DTCRCERRIE           BIT(1)                 /*!< data CRC fail interrupt enable */
+#define SDIO_INTEN_CMDTMOUTIE           BIT(2)                 /*!< command response timeout interrupt enable */
+#define SDIO_INTEN_DTTMOUTIE            BIT(3)                 /*!< data timeout interrupt enable */
+#define SDIO_INTEN_TXUREIE              BIT(4)                 /*!< transmit FIFO underrun error interrupt enable */
+#define SDIO_INTEN_RXOREIE              BIT(5)                 /*!< received FIFO overrun error interrupt enable */
+#define SDIO_INTEN_CMDRECVIE            BIT(6)                 /*!< command response received interrupt enable */
+#define SDIO_INTEN_CMDSENDIE            BIT(7)                 /*!< command sent interrupt enable */
+#define SDIO_INTEN_DTENDIE              BIT(8)                 /*!< data end interrupt enable */
+#define SDIO_INTEN_STBITEIE             BIT(9)                 /*!< start bit error interrupt enable */
+#define SDIO_INTEN_DTBLKENDIE           BIT(10)                /*!< data block end interrupt enable */
+#define SDIO_INTEN_CMDRUNIE             BIT(11)                /*!< command transmission interrupt enable */
+#define SDIO_INTEN_TXRUNIE              BIT(12)                /*!< data transmission interrupt enable */
+#define SDIO_INTEN_RXRUNIE              BIT(13)                /*!< data reception interrupt enable */
+#define SDIO_INTEN_TFHIE                BIT(14)                /*!< transmit FIFO half empty interrupt enable */
+#define SDIO_INTEN_RFHIE                BIT(15)                /*!< receive FIFO half full interrupt enable */
+#define SDIO_INTEN_TFFIE                BIT(16)                /*!< transmit FIFO full interrupt enable */
+#define SDIO_INTEN_RFFIE                BIT(17)                /*!< receive FIFO full interrupt enable */
+#define SDIO_INTEN_TFEIE                BIT(18)                /*!< transmit FIFO empty interrupt enable */
+#define SDIO_INTEN_RFEIE                BIT(19)                /*!< receive FIFO empty interrupt enable */
+#define SDIO_INTEN_TXDTVALIE            BIT(20)                /*!< data valid in transmit FIFO interrupt enable */
+#define SDIO_INTEN_RXDTVALIE            BIT(21)                /*!< data valid in receive FIFO interrupt enable */
+#define SDIO_INTEN_SDIOINTIE            BIT(22)                /*!< SD I/O interrupt received interrupt enable */
+#define SDIO_INTEN_ATAENDIE             BIT(23)                /*!< CE-ATA command completion signal received interrupt enable */
+
+/* SDIO_FIFO */
+#define SDIO_FIFO_FIFODT                BITS(0,31)             /*!< receive FIFO data or transmit FIFO data */
+
+/* constants definitions */
+/* SDIO flags */
+#define SDIO_FLAG_CCRCERR               BIT(0)                 /*!< command response received (CRC check failed) flag */
+#define SDIO_FLAG_DTCRCERR              BIT(1)                 /*!< data block sent/received (CRC check failed) flag */
+#define SDIO_FLAG_CMDTMOUT              BIT(2)                 /*!< command response timeout flag */
+#define SDIO_FLAG_DTTMOUT               BIT(3)                 /*!< data timeout flag */
+#define SDIO_FLAG_TXURE                 BIT(4)                 /*!< transmit FIFO underrun error occurs flag */
+#define SDIO_FLAG_RXORE                 BIT(5)                 /*!< received FIFO overrun error occurs flag */
+#define SDIO_FLAG_CMDRECV               BIT(6)                 /*!< command response received (CRC check passed) flag */
+#define SDIO_FLAG_CMDSEND               BIT(7)                 /*!< command sent (no response required) flag */
+#define SDIO_FLAG_DTEND                 BIT(8)                 /*!< data end (data counter, SDIO_DATACNT, is zero) flag */
+#define SDIO_FLAG_STBITE                BIT(9)                 /*!< start bit error in the bus flag */
+#define SDIO_FLAG_DTBLKEND              BIT(10)                /*!< data block sent/received (CRC check passed) flag */
+#define SDIO_FLAG_CMDRUN                BIT(11)                /*!< command transmission in progress flag */
+#define SDIO_FLAG_TXRUN                 BIT(12)                /*!< data transmission in progress flag */
+#define SDIO_FLAG_RXRUN                 BIT(13)                /*!< data reception in progress flag */
+#define SDIO_FLAG_TFH                   BIT(14)                /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */
+#define SDIO_FLAG_RFH                   BIT(15)                /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */
+#define SDIO_FLAG_TFF                   BIT(16)                /*!< transmit FIFO is full flag */
+#define SDIO_FLAG_RFF                   BIT(17)                /*!< receive FIFO is full flag */
+#define SDIO_FLAG_TFE                   BIT(18)                /*!< transmit FIFO is empty flag */
+#define SDIO_FLAG_RFE                   BIT(19)                /*!< receive FIFO is empty flag */
+#define SDIO_FLAG_TXDTVAL               BIT(20)                /*!< data is valid in transmit FIFO flag */
+#define SDIO_FLAG_RXDTVAL               BIT(21)                /*!< data is valid in receive FIFO flag */
+#define SDIO_FLAG_SDIOINT               BIT(22)                /*!< SD I/O interrupt received flag */
+#define SDIO_FLAG_ATAEND                BIT(23)                /*!< CE-ATA command completion signal received (only for CMD61) flag */
+
+/* SDIO interrupt enable or disable */
+#define SDIO_INT_CCRCERR                BIT(0)                 /*!< SDIO CCRCERR interrupt */
+#define SDIO_INT_DTCRCERR               BIT(1)                 /*!< SDIO DTCRCERR interrupt */
+#define SDIO_INT_CMDTMOUT               BIT(2)                 /*!< SDIO CMDTMOUT interrupt */
+#define SDIO_INT_DTTMOUT                BIT(3)                 /*!< SDIO DTTMOUT interrupt */
+#define SDIO_INT_TXURE                  BIT(4)                 /*!< SDIO TXURE interrupt */
+#define SDIO_INT_RXORE                  BIT(5)                 /*!< SDIO RXORE interrupt */
+#define SDIO_INT_CMDRECV                BIT(6)                 /*!< SDIO CMDRECV interrupt */
+#define SDIO_INT_CMDSEND                BIT(7)                 /*!< SDIO CMDSEND interrupt */
+#define SDIO_INT_DTEND                  BIT(8)                 /*!< SDIO DTEND interrupt */
+#define SDIO_INT_STBITE                 BIT(9)                 /*!< SDIO STBITE interrupt */
+#define SDIO_INT_DTBLKEND               BIT(10)                /*!< SDIO DTBLKEND interrupt */
+#define SDIO_INT_CMDRUN                 BIT(11)                /*!< SDIO CMDRUN interrupt */
+#define SDIO_INT_TXRUN                  BIT(12)                /*!< SDIO TXRUN interrupt */
+#define SDIO_INT_RXRUN                  BIT(13)                /*!< SDIO RXRUN interrupt */
+#define SDIO_INT_TFH                    BIT(14)                /*!< SDIO TFH interrupt */
+#define SDIO_INT_RFH                    BIT(15)                /*!< SDIO RFH interrupt */
+#define SDIO_INT_TFF                    BIT(16)                /*!< SDIO TFF interrupt */
+#define SDIO_INT_RFF                    BIT(17)                /*!< SDIO RFF interrupt */
+#define SDIO_INT_TFE                    BIT(18)                /*!< SDIO TFE interrupt */
+#define SDIO_INT_RFE                    BIT(19)                /*!< SDIO RFE interrupt */
+#define SDIO_INT_TXDTVAL                BIT(20)                /*!< SDIO TXDTVAL interrupt */
+#define SDIO_INT_RXDTVAL                BIT(21)                /*!< SDIO RXDTVAL interrupt */
+#define SDIO_INT_SDIOINT                BIT(22)                /*!< SDIO SDIOINT interrupt */
+#define SDIO_INT_ATAEND                 BIT(23)                /*!< SDIO ATAEND interrupt */
+
+/* SDIO interrupt flags */
+#define SDIO_INT_FLAG_CCRCERR           BIT(0)                 /*!< SDIO CCRCERR interrupt flag */
+#define SDIO_INT_FLAG_DTCRCERR          BIT(1)                 /*!< SDIO DTCRCERR interrupt flag */
+#define SDIO_INT_FLAG_CMDTMOUT          BIT(2)                 /*!< SDIO CMDTMOUT interrupt flag */
+#define SDIO_INT_FLAG_DTTMOUT           BIT(3)                 /*!< SDIO DTTMOUT interrupt flag */
+#define SDIO_INT_FLAG_TXURE             BIT(4)                 /*!< SDIO TXURE interrupt flag */
+#define SDIO_INT_FLAG_RXORE             BIT(5)                 /*!< SDIO RXORE interrupt flag */
+#define SDIO_INT_FLAG_CMDRECV           BIT(6)                 /*!< SDIO CMDRECV interrupt flag */
+#define SDIO_INT_FLAG_CMDSEND           BIT(7)                 /*!< SDIO CMDSEND interrupt flag */
+#define SDIO_INT_FLAG_DTEND             BIT(8)                 /*!< SDIO DTEND interrupt flag */
+#define SDIO_INT_FLAG_STBITE            BIT(9)                 /*!< SDIO STBITE interrupt flag */
+#define SDIO_INT_FLAG_DTBLKEND          BIT(10)                /*!< SDIO DTBLKEND interrupt flag */
+#define SDIO_INT_FLAG_CMDRUN            BIT(11)                /*!< SDIO CMDRUN interrupt flag */
+#define SDIO_INT_FLAG_TXRUN             BIT(12)                /*!< SDIO TXRUN interrupt flag */
+#define SDIO_INT_FLAG_RXRUN             BIT(13)                /*!< SDIO RXRUN interrupt flag */
+#define SDIO_INT_FLAG_TFH               BIT(14)                /*!< SDIO TFH interrupt flag */
+#define SDIO_INT_FLAG_RFH               BIT(15)                /*!< SDIO RFH interrupt flag */
+#define SDIO_INT_FLAG_TFF               BIT(16)                /*!< SDIO TFF interrupt flag */
+#define SDIO_INT_FLAG_RFF               BIT(17)                /*!< SDIO RFF interrupt flag */
+#define SDIO_INT_FLAG_TFE               BIT(18)                /*!< SDIO TFE interrupt flag */
+#define SDIO_INT_FLAG_RFE               BIT(19)                /*!< SDIO RFE interrupt flag */
+#define SDIO_INT_FLAG_TXDTVAL           BIT(20)                /*!< SDIO TXDTVAL interrupt flag */
+#define SDIO_INT_FLAG_RXDTVAL           BIT(21)                /*!< SDIO RXDTVAL interrupt flag */
+#define SDIO_INT_FLAG_SDIOINT           BIT(22)                /*!< SDIO SDIOINT interrupt flag */
+#define SDIO_INT_FLAG_ATAEND            BIT(23)                /*!< SDIO ATAEND interrupt flag */
+
+/* SDIO power control */
+#define PWRCTL_PWRCTL(regval)           (BITS(0,1) & ((uint32_t)(regval) << 0))
+#define SDIO_POWER_OFF                  PWRCTL_PWRCTL(0)       /*!< SDIO power off */
+#define SDIO_POWER_ON                   PWRCTL_PWRCTL(3)       /*!< SDIO power on */
+
+/* SDIO card bus mode control */
+#define CLKCTL_BUSMODE(regval)          (BITS(11,12) & ((uint32_t)(regval) << 11))
+#define SDIO_BUSMODE_1BIT               CLKCTL_BUSMODE(0)      /*!< 1-bit SDIO card bus mode */
+#define SDIO_BUSMODE_4BIT               CLKCTL_BUSMODE(1)      /*!< 4-bit SDIO card bus mode */
+#define SDIO_BUSMODE_8BIT               CLKCTL_BUSMODE(2)      /*!< 8-bit SDIO card bus mode */
+
+/* SDIO_CLK clock edge selection */
+#define SDIO_SDIOCLKEDGE_RISING         ((uint32_t)0x00000000U)/*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */
+#define SDIO_SDIOCLKEDGE_FALLING        SDIO_CLKCTL_CLKEDGE    /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */
+
+/* clock bypass enable or disable */
+#define SDIO_CLOCKBYPASS_DISABLE        ((uint32_t)0x00000000U)/*!< no bypass */
+#define SDIO_CLOCKBYPASS_ENABLE         SDIO_CLKCTL_CLKBYP     /*!< clock bypass */
+
+/* SDIO_CLK clock dynamic switch on/off for power saving */
+#define SDIO_CLOCKPWRSAVE_DISABLE       ((uint32_t)0x00000000U)/*!< SDIO_CLK clock is always on */
+#define SDIO_CLOCKPWRSAVE_ENABLE        SDIO_CLKCTL_CLKPWRSAV  /*!< SDIO_CLK closed when bus is idle */
+
+/* SDIO command response type */
+#define CMDCTL_CMDRESP(regval)          (BITS(6,7) & ((uint32_t)(regval) << 6))
+#define SDIO_RESPONSETYPE_NO            CMDCTL_CMDRESP(0)      /*!< no response */
+#define SDIO_RESPONSETYPE_SHORT         CMDCTL_CMDRESP(1)      /*!< short response */
+#define SDIO_RESPONSETYPE_LONG          CMDCTL_CMDRESP(3)      /*!< long response */
+
+/* command state machine wait type */
+#define SDIO_WAITTYPE_NO                ((uint32_t)0x00000000U)/*!< not wait interrupt */
+#define SDIO_WAITTYPE_INTERRUPT         SDIO_CMDCTL_INTWAIT    /*!< wait interrupt */
+#define SDIO_WAITTYPE_DATAEND           SDIO_CMDCTL_WAITDEND   /*!< wait the end of data transfer */
+
+#define SDIO_RESPONSE0                  ((uint32_t)0x00000000U)/*!< card response[31:0]/card response[127:96] */
+#define SDIO_RESPONSE1                  ((uint32_t)0x00000001U)/*!< card response[95:64] */
+#define SDIO_RESPONSE2                  ((uint32_t)0x00000002U)/*!< card response[63:32] */
+#define SDIO_RESPONSE3                  ((uint32_t)0x00000003U)/*!< card response[31:1], plus bit 0 */
+
+/* SDIO data block size */
+#define DATACTL_BLKSZ(regval)           (BITS(4,7) & ((uint32_t)(regval) << 4))
+#define SDIO_DATABLOCKSIZE_1BYTE        DATACTL_BLKSZ(0)       /*!< block size = 1 byte */
+#define SDIO_DATABLOCKSIZE_2BYTES       DATACTL_BLKSZ(1)       /*!< block size = 2 bytes */
+#define SDIO_DATABLOCKSIZE_4BYTES       DATACTL_BLKSZ(2)       /*!< block size = 4 bytes */
+#define SDIO_DATABLOCKSIZE_8BYTES       DATACTL_BLKSZ(3)       /*!< block size = 8 bytes */
+#define SDIO_DATABLOCKSIZE_16BYTES      DATACTL_BLKSZ(4)       /*!< block size = 16 bytes */
+#define SDIO_DATABLOCKSIZE_32BYTES      DATACTL_BLKSZ(5)       /*!< block size = 32 bytes */
+#define SDIO_DATABLOCKSIZE_64BYTES      DATACTL_BLKSZ(6)       /*!< block size = 64 bytes */
+#define SDIO_DATABLOCKSIZE_128BYTES     DATACTL_BLKSZ(7)       /*!< block size = 128 bytes */
+#define SDIO_DATABLOCKSIZE_256BYTES     DATACTL_BLKSZ(8)       /*!< block size = 256 bytes */
+#define SDIO_DATABLOCKSIZE_512BYTES     DATACTL_BLKSZ(9)       /*!< block size = 512 bytes */
+#define SDIO_DATABLOCKSIZE_1024BYTES    DATACTL_BLKSZ(10)      /*!< block size = 1024 bytes */
+#define SDIO_DATABLOCKSIZE_2048BYTES    DATACTL_BLKSZ(11)      /*!< block size = 2048 bytes */
+#define SDIO_DATABLOCKSIZE_4096BYTES    DATACTL_BLKSZ(12)      /*!< block size = 4096 bytes */
+#define SDIO_DATABLOCKSIZE_8192BYTES    DATACTL_BLKSZ(13)      /*!< block size = 8192 bytes */
+#define SDIO_DATABLOCKSIZE_16384BYTES   DATACTL_BLKSZ(14)      /*!< block size = 16384 bytes */
+
+/* SDIO data transfer mode */
+#define SDIO_TRANSMODE_BLOCK            ((uint32_t)0x00000000U)/*!< block transfer */
+#define SDIO_TRANSMODE_STREAM           SDIO_DATACTL_TRANSMOD  /*!< stream transfer or SDIO multibyte transfer */
+
+/* SDIO data transfer direction */
+#define SDIO_TRANSDIRECTION_TOCARD      ((uint32_t)0x00000000U)/*!< write data to card */
+#define SDIO_TRANSDIRECTION_TOSDIO      SDIO_DATACTL_DATADIR   /*!< read data from card */
+
+/* SDIO read wait type */
+#define SDIO_READWAITTYPE_DAT2          ((uint32_t)0x00000000U)/*!< read wait control using SDIO_DAT[2] */
+#define SDIO_READWAITTYPE_CLK           SDIO_DATACTL_RWTYPE    /*!< read wait control by stopping SDIO_CLK */
+
+/* function declarations */
+/* de/initialization functions, hardware clock, bus mode, power_state and SDIO clock configuration */
+/* deinitialize the SDIO */
+void sdio_deinit(void);
+/* configure the SDIO clock */
+void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division);
+/* enable hardware clock control */
+void sdio_hardware_clock_enable(void);
+/* disable hardware clock control */
+void sdio_hardware_clock_disable(void);
+/* set different SDIO card bus mode */
+void sdio_bus_mode_set(uint32_t bus_mode);
+/* set the SDIO power state */
+void sdio_power_state_set(uint32_t power_state);
+/* get the SDIO power state */
+uint32_t sdio_power_state_get(void);
+/* enable SDIO_CLK clock output */
+void sdio_clock_enable(void);
+/* disable SDIO_CLK clock output */
+void sdio_clock_disable(void);
+
+/* configure the command index, argument, response type, wait type and CSM to send command functions */
+/* configure the command and response */
+void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type);
+/* set the command state machine wait type */
+void sdio_wait_type_set(uint32_t wait_type);
+/* enable the CSM(command state machine) */
+void sdio_csm_enable(void);
+/* disable the CSM(command state machine) */
+void sdio_csm_disable(void);
+/* get the last response command index */
+uint8_t sdio_command_index_get(void);
+/* get the response for the last received command */
+uint32_t sdio_response_get(uint32_t responsex);
+
+/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer functions */
+/* configure the data timeout, data length and data block size */
+void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize);
+/* configure the data transfer mode and direction */
+void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction);
+/* enable the DSM(data state machine) for data transfer */
+void sdio_dsm_enable(void);
+/* disable the DSM(data state machine) */
+void sdio_dsm_disable(void);
+/* write data(one word) to the transmit FIFO */
+void sdio_data_write(uint32_t data);
+/* read data(one word) from the receive FIFO */
+uint32_t sdio_data_read(void);
+/* get the number of remaining data bytes to be transferred to card */
+uint32_t sdio_data_counter_get(void);
+/* get the number of words remaining to be written or read from FIFO */
+uint32_t sdio_fifo_counter_get(void);
+/* enable the DMA request for SDIO */
+void sdio_dma_enable(void);
+/* disable the DMA request for SDIO */
+void sdio_dma_disable(void);
+
+/* flag and interrupt functions */
+/* get the flags state of SDIO */
+FlagStatus sdio_flag_get(uint32_t flag);
+/* clear the pending flags of SDIO */
+void sdio_flag_clear(uint32_t flag);
+/* enable the SDIO interrupt */
+void sdio_interrupt_enable(uint32_t int_flag);
+/* disable the SDIO interrupt */
+void sdio_interrupt_disable(uint32_t int_flag);
+/* get the interrupt flags state of SDIO */
+FlagStatus sdio_interrupt_flag_get(uint32_t int_flag);
+/* clear the interrupt pending flags of SDIO */
+void sdio_interrupt_flag_clear(uint32_t int_flag);
+
+/* SD I/O card functions */
+/* enable the read wait mode(SD I/O only) */
+void sdio_readwait_enable(void);
+/* disable the read wait mode(SD I/O only) */
+void sdio_readwait_disable(void);
+/* enable the function that stop the read wait process(SD I/O only) */
+void sdio_stop_readwait_enable(void);
+/* disable the function that stop the read wait process(SD I/O only) */
+void sdio_stop_readwait_disable(void);
+/* set the read wait type(SD I/O only) */
+void sdio_readwait_type_set(uint32_t readwait_type);
+/* enable the SD I/O mode specific operation(SD I/O only) */
+void sdio_operation_enable(void);
+/* disable the SD I/O mode specific operation(SD I/O only) */
+void sdio_operation_disable(void);
+/* enable the SD I/O suspend operation(SD I/O only) */
+void sdio_suspend_enable(void);
+/* disable the SD I/O suspend operation(SD I/O only) */
+void sdio_suspend_disable(void);
+
+/* CE-ATA functions */
+/* enable the CE-ATA command(CE-ATA only) */
+void sdio_ceata_command_enable(void);
+/* disable the CE-ATA command(CE-ATA only) */
+void sdio_ceata_command_disable(void);
+/* enable the CE-ATA interrupt(CE-ATA only) */
+void sdio_ceata_interrupt_enable(void);
+/* disable the CE-ATA interrupt(CE-ATA only) */
+void sdio_ceata_interrupt_disable(void);
+/* enable the CE-ATA command completion signal(CE-ATA only) */
+void sdio_ceata_command_completion_enable(void);
+/* disable the CE-ATA command completion signal(CE-ATA only) */
+void sdio_ceata_command_completion_disable(void);
+
+#endif /* GD32F10X_SDIO_H */

+ 327 - 0
Library/Include/gd32f10x_spi.h

@@ -0,0 +1,327 @@
+/*!
+    \file    gd32f10x_spi.h
+    \brief   definitions for the SPI
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_SPI_H
+#define GD32F10X_SPI_H
+
+#include "gd32f10x.h"
+
+/* SPIx(x=0,1,2) definitions */
+#define SPI0                            (SPI_BASE + 0x0000F800U)
+#define SPI1                            SPI_BASE
+#define SPI2                            (SPI_BASE + 0x00000400U)
+
+/* SPI registers definitions */
+#define SPI_CTL0(spix)                  REG32((spix) + 0x00U)                   /*!< SPI control register 0 */
+#define SPI_CTL1(spix)                  REG32((spix) + 0x04U)                   /*!< SPI control register 1*/
+#define SPI_STAT(spix)                  REG32((spix) + 0x08U)                   /*!< SPI status register */
+#define SPI_DATA(spix)                  REG32((spix) + 0x0CU)                   /*!< SPI data register */
+#define SPI_CRCPOLY(spix)               REG32((spix) + 0x10U)                   /*!< SPI CRC polynomial register */
+#define SPI_RCRC(spix)                  REG32((spix) + 0x14U)                   /*!< SPI receive CRC register */
+#define SPI_TCRC(spix)                  REG32((spix) + 0x18U)                   /*!< SPI transmit CRC register */
+#define SPI_I2SCTL(spix)                REG32((spix) + 0x1CU)                   /*!< SPI I2S control register */
+#define SPI_I2SPSC(spix)                REG32((spix) + 0x20U)                   /*!< SPI I2S clock prescaler register */
+
+/* bits definitions */
+/* SPI_CTL0 */
+#define SPI_CTL0_CKPH                   BIT(0)                                  /*!< clock phase selection*/
+#define SPI_CTL0_CKPL                   BIT(1)                                  /*!< clock polarity selection */
+#define SPI_CTL0_MSTMOD                 BIT(2)                                  /*!< master mode enable */
+#define SPI_CTL0_PSC                    BITS(3,5)                               /*!< master clock prescaler selection */
+#define SPI_CTL0_SPIEN                  BIT(6)                                  /*!< SPI enable*/
+#define SPI_CTL0_LF                     BIT(7)                                  /*!< LSB first mode */
+#define SPI_CTL0_SWNSS                  BIT(8)                                  /*!< NSS pin selection in NSS software mode */
+#define SPI_CTL0_SWNSSEN                BIT(9)                                  /*!< NSS software mode selection */
+#define SPI_CTL0_RO                     BIT(10)                                 /*!< receive only */
+#define SPI_CTL0_FF16                   BIT(11)                                 /*!< data frame size */
+#define SPI_CTL0_CRCNT                  BIT(12)                                 /*!< CRC next transfer */
+#define SPI_CTL0_CRCEN                  BIT(13)                                 /*!< CRC calculation enable */
+#define SPI_CTL0_BDOEN                  BIT(14)                                 /*!< bidirectional transmit output enable*/
+#define SPI_CTL0_BDEN                   BIT(15)                                 /*!< bidirectional enable */
+
+/* SPI_CTL1 */
+#define SPI_CTL1_DMAREN                 BIT(0)                                  /*!< receive buffer dma enable */
+#define SPI_CTL1_DMATEN                 BIT(1)                                  /*!< transmit buffer dma enable */
+#define SPI_CTL1_NSSDRV                 BIT(2)                                  /*!< drive NSS output */
+#define SPI_CTL1_ERRIE                  BIT(5)                                  /*!< errors interrupt enable */
+#define SPI_CTL1_RBNEIE                 BIT(6)                                  /*!< receive buffer not empty interrupt enable */
+#define SPI_CTL1_TBEIE                  BIT(7)                                  /*!< transmit buffer empty interrupt enable */
+
+/* SPI_STAT */
+#define SPI_STAT_RBNE                   BIT(0)                                  /*!< receive buffer not empty */
+#define SPI_STAT_TBE                    BIT(1)                                  /*!< transmit buffer empty */
+#define SPI_STAT_I2SCH                  BIT(2)                                  /*!< I2S channel side */
+#define SPI_STAT_TXURERR                BIT(3)                                  /*!< I2S transmission underrun error bit */
+#define SPI_STAT_CRCERR                 BIT(4)                                  /*!< SPI CRC error bit */
+#define SPI_STAT_CONFERR                BIT(5)                                  /*!< SPI configuration error bit */
+#define SPI_STAT_RXORERR                BIT(6)                                  /*!< SPI reception overrun error bit */
+#define SPI_STAT_TRANS                  BIT(7)                                  /*!< transmitting on-going bit */
+
+/* SPI_DATA */
+#define SPI_DATA_DATA                   BITS(0,15)                              /*!< data transfer register */
+
+/* SPI_CRCPOLY */
+#define SPI_CRCPOLY_CPR                 BITS(0,15)                              /*!< CRC polynomial value */
+
+/* SPI_RCRC */
+#define SPI_RCRC_RCR                    BITS(0,15)                              /*!< RX CRC value */
+
+/* SPI_TCRC */
+#define SPI_TCRC_TCR                    BITS(0,15)                              /*!< TX CRC value */
+
+/* SPI_I2SCTL */
+#define SPI_I2SCTL_CHLEN                BIT(0)                                  /*!< channel length */
+#define SPI_I2SCTL_DTLEN                BITS(1,2)                               /*!< data length */
+#define SPI_I2SCTL_CKPL                 BIT(3)                                  /*!< idle state clock polarity */
+#define SPI_I2SCTL_I2SSTD               BITS(4,5)                               /*!< I2S standard selection */
+#define SPI_I2SCTL_PCMSMOD              BIT(7)                                  /*!< PCM frame synchronization mode */
+#define SPI_I2SCTL_I2SOPMOD             BITS(8,9)                               /*!< I2S operation mode */
+#define SPI_I2SCTL_I2SEN                BIT(10)                                 /*!< I2S enable */
+#define SPI_I2SCTL_I2SSEL               BIT(11)                                 /*!< I2S mode selection */
+
+/* SPI_I2SPSC */
+#define SPI_I2SPSC_DIV                  BITS(0,7)                               /*!< dividing factor for the prescaler */
+#define SPI_I2SPSC_OF                   BIT(8)                                  /*!< odd factor for the prescaler */
+#define SPI_I2SPSC_MCKOEN               BIT(9)                                  /*!< I2S MCK output enable */
+
+/* constants definitions */
+/* SPI and I2S parameter struct definitions */
+typedef struct
+{   
+    uint32_t device_mode;                                                       /*!< SPI master or slave */
+    uint32_t trans_mode;                                                        /*!< SPI transtype */
+    uint32_t frame_size;                                                        /*!< SPI frame size */
+    uint32_t nss;                                                               /*!< SPI NSS control by handware or software */
+    uint32_t endian;                                                            /*!< SPI big endian or little endian */
+    uint32_t clock_polarity_phase;                                              /*!< SPI clock phase and polarity */
+    uint32_t prescale;                                                          /*!< SPI prescale factor */
+}spi_parameter_struct;
+
+/* SPI mode definitions */
+#define SPI_MASTER                      (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS)      /*!< SPI as master */
+#define SPI_SLAVE                       ((uint32_t)0x00000000U)                 /*!< SPI as slave */
+
+/* SPI bidirectional transfer direction */
+#define SPI_BIDIRECTIONAL_TRANSMIT      SPI_CTL0_BDOEN                          /*!< SPI work in transmit-only mode */
+#define SPI_BIDIRECTIONAL_RECEIVE       (~SPI_CTL0_BDOEN)                       /*!< SPI work in receive-only mode */
+
+/* SPI transmit type */
+#define SPI_TRANSMODE_FULLDUPLEX        ((uint32_t)0x00000000U)                 /*!< SPI receive and send data at fullduplex communication */
+#define SPI_TRANSMODE_RECEIVEONLY       SPI_CTL0_RO                             /*!< SPI only receive data */
+#define SPI_TRANSMODE_BDRECEIVE         SPI_CTL0_BDEN                           /*!< bidirectional receive data */
+#define SPI_TRANSMODE_BDTRANSMIT        (SPI_CTL0_BDEN | SPI_CTL0_BDOEN)        /*!< bidirectional transmit data*/
+
+/* SPI frame size */
+#define SPI_FRAMESIZE_16BIT             SPI_CTL0_FF16                           /*!< SPI frame size is 16 bits */
+#define SPI_FRAMESIZE_8BIT              ((uint32_t)0x00000000U)                 /*!< SPI frame size is 8 bits */
+
+/* SPI NSS control mode */
+#define SPI_NSS_SOFT                    SPI_CTL0_SWNSSEN                        /*!< SPI NSS control by software */
+#define SPI_NSS_HARD                    ((uint32_t)0x00000000U)                 /*!< SPI NSS control by hardware */
+
+/* SPI transmit way */
+#define SPI_ENDIAN_MSB                  ((uint32_t)0x00000000U)                 /*!< SPI transmit way is big endian: transmit MSB first */
+#define SPI_ENDIAN_LSB                  SPI_CTL0_LF                             /*!< SPI transmit way is little endian: transmit LSB first */
+
+/* SPI clock phase and polarity */
+#define SPI_CK_PL_LOW_PH_1EDGE          ((uint32_t)0x00000000U)                 /*!< SPI clock polarity is low level and phase is first edge */
+#define SPI_CK_PL_HIGH_PH_1EDGE         SPI_CTL0_CKPL                           /*!< SPI clock polarity is high level and phase is first edge */
+#define SPI_CK_PL_LOW_PH_2EDGE          SPI_CTL0_CKPH                           /*!< SPI clock polarity is low level and phase is second edge */
+#define SPI_CK_PL_HIGH_PH_2EDGE         (SPI_CTL0_CKPL | SPI_CTL0_CKPH)         /*!< SPI clock polarity is high level and phase is second edge */
+
+/* SPI clock prescale factor */
+#define CTL0_PSC(regval)                (BITS(3,5) & ((uint32_t)(regval) << 3))
+#define SPI_PSC_2                       CTL0_PSC(0)                             /*!< SPI clock prescale factor is 2 */
+#define SPI_PSC_4                       CTL0_PSC(1)                             /*!< SPI clock prescale factor is 4 */
+#define SPI_PSC_8                       CTL0_PSC(2)                             /*!< SPI clock prescale factor is 8 */
+#define SPI_PSC_16                      CTL0_PSC(3)                             /*!< SPI clock prescale factor is 16 */
+#define SPI_PSC_32                      CTL0_PSC(4)                             /*!< SPI clock prescale factor is 32 */
+#define SPI_PSC_64                      CTL0_PSC(5)                             /*!< SPI clock prescale factor is 64 */
+#define SPI_PSC_128                     CTL0_PSC(6)                             /*!< SPI clock prescale factor is 128 */
+#define SPI_PSC_256                     CTL0_PSC(7)                             /*!< SPI clock prescale factor is 256 */
+
+/* I2S audio sample rate */
+#define I2S_AUDIOSAMPLE_8K              ((uint32_t)8000U)                       /*!< I2S audio sample rate is 8KHz */
+#define I2S_AUDIOSAMPLE_11K             ((uint32_t)11025U)                      /*!< I2S audio sample rate is 11KHz */
+#define I2S_AUDIOSAMPLE_16K             ((uint32_t)16000U)                      /*!< I2S audio sample rate is 16KHz */
+#define I2S_AUDIOSAMPLE_22K             ((uint32_t)22050U)                      /*!< I2S audio sample rate is 22KHz */
+#define I2S_AUDIOSAMPLE_32K             ((uint32_t)32000U)                      /*!< I2S audio sample rate is 32KHz */
+#define I2S_AUDIOSAMPLE_44K             ((uint32_t)44100U)                      /*!< I2S audio sample rate is 44KHz */
+#define I2S_AUDIOSAMPLE_48K             ((uint32_t)48000U)                      /*!< I2S audio sample rate is 48KHz */
+#define I2S_AUDIOSAMPLE_96K             ((uint32_t)96000U)                      /*!< I2S audio sample rate is 96KHz */
+#define I2S_AUDIOSAMPLE_192K            ((uint32_t)192000U)                     /*!< I2S audio sample rate is 192KHz */
+
+/* I2S frame format */
+#define I2SCTL_DTLEN(regval)            (BITS(1,2) & ((uint32_t)(regval) << 1))
+#define I2S_FRAMEFORMAT_DT16B_CH16B     I2SCTL_DTLEN(0)                         /*!< I2S data length is 16 bit and channel length is 16 bit */
+#define I2S_FRAMEFORMAT_DT16B_CH32B     (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN)    /*!< I2S data length is 16 bit and channel length is 32 bit */
+#define I2S_FRAMEFORMAT_DT24B_CH32B     (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN)    /*!< I2S data length is 24 bit and channel length is 32 bit */
+#define I2S_FRAMEFORMAT_DT32B_CH32B     (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN)    /*!< I2S data length is 32 bit and channel length is 32 bit */
+
+/* I2S master clock output */
+#define I2S_MCKOUT_DISABLE              ((uint32_t)0x00000000U)                 /*!< I2S master clock output disable */
+#define I2S_MCKOUT_ENABLE               SPI_I2SPSC_MCKOEN                       /*!< I2S master clock output enable */
+
+/* I2S operation mode */
+#define I2SCTL_I2SOPMOD(regval)         (BITS(8,9) & ((uint32_t)(regval) << 8))
+#define I2S_MODE_SLAVETX                I2SCTL_I2SOPMOD(0)                      /*!< I2S slave transmit mode */
+#define I2S_MODE_SLAVERX                I2SCTL_I2SOPMOD(1)                      /*!< I2S slave receive mode */
+#define I2S_MODE_MASTERTX               I2SCTL_I2SOPMOD(2)                      /*!< I2S master transmit mode */
+#define I2S_MODE_MASTERRX               I2SCTL_I2SOPMOD(3)                      /*!< I2S master receive mode */
+
+/* I2S standard */
+#define I2SCTL_I2SSTD(regval)           (BITS(4,5) & ((uint32_t)(regval) << 4))
+#define I2S_STD_PHILLIPS                I2SCTL_I2SSTD(0)                        /*!< I2S phillips standard */
+#define I2S_STD_MSB                     I2SCTL_I2SSTD(1)                        /*!< I2S MSB standard */
+#define I2S_STD_LSB                     I2SCTL_I2SSTD(2)                        /*!< I2S LSB standard */
+#define I2S_STD_PCMSHORT                I2SCTL_I2SSTD(3)                        /*!< I2S PCM short standard */
+#define I2S_STD_PCMLONG                 (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */
+
+/* I2S clock polarity */
+#define I2S_CKPL_LOW                    ((uint32_t)0x00000000U)                 /*!< I2S clock polarity low level */
+#define I2S_CKPL_HIGH                   SPI_I2SCTL_CKPL                         /*!< I2S clock polarity high level */
+
+/* SPI DMA constants definitions */                                    
+#define SPI_DMA_TRANSMIT                ((uint8_t)0x00U)                        /*!< SPI transmit data use DMA */
+#define SPI_DMA_RECEIVE                 ((uint8_t)0x01U)                        /*!< SPI receive data use DMA */
+
+/* SPI CRC constants definitions */
+#define SPI_CRC_TX                      ((uint8_t)0x00U)                        /*!< SPI transmit CRC value */
+#define SPI_CRC_RX                      ((uint8_t)0x01U)                        /*!< SPI receive CRC value */
+
+/* SPI/I2S interrupt enable/disable constants definitions */
+#define SPI_I2S_INT_TBE                 ((uint8_t)0x00U)                        /*!< transmit buffer empty interrupt */
+#define SPI_I2S_INT_RBNE                ((uint8_t)0x01U)                        /*!< receive buffer not empty interrupt */
+#define SPI_I2S_INT_ERR                 ((uint8_t)0x02U)                        /*!< error interrupt */
+
+/* SPI/I2S interrupt flag constants definitions */
+#define SPI_I2S_INT_FLAG_TBE            ((uint8_t)0x00U)                        /*!< transmit buffer empty interrupt flag */
+#define SPI_I2S_INT_FLAG_RBNE           ((uint8_t)0x01U)                        /*!< receive buffer not empty interrupt flag */
+#define SPI_I2S_INT_FLAG_RXORERR        ((uint8_t)0x02U)                        /*!< overrun interrupt flag */
+#define SPI_INT_FLAG_CONFERR            ((uint8_t)0x03U)                        /*!< config error interrupt flag */
+#define SPI_INT_FLAG_CRCERR             ((uint8_t)0x04U)                        /*!< CRC error interrupt flag */
+#define I2S_INT_FLAG_TXURERR            ((uint8_t)0x05U)                        /*!< underrun error interrupt flag */
+
+/* SPI/I2S flag definitions */                                                  
+#define SPI_FLAG_RBNE                   SPI_STAT_RBNE                           /*!< receive buffer not empty flag */
+#define SPI_FLAG_TBE                    SPI_STAT_TBE                            /*!< transmit buffer empty flag */
+#define SPI_FLAG_CRCERR                 SPI_STAT_CRCERR                         /*!< CRC error flag */
+#define SPI_FLAG_CONFERR                SPI_STAT_CONFERR                        /*!< mode config error flag */
+#define SPI_FLAG_RXORERR                SPI_STAT_RXORERR                        /*!< receive overrun error flag */
+#define SPI_FLAG_TRANS                  SPI_STAT_TRANS                          /*!< transmit on-going flag */
+#define I2S_FLAG_RBNE                   SPI_STAT_RBNE                           /*!< receive buffer not empty flag */
+#define I2S_FLAG_TBE                    SPI_STAT_TBE                            /*!< transmit buffer empty flag */
+#define I2S_FLAG_CH                     SPI_STAT_I2SCH                          /*!< channel side flag */
+#define I2S_FLAG_TXURERR                SPI_STAT_TXURERR                        /*!< underrun error flag */
+#define I2S_FLAG_RXORERR                SPI_STAT_RXORERR                        /*!< overrun error flag */
+#define I2S_FLAG_TRANS                  SPI_STAT_TRANS                          /*!< transmit on-going flag */
+
+/* function declarations */
+/* SPI/I2S deinitialization and initialization functions */
+/* reset SPI and I2S */
+void spi_i2s_deinit(uint32_t spi_periph);
+/* initialize the parameters of SPI struct with the default values */
+void spi_struct_para_init(spi_parameter_struct* spi_struct);
+/* initialize SPI parameter */
+void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct);
+/* enable SPI */
+void spi_enable(uint32_t spi_periph);
+/* disable SPI */
+void spi_disable(uint32_t spi_periph);
+
+/* initialize I2S parameter */
+void i2s_init(uint32_t spi_periph,uint32_t mode, uint32_t standard, uint32_t ckpl);
+/* configure I2S prescaler */
+void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout);
+/* enable I2S */
+void i2s_enable(uint32_t spi_periph);
+/* disable I2S */
+void i2s_disable(uint32_t spi_periph);
+
+/* NSS functions */
+/* enable SPI NSS output */
+void spi_nss_output_enable(uint32_t spi_periph);
+/* disable SPI NSS output */
+void spi_nss_output_disable(uint32_t spi_periph);
+/* SPI NSS pin high level in software mode */
+void spi_nss_internal_high(uint32_t spi_periph);
+/* SPI NSS pin low level in software mode */
+void spi_nss_internal_low(uint32_t spi_periph);
+
+/* DMA communication */
+/* enable SPI DMA */
+void spi_dma_enable(uint32_t spi_periph, uint8_t dma);
+/* disable SPI DMA */
+void spi_dma_disable(uint32_t spi_periph, uint8_t dma);
+
+/* normal mode communication */
+/* configure SPI/I2S data frame format */
+void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format);
+/* SPI transmit data */
+void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data);
+/* SPI receive data */
+uint16_t spi_i2s_data_receive(uint32_t spi_periph);
+/* configure SPI bidirectional transfer direction */
+void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction);
+
+/* SPI CRC functions */
+/* set SPI CRC polynomial */
+void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly);
+/* get SPI CRC polynomial */
+uint16_t spi_crc_polynomial_get(uint32_t spi_periph);
+/* turn on SPI CRC function */
+void spi_crc_on(uint32_t spi_periph);
+/* turn off SPI CRC function */
+void spi_crc_off(uint32_t spi_periph);
+/* SPI next data is CRC value */
+void spi_crc_next(uint32_t spi_periph);
+/* get SPI CRC send value or receive value */
+uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc);
+
+/* flag and interrupt functions */
+/* enable SPI and I2S interrupt */
+void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt);
+/* disable SPI and I2S interrupt */
+void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt);
+/* get SPI and I2S interrupt status */
+FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt);
+/* get SPI and I2S flag status */
+FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag);
+/* clear SPI CRC error flag status */
+void spi_crc_error_clear(uint32_t spi_periph);
+
+#endif /* GD32F10X_SPI_H */

+ 728 - 0
Library/Include/gd32f10x_timer.h

@@ -0,0 +1,728 @@
+/*!
+    \file    gd32f10x_timer.h
+    \brief   definitions for the TIMER
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_TIMER_H
+#define GD32F10X_TIMER_H
+
+#include "gd32f10x.h"
+
+/* TIMERx(x=0..13) definitions */
+#define TIMER0                           (TIMER_BASE + 0x00012C00U)
+#define TIMER1                           (TIMER_BASE + 0x00000000U)
+#define TIMER2                           (TIMER_BASE + 0x00000400U)
+#define TIMER3                           (TIMER_BASE + 0x00000800U)
+#define TIMER4                           (TIMER_BASE + 0x00000C00U)
+#define TIMER5                           (TIMER_BASE + 0x00001000U)
+#define TIMER6                           (TIMER_BASE + 0x00001400U)
+#define TIMER7                           (TIMER_BASE + 0x00013400U)
+#define TIMER8                           (TIMER_BASE + 0x00014C00U)
+#define TIMER9                           (TIMER_BASE + 0x00015000U)
+#define TIMER10                          (TIMER_BASE + 0x00015400U)
+#define TIMER11                          (TIMER_BASE + 0x00001800U)
+#define TIMER12                          (TIMER_BASE + 0x00001C00U)
+#define TIMER13                          (TIMER_BASE + 0x00002000U)
+
+/* registers definitions */
+#define TIMER_CTL0(timerx)               REG32((timerx) + 0x00U)           /*!< TIMER control register 0 */
+#define TIMER_CTL1(timerx)               REG32((timerx) + 0x04U)           /*!< TIMER control register 1 */
+#define TIMER_SMCFG(timerx)              REG32((timerx) + 0x08U)           /*!< TIMER slave mode configuration register */
+#define TIMER_DMAINTEN(timerx)           REG32((timerx) + 0x0CU)           /*!< TIMER DMA and interrupt enable register */
+#define TIMER_INTF(timerx)               REG32((timerx) + 0x10U)           /*!< TIMER interrupt flag register */
+#define TIMER_SWEVG(timerx)              REG32((timerx) + 0x14U)           /*!< TIMER software event generation register */
+#define TIMER_CHCTL0(timerx)             REG32((timerx) + 0x18U)           /*!< TIMER channel control register 0 */
+#define TIMER_CHCTL1(timerx)             REG32((timerx) + 0x1CU)           /*!< TIMER channel control register 1 */
+#define TIMER_CHCTL2(timerx)             REG32((timerx) + 0x20U)           /*!< TIMER channel control register 2 */
+#define TIMER_CNT(timerx)                REG32((timerx) + 0x24U)           /*!< TIMER counter register */
+#define TIMER_PSC(timerx)                REG32((timerx) + 0x28U)           /*!< TIMER prescaler register */
+#define TIMER_CAR(timerx)                REG32((timerx) + 0x2CU)           /*!< TIMER counter auto reload register */
+#define TIMER_CREP(timerx)               REG32((timerx) + 0x30U)           /*!< TIMER counter repetition register */
+#define TIMER_CH0CV(timerx)              REG32((timerx) + 0x34U)           /*!< TIMER channel 0 capture/compare value register */
+#define TIMER_CH1CV(timerx)              REG32((timerx) + 0x38U)           /*!< TIMER channel 1 capture/compare value register */
+#define TIMER_CH2CV(timerx)              REG32((timerx) + 0x3CU)           /*!< TIMER channel 2 capture/compare value register */
+#define TIMER_CH3CV(timerx)              REG32((timerx) + 0x40U)           /*!< TIMER channel 3 capture/compare value register */
+#define TIMER_CCHP(timerx)               REG32((timerx) + 0x44U)           /*!< TIMER channel complementary protection register */
+#define TIMER_DMACFG(timerx)             REG32((timerx) + 0x48U)           /*!< TIMER DMA configuration register */
+#define TIMER_DMATB(timerx)              REG32((timerx) + 0x4CU)           /*!< TIMER DMA transfer buffer register */
+
+/* bits definitions */
+/* TIMER_CTL0 */
+#define TIMER_CTL0_CEN                   BIT(0)              /*!< TIMER counter enable */
+#define TIMER_CTL0_UPDIS                 BIT(1)              /*!< update disable */
+#define TIMER_CTL0_UPS                   BIT(2)              /*!< update source */
+#define TIMER_CTL0_SPM                   BIT(3)              /*!< single pulse mode */
+#define TIMER_CTL0_DIR                   BIT(4)              /*!< timer counter direction */
+#define TIMER_CTL0_CAM                   BITS(5,6)           /*!< center-aligned mode selection */
+#define TIMER_CTL0_ARSE                  BIT(7)              /*!< auto-reload shadow enable */
+#define TIMER_CTL0_CKDIV                 BITS(8,9)           /*!< clock division */
+
+/* TIMER_CTL1 */
+#define TIMER_CTL1_CCSE                  BIT(0)              /*!< commutation control shadow enable */
+#define TIMER_CTL1_CCUC                  BIT(2)              /*!< commutation control shadow register update control */
+#define TIMER_CTL1_DMAS                  BIT(3)              /*!< DMA request source selection */
+#define TIMER_CTL1_MMC                   BITS(4,6)           /*!< master mode control */
+#define TIMER_CTL1_TI0S                  BIT(7)              /*!< channel 0 trigger input selection(hall mode selection) */
+#define TIMER_CTL1_ISO0                  BIT(8)              /*!< idle state of channel 0 output */
+#define TIMER_CTL1_ISO0N                 BIT(9)              /*!< idle state of channel 0 complementary output */
+#define TIMER_CTL1_ISO1                  BIT(10)             /*!< idle state of channel 1 output */
+#define TIMER_CTL1_ISO1N                 BIT(11)             /*!< idle state of channel 1 complementary output */
+#define TIMER_CTL1_ISO2                  BIT(12)             /*!< idle state of channel 2 output */
+#define TIMER_CTL1_ISO2N                 BIT(13)             /*!< idle state of channel 2 complementary output */
+#define TIMER_CTL1_ISO3                  BIT(14)             /*!< idle state of channel 3 output */
+
+/* TIMER_SMCFG */
+#define TIMER_SMCFG_SMC                  BITS(0,2)           /*!< slave mode control */
+#define TIMER_SMCFG_TRGS                 BITS(4,6)           /*!< trigger selection */
+#define TIMER_SMCFG_MSM                  BIT(7)              /*!< master-slave mode */
+#define TIMER_SMCFG_ETFC                 BITS(8,11)          /*!< external trigger filter control */
+#define TIMER_SMCFG_ETPSC                BITS(12,13)         /*!< external trigger prescaler */
+#define TIMER_SMCFG_SMC1                 BIT(14)             /*!< part of SMC for enable external clock mode 1 */
+#define TIMER_SMCFG_ETP                  BIT(15)             /*!< external trigger polarity */
+ 
+/* TIMER_DMAINTEN */
+#define TIMER_DMAINTEN_UPIE              BIT(0)              /*!< update interrupt enable */
+#define TIMER_DMAINTEN_CH0IE             BIT(1)              /*!< channel 0 capture/compare interrupt enable */
+#define TIMER_DMAINTEN_CH1IE             BIT(2)              /*!< channel 1 capture/compare interrupt enable */
+#define TIMER_DMAINTEN_CH2IE             BIT(3)              /*!< channel 2 capture/compare interrupt enable */
+#define TIMER_DMAINTEN_CH3IE             BIT(4)              /*!< channel 3 capture/compare interrupt enable */
+#define TIMER_DMAINTEN_CMTIE             BIT(5)              /*!< commutation interrupt request enable */
+#define TIMER_DMAINTEN_TRGIE             BIT(6)              /*!< trigger interrupt enable */
+#define TIMER_DMAINTEN_BRKIE             BIT(7)              /*!< break interrupt enable */
+#define TIMER_DMAINTEN_UPDEN             BIT(8)              /*!< update DMA request enable */
+#define TIMER_DMAINTEN_CH0DEN            BIT(9)              /*!< channel 0 capture/compare DMA request enable */
+#define TIMER_DMAINTEN_CH1DEN            BIT(10)             /*!< channel 1 capture/compare DMA request enable */
+#define TIMER_DMAINTEN_CH2DEN            BIT(11)             /*!< channel 2 capture/compare DMA request enable */
+#define TIMER_DMAINTEN_CH3DEN            BIT(12)             /*!< channel 3 capture/compare DMA request enable */
+#define TIMER_DMAINTEN_CMTDEN            BIT(13)             /*!< commutation DMA request enable */
+#define TIMER_DMAINTEN_TRGDEN            BIT(14)             /*!< trigger DMA request enable */
+
+/* TIMER_INTF */
+#define TIMER_INTF_UPIF                  BIT(0)              /*!< update interrupt flag */
+#define TIMER_INTF_CH0IF                 BIT(1)              /*!< channel 0 capture/compare interrupt flag */
+#define TIMER_INTF_CH1IF                 BIT(2)              /*!< channel 1 capture/compare interrupt flag */
+#define TIMER_INTF_CH2IF                 BIT(3)              /*!< channel 2 capture/compare interrupt flag */
+#define TIMER_INTF_CH3IF                 BIT(4)              /*!< channel 3 capture/compare interrupt flag */
+#define TIMER_INTF_CMTIF                 BIT(5)              /*!< channel commutation interrupt flag */
+#define TIMER_INTF_TRGIF                 BIT(6)              /*!< trigger interrupt flag */
+#define TIMER_INTF_BRKIF                 BIT(7)              /*!< break interrupt flag */
+#define TIMER_INTF_CH0OF                 BIT(9)              /*!< channel 0 over capture flag */
+#define TIMER_INTF_CH1OF                 BIT(10)             /*!< channel 1 over capture flag */
+#define TIMER_INTF_CH2OF                 BIT(11)             /*!< channel 2 over capture flag */
+#define TIMER_INTF_CH3OF                 BIT(12)             /*!< channel 3 over capture flag */
+
+/* TIMER_SWEVG */
+#define TIMER_SWEVG_UPG                  BIT(0)              /*!< update event generate */
+#define TIMER_SWEVG_CH0G                 BIT(1)              /*!< channel 0 capture or compare event generation */
+#define TIMER_SWEVG_CH1G                 BIT(2)              /*!< channel 1 capture or compare event generation */
+#define TIMER_SWEVG_CH2G                 BIT(3)              /*!< channel 2 capture or compare event generation */
+#define TIMER_SWEVG_CH3G                 BIT(4)              /*!< channel 3 capture or compare event generation */
+#define TIMER_SWEVG_CMTG                 BIT(5)              /*!< channel commutation event generation */
+#define TIMER_SWEVG_TRGG                 BIT(6)              /*!< trigger event generation */
+#define TIMER_SWEVG_BRKG                 BIT(7)              /*!< break event generation */
+
+/* TIMER_CHCTL0 */
+/* output compare mode */
+#define TIMER_CHCTL0_CH0MS               BITS(0,1)           /*!< channel 0 mode selection */
+#define TIMER_CHCTL0_CH0COMFEN           BIT(2)              /*!< channel 0 output compare fast enable */
+#define TIMER_CHCTL0_CH0COMSEN           BIT(3)              /*!< channel 0 output compare shadow enable */
+#define TIMER_CHCTL0_CH0COMCTL           BITS(4,6)           /*!< channel 0 output compare control  */
+#define TIMER_CHCTL0_CH0COMCEN           BIT(7)              /*!< channel 0 output compare clear enable */
+#define TIMER_CHCTL0_CH1MS               BITS(8,9)           /*!< channel 1 mode selection */
+#define TIMER_CHCTL0_CH1COMFEN           BIT(10)             /*!< channel 1 output compare fast enable */
+#define TIMER_CHCTL0_CH1COMSEN           BIT(11)             /*!< channel 1 output compare shadow enable */
+#define TIMER_CHCTL0_CH1COMCTL           BITS(12,14)         /*!< channel 1 output compare control  */
+#define TIMER_CHCTL0_CH1COMCEN           BIT(15)             /*!< channel 1 output compare clear enable */
+/* input capture mode */
+#define TIMER_CHCTL0_CH0CAPPSC           BITS(2,3)           /*!< channel 0 input capture prescaler */
+#define TIMER_CHCTL0_CH0CAPFLT           BITS(4,7)           /*!< channel 0 input capture filter control */
+#define TIMER_CHCTL0_CH1CAPPSC           BITS(10,11)         /*!< channel 1 input capture prescaler */
+#define TIMER_CHCTL0_CH1CAPFLT           BITS(12,15)         /*!< channel 1 input capture filter control */
+
+/* TIMER_CHCTL1 */
+/* output compare mode */
+#define TIMER_CHCTL1_CH2MS               BITS(0,1)           /*!< channel 2 mode selection */
+#define TIMER_CHCTL1_CH2COMFEN           BIT(2)              /*!< channel 2 output compare fast enable */
+#define TIMER_CHCTL1_CH2COMSEN           BIT(3)              /*!< channel 2 output compare shadow enable */
+#define TIMER_CHCTL1_CH2COMCTL           BITS(4,6)           /*!< channel 2 output compare control */
+#define TIMER_CHCTL1_CH2COMCEN           BIT(7)              /*!< channel 2 output compare clear enable */
+#define TIMER_CHCTL1_CH3MS               BITS(8,9)           /*!< channel 3 mode selection */
+#define TIMER_CHCTL1_CH3COMFEN           BIT(10)             /*!< channel 3 output compare fast enable */
+#define TIMER_CHCTL1_CH3COMSEN           BIT(11)             /*!< channel 3 output compare shadow enable */
+#define TIMER_CHCTL1_CH3COMCTL           BITS(12,14)         /*!< channel 3 output compare control */
+#define TIMER_CHCTL1_CH3COMCEN           BIT(15)             /*!< channel 3 output compare clear enable */
+/* input capture mode */
+#define TIMER_CHCTL1_CH2CAPPSC           BITS(2,3)           /*!< channel 2 input capture prescaler */
+#define TIMER_CHCTL1_CH2CAPFLT           BITS(4,7)           /*!< channel 2 input capture filter control */
+#define TIMER_CHCTL1_CH3CAPPSC           BITS(10,11)         /*!< channel 3 input capture prescaler */
+#define TIMER_CHCTL1_CH3CAPFLT           BITS(12,15)         /*!< channel 3 input capture filter control */
+
+/* TIMER_CHCTL2 */
+#define TIMER_CHCTL2_CH0EN               BIT(0)              /*!< channel 0 capture/compare function enable */
+#define TIMER_CHCTL2_CH0P                BIT(1)              /*!< channel 0 capture/compare function polarity */
+#define TIMER_CHCTL2_CH0NEN              BIT(2)              /*!< channel 0 complementary output enable */
+#define TIMER_CHCTL2_CH0NP               BIT(3)              /*!< channel 0 complementary output polarity */
+#define TIMER_CHCTL2_CH1EN               BIT(4)              /*!< channel 1 capture/compare function enable  */
+#define TIMER_CHCTL2_CH1P                BIT(5)              /*!< channel 1 capture/compare function polarity */
+#define TIMER_CHCTL2_CH1NEN              BIT(6)              /*!< channel 1 complementary output enable */
+#define TIMER_CHCTL2_CH1NP               BIT(7)              /*!< channel 1 complementary output polarity */
+#define TIMER_CHCTL2_CH2EN               BIT(8)              /*!< channel 2 capture/compare function enable  */
+#define TIMER_CHCTL2_CH2P                BIT(9)              /*!< channel 2 capture/compare function polarity */
+#define TIMER_CHCTL2_CH2NEN              BIT(10)             /*!< channel 2 complementary output enable */
+#define TIMER_CHCTL2_CH2NP               BIT(11)             /*!< channel 2 complementary output polarity */
+#define TIMER_CHCTL2_CH3EN               BIT(12)             /*!< channel 3 capture/compare function enable  */
+#define TIMER_CHCTL2_CH3P                BIT(13)             /*!< channel 3 capture/compare function polarity */
+
+/* TIMER_CNT */
+#define TIMER_CNT_CNT                    BITS(0,15)          /*!< 16 bit timer counter */
+
+/* TIMER_PSC */
+#define TIMER_PSC_PSC                    BITS(0,15)          /*!< prescaler value of the counter clock */
+
+/* TIMER_CAR */
+#define TIMER_CAR_CARL                   BITS(0,15)          /*!< 16 bit counter auto reload value */
+
+/* TIMER_CREP */
+#define TIMER_CREP_CREP                  BITS(0,7)           /*!< counter repetition value */
+
+/* TIMER_CH0CV */
+#define TIMER_CH0CV_CH0VAL               BITS(0,15)          /*!< 16 bit capture/compare value of channel 0 */
+
+/* TIMER_CH1CV */
+#define TIMER_CH1CV_CH1VAL               BITS(0,15)          /*!< 16 bit capture/compare value of channel 1 */
+
+/* TIMER_CH2CV */
+#define TIMER_CH2CV_CH2VAL               BITS(0,15)          /*!< 16 bit capture/compare value of channel 2 */
+
+/* TIMER_CH3CV */
+#define TIMER_CH3CV_CH3VAL               BITS(0,15)          /*!< 16 bit capture/compare value of channel 3 */
+
+/* TIMER_CCHP */
+#define TIMER_CCHP_DTCFG                 BITS(0,7)           /*!< dead time configure */
+#define TIMER_CCHP_PROT                  BITS(8,9)           /*!< complementary register protect control */
+#define TIMER_CCHP_IOS                   BIT(10)             /*!< idle mode off-state configure */
+#define TIMER_CCHP_ROS                   BIT(11)             /*!< run mode off-state configure */
+#define TIMER_CCHP_BRKEN                 BIT(12)             /*!< break enable */
+#define TIMER_CCHP_BRKP                  BIT(13)             /*!< break polarity */
+#define TIMER_CCHP_OAEN                  BIT(14)             /*!< output automatic enable */
+#define TIMER_CCHP_POEN                  BIT(15)             /*!< primary output enable */
+
+/* TIMER_DMACFG */
+#define TIMER_DMACFG_DMATA               BITS(0,4)           /*!< DMA transfer access start address */
+#define TIMER_DMACFG_DMATC               BITS(8,12)          /*!< DMA transfer count */
+
+/* TIMER_DMATB */
+#define TIMER_DMATB_DMATB                BITS(0,15)          /*!< DMA transfer buffer address */
+
+/* constants definitions */
+/* TIMER init parameter struct definitions */
+typedef struct
+{ 
+    uint16_t prescaler;                         /*!< prescaler value */
+    uint16_t alignedmode;                       /*!< aligned mode */
+    uint16_t counterdirection;                  /*!< counter direction */
+    uint32_t period;                            /*!< period value */
+    uint16_t clockdivision;                     /*!< clock division value */
+    uint8_t  repetitioncounter;                 /*!< the counter repetition value */
+}timer_parameter_struct;
+
+/* break parameter struct definitions*/
+typedef struct
+{ 
+    uint16_t runoffstate;                       /*!< run mode off-state */
+    uint16_t ideloffstate;                      /*!< idle mode off-state */
+    uint16_t deadtime;                          /*!< dead time */
+    uint16_t breakpolarity;                     /*!< break polarity */
+    uint16_t outputautostate;                   /*!< output automatic enable */
+    uint16_t protectmode;                       /*!< complementary register protect control */
+    uint16_t breakstate;                        /*!< break enable */
+}timer_break_parameter_struct;
+
+/* channel output parameter struct definitions */
+typedef struct
+{ 
+    uint16_t outputstate;                       /*!< channel output state */
+    uint16_t outputnstate;                      /*!< channel complementary output state */
+    uint16_t ocpolarity;                        /*!< channel output polarity */
+    uint16_t ocnpolarity;                       /*!< channel complementary output polarity */
+    uint16_t ocidlestate;                       /*!< idle state of channel output */
+    uint16_t ocnidlestate;                      /*!< idle state of channel complementary output */
+}timer_oc_parameter_struct;
+
+/* channel input parameter struct definitions */
+typedef struct
+{ 
+    uint16_t icpolarity;                        /*!< channel input polarity */
+    uint16_t icselection;                       /*!< channel input mode selection */
+    uint16_t icprescaler;                       /*!< channel input capture prescaler */
+    uint16_t icfilter;                          /*!< channel input capture filter control */
+}timer_ic_parameter_struct;
+
+/* TIMER interrupt enable or disable */
+#define TIMER_INT_UP                        TIMER_DMAINTEN_UPIE                     /*!< update interrupt */
+#define TIMER_INT_CH0                       TIMER_DMAINTEN_CH0IE                    /*!< channel 0 interrupt */
+#define TIMER_INT_CH1                       TIMER_DMAINTEN_CH1IE                    /*!< channel 1 interrupt */
+#define TIMER_INT_CH2                       TIMER_DMAINTEN_CH2IE                    /*!< channel 2 interrupt */
+#define TIMER_INT_CH3                       TIMER_DMAINTEN_CH3IE                    /*!< channel 3 interrupt */
+#define TIMER_INT_CMT                       TIMER_DMAINTEN_CMTIE                    /*!< channel commutation interrupt flag */
+#define TIMER_INT_TRG                       TIMER_DMAINTEN_TRGIE                    /*!< trigger interrupt */
+#define TIMER_INT_BRK                       TIMER_DMAINTEN_BRKIE                    /*!< break interrupt */
+
+/* TIMER interrupt flag */
+#define TIMER_INT_FLAG_UP                   TIMER_INT_UP                            /*!< update interrupt */
+#define TIMER_INT_FLAG_CH0                  TIMER_INT_CH0                           /*!< channel 0 interrupt */
+#define TIMER_INT_FLAG_CH1                  TIMER_INT_CH1                           /*!< channel 1 interrupt */
+#define TIMER_INT_FLAG_CH2                  TIMER_INT_CH2                           /*!< channel 2 interrupt */
+#define TIMER_INT_FLAG_CH3                  TIMER_INT_CH3                           /*!< channel 3 interrupt */
+#define TIMER_INT_FLAG_CMT                  TIMER_INT_CMT                           /*!< channel commutation interrupt flag */
+#define TIMER_INT_FLAG_TRG                  TIMER_INT_TRG                           /*!< trigger interrupt */
+#define TIMER_INT_FLAG_BRK                  TIMER_INT_BRK  
+
+/* TIMER flag */
+#define TIMER_FLAG_UP                       TIMER_INTF_UPIF                         /*!< update flag */
+#define TIMER_FLAG_CH0                      TIMER_INTF_CH0IF                        /*!< channel 0 flag */
+#define TIMER_FLAG_CH1                      TIMER_INTF_CH1IF                        /*!< channel 1 flag */
+#define TIMER_FLAG_CH2                      TIMER_INTF_CH2IF                        /*!< channel 2 flag */
+#define TIMER_FLAG_CH3                      TIMER_INTF_CH3IF                        /*!< channel 3 flag */
+#define TIMER_FLAG_CMT                      TIMER_INTF_CMTIF                        /*!< channel commutation flag */
+#define TIMER_FLAG_TRG                      TIMER_INTF_TRGIF                        /*!< trigger flag */
+#define TIMER_FLAG_BRK                      TIMER_INTF_BRKIF                        /*!< break flag */
+#define TIMER_FLAG_CH0O                     TIMER_INTF_CH0OF                        /*!< channel 0 overcapture flag */
+#define TIMER_FLAG_CH1O                     TIMER_INTF_CH1OF                        /*!< channel 1 overcapture flag */
+#define TIMER_FLAG_CH2O                     TIMER_INTF_CH2OF                        /*!< channel 2 overcapture flag */
+#define TIMER_FLAG_CH3O                     TIMER_INTF_CH3OF                        /*!< channel 3 overcapture flag */
+/* TIMER DMA source enable */
+#define TIMER_DMA_UPD                       ((uint16_t)TIMER_DMAINTEN_UPDEN)        /*!< update DMA enable */
+#define TIMER_DMA_CH0D                      ((uint16_t)TIMER_DMAINTEN_CH0DEN)       /*!< channel 0 DMA enable */
+#define TIMER_DMA_CH1D                      ((uint16_t)TIMER_DMAINTEN_CH1DEN)       /*!< channel 1 DMA enable */
+#define TIMER_DMA_CH2D                      ((uint16_t)TIMER_DMAINTEN_CH2DEN)       /*!< channel 2 DMA enable */
+#define TIMER_DMA_CH3D                      ((uint16_t)TIMER_DMAINTEN_CH3DEN)       /*!< channel 3 DMA enable */
+#define TIMER_DMA_CMTD                      ((uint16_t)TIMER_DMAINTEN_CMTDEN)       /*!< commutation DMA request enable */
+#define TIMER_DMA_TRGD                      ((uint16_t)TIMER_DMAINTEN_TRGDEN)       /*!< trigger DMA enable */
+
+/* channel DMA request source selection */ 
+#define TIMER_DMAREQUEST_UPDATEEVENT        TIMER_CTL1_DMAS                         /*!< DMA request of channel n is sent when update event occurs */
+#define TIMER_DMAREQUEST_CHANNELEVENT       ((uint32_t)0x00000000U)                 /*!< DMA request of channel n is sent when channel n event occurs */
+
+/* DMA access base address */
+#define DMACFG_DMATA(regval)                (BITS(0, 4) & ((uint32_t)(regval) << 0U))
+#define TIMER_DMACFG_DMATA_CTL0             DMACFG_DMATA(0)                         /*!< DMA transfer address is TIMER_CTL0 */
+#define TIMER_DMACFG_DMATA_CTL1             DMACFG_DMATA(1)                         /*!< DMA transfer address is TIMER_CTL1 */
+#define TIMER_DMACFG_DMATA_SMCFG            DMACFG_DMATA(2)                         /*!< DMA transfer address is TIMER_SMCFG */
+#define TIMER_DMACFG_DMATA_DMAINTEN         DMACFG_DMATA(3)                         /*!< DMA transfer address is TIMER_DMAINTEN */
+#define TIMER_DMACFG_DMATA_INTF             DMACFG_DMATA(4)                         /*!< DMA transfer address is TIMER_INTF */
+#define TIMER_DMACFG_DMATA_SWEVG            DMACFG_DMATA(5)                         /*!< DMA transfer address is TIMER_SWEVG */
+#define TIMER_DMACFG_DMATA_CHCTL0           DMACFG_DMATA(6)                         /*!< DMA transfer address is TIMER_CHCTL0 */
+#define TIMER_DMACFG_DMATA_CHCTL1           DMACFG_DMATA(7)                         /*!< DMA transfer address is TIMER_CHCTL1 */
+#define TIMER_DMACFG_DMATA_CHCTL2           DMACFG_DMATA(8)                         /*!< DMA transfer address is TIMER_CHCTL2 */
+#define TIMER_DMACFG_DMATA_CNT              DMACFG_DMATA(9)                         /*!< DMA transfer address is TIMER_CNT */
+#define TIMER_DMACFG_DMATA_PSC              DMACFG_DMATA(10)                        /*!< DMA transfer address is TIMER_PSC */
+#define TIMER_DMACFG_DMATA_CAR              DMACFG_DMATA(11)                        /*!< DMA transfer address is TIMER_CAR */
+#define TIMER_DMACFG_DMATA_CREP             DMACFG_DMATA(12)                        /*!< DMA transfer address is TIMER_CREP */
+#define TIMER_DMACFG_DMATA_CH0CV            DMACFG_DMATA(13)                        /*!< DMA transfer address is TIMER_CH0CV */
+#define TIMER_DMACFG_DMATA_CH1CV            DMACFG_DMATA(14)                        /*!< DMA transfer address is TIMER_CH1CV */
+#define TIMER_DMACFG_DMATA_CH2CV            DMACFG_DMATA(15)                        /*!< DMA transfer address is TIMER_CH2CV */
+#define TIMER_DMACFG_DMATA_CH3CV            DMACFG_DMATA(16)                        /*!< DMA transfer address is TIMER_CH3CV */
+#define TIMER_DMACFG_DMATA_CCHP             DMACFG_DMATA(17)                        /*!< DMA transfer address is TIMER_CCHP */
+#define TIMER_DMACFG_DMATA_DMACFG           DMACFG_DMATA(18)                        /*!< DMA transfer address is TIMER_DMACFG */
+
+/* DMA access burst length */
+#define DMACFG_DMATC(regval)                (BITS(8, 12) & ((uint32_t)(regval) << 8U))
+#define TIMER_DMACFG_DMATC_1TRANSFER        DMACFG_DMATC(0)                         /*!< DMA transfer 1 time */
+#define TIMER_DMACFG_DMATC_2TRANSFER        DMACFG_DMATC(1)                         /*!< DMA transfer 2 times */
+#define TIMER_DMACFG_DMATC_3TRANSFER        DMACFG_DMATC(2)                         /*!< DMA transfer 3 times */
+#define TIMER_DMACFG_DMATC_4TRANSFER        DMACFG_DMATC(3)                         /*!< DMA transfer 4 times */
+#define TIMER_DMACFG_DMATC_5TRANSFER        DMACFG_DMATC(4)                         /*!< DMA transfer 5 times */
+#define TIMER_DMACFG_DMATC_6TRANSFER        DMACFG_DMATC(5)                         /*!< DMA transfer 6 times */
+#define TIMER_DMACFG_DMATC_7TRANSFER        DMACFG_DMATC(6)                         /*!< DMA transfer 7 times */
+#define TIMER_DMACFG_DMATC_8TRANSFER        DMACFG_DMATC(7)                         /*!< DMA transfer 8 times */
+#define TIMER_DMACFG_DMATC_9TRANSFER        DMACFG_DMATC(8)                         /*!< DMA transfer 9 times */
+#define TIMER_DMACFG_DMATC_10TRANSFER       DMACFG_DMATC(9)                         /*!< DMA transfer 10 times */
+#define TIMER_DMACFG_DMATC_11TRANSFER       DMACFG_DMATC(10)                        /*!< DMA transfer 11 times */
+#define TIMER_DMACFG_DMATC_12TRANSFER       DMACFG_DMATC(11)                        /*!< DMA transfer 12 times */
+#define TIMER_DMACFG_DMATC_13TRANSFER       DMACFG_DMATC(12)                        /*!< DMA transfer 13 times */
+#define TIMER_DMACFG_DMATC_14TRANSFER       DMACFG_DMATC(13)                        /*!< DMA transfer 14 times */
+#define TIMER_DMACFG_DMATC_15TRANSFER       DMACFG_DMATC(14)                        /*!< DMA transfer 15 times */
+#define TIMER_DMACFG_DMATC_16TRANSFER       DMACFG_DMATC(15)                        /*!< DMA transfer 16 times */
+#define TIMER_DMACFG_DMATC_17TRANSFER       DMACFG_DMATC(16)                        /*!< DMA transfer 17 times */
+#define TIMER_DMACFG_DMATC_18TRANSFER       DMACFG_DMATC(17)                        /*!< DMA transfer 18 times */
+
+/* TIMER software event generation source */
+#define TIMER_EVENT_SRC_UPG                 ((uint16_t)0x0001U)                     /*!< update event generation */
+#define TIMER_EVENT_SRC_CH0G                ((uint16_t)0x0002U)                     /*!< channel 0 capture or compare event generation */
+#define TIMER_EVENT_SRC_CH1G                ((uint16_t)0x0004U)                     /*!< channel 1 capture or compare event generation */
+#define TIMER_EVENT_SRC_CH2G                ((uint16_t)0x0008U)                     /*!< channel 2 capture or compare event generation */
+#define TIMER_EVENT_SRC_CH3G                ((uint16_t)0x0010U)                     /*!< channel 3 capture or compare event generation */
+#define TIMER_EVENT_SRC_CMTG                ((uint16_t)0x0020U)                     /*!< channel commutation event generation */
+#define TIMER_EVENT_SRC_TRGG                ((uint16_t)0x0040U)                     /*!< trigger event generation */
+#define TIMER_EVENT_SRC_BRKG                ((uint16_t)0x0080U)                     /*!< break event generation */
+
+/* center-aligned mode selection */
+#define CTL0_CAM(regval)                    ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U)))
+#define TIMER_COUNTER_EDGE                  CTL0_CAM(0)                             /*!< edge-aligned mode */
+#define TIMER_COUNTER_CENTER_DOWN           CTL0_CAM(1)                             /*!< center-aligned and counting down assert mode */
+#define TIMER_COUNTER_CENTER_UP             CTL0_CAM(2)                             /*!< center-aligned and counting up assert mode */
+#define TIMER_COUNTER_CENTER_BOTH           CTL0_CAM(3)                             /*!< center-aligned and counting up/down assert mode */
+
+/* TIMER prescaler reload mode */
+#define TIMER_PSC_RELOAD_NOW                TIMER_SWEVG_UPG                         /*!< the prescaler is loaded right now */
+#define TIMER_PSC_RELOAD_UPDATE             ((uint32_t)0x00000000U)                 /*!< the prescaler is loaded at the next update event */
+
+/* count direction */
+#define TIMER_COUNTER_UP                    ((uint16_t)0x0000U)                     /*!< counter up direction */
+#define TIMER_COUNTER_DOWN                  ((uint16_t)TIMER_CTL0_DIR)              /*!< counter down direction */
+
+/* specify division ratio between TIMER clock and dead-time and sampling clock */
+#define CTL0_CKDIV(regval)                  ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U)))
+#define TIMER_CKDIV_DIV1                    CTL0_CKDIV(0)                           /*!< clock division value is 1,fDTS=fTIMER_CK */
+#define TIMER_CKDIV_DIV2                    CTL0_CKDIV(1)                           /*!< clock division value is 2,fDTS= fTIMER_CK/2 */
+#define TIMER_CKDIV_DIV4                    CTL0_CKDIV(2)                           /*!< clock division value is 4, fDTS= fTIMER_CK/4 */
+
+/* single pulse mode */
+#define TIMER_SP_MODE_SINGLE                TIMER_CTL0_SPM                          /*!< single pulse mode */
+#define TIMER_SP_MODE_REPETITIVE            ((uint32_t)0x00000000U)                 /*!< repetitive pulse mode */
+
+/* update source */
+#define TIMER_UPDATE_SRC_REGULAR            TIMER_CTL0_UPS                          /*!< update generate only by counter overflow/underflow */
+#define TIMER_UPDATE_SRC_GLOBAL             ((uint32_t)0x00000000U)                 /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */
+
+/* run mode off-state configure */
+#define TIMER_ROS_STATE_ENABLE              ((uint16_t)TIMER_CCHP_ROS)              /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */
+#define TIMER_ROS_STATE_DISABLE             ((uint16_t)0x0000U)                     /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */
+
+/* idle mode off-state configure */                                                 
+#define TIMER_IOS_STATE_ENABLE              ((uint16_t)TIMER_CCHP_IOS)              /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */
+#define TIMER_IOS_STATE_DISABLE             ((uint16_t)0x0000U)                     /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */
+
+/* break input polarity */
+#define TIMER_BREAK_POLARITY_LOW            ((uint16_t)0x0000U)                     /*!< break input polarity is low */
+#define TIMER_BREAK_POLARITY_HIGH           ((uint16_t)TIMER_CCHP_BRKP)             /*!< break input polarity is high */
+
+/* output automatic enable */
+#define TIMER_OUTAUTO_ENABLE                ((uint16_t)TIMER_CCHP_OAEN)             /*!< output automatic enable */
+#define TIMER_OUTAUTO_DISABLE               ((uint16_t)0x0000U)                     /*!< output automatic disable */
+
+/* complementary register protect control */
+#define CCHP_PROT(regval)                   ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U)))
+#define TIMER_CCHP_PROT_OFF                 CCHP_PROT(0)                            /*!< protect disable */
+#define TIMER_CCHP_PROT_0                   CCHP_PROT(1)                            /*!< PROT mode 0 */
+#define TIMER_CCHP_PROT_1                   CCHP_PROT(2)                            /*!< PROT mode 1 */
+#define TIMER_CCHP_PROT_2                   CCHP_PROT(3)                            /*!< PROT mode 2 */
+
+/* break input enable */
+#define TIMER_BREAK_ENABLE                  ((uint16_t)TIMER_CCHP_BRKEN)            /*!< break input enable */
+#define TIMER_BREAK_DISABLE                 ((uint16_t)0x0000U)                     /*!< break input disable */
+
+/* TIMER channel n(n=0,1,2,3) */
+#define TIMER_CH_0                          ((uint16_t)0x0000U)                     /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */
+#define TIMER_CH_1                          ((uint16_t)0x0001U)                     /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */
+#define TIMER_CH_2                          ((uint16_t)0x0002U)                     /*!< TIMER channel 2(TIMERx(x=0..4,7)) */
+#define TIMER_CH_3                          ((uint16_t)0x0003U)                     /*!< TIMER channel 3(TIMERx(x=0..4,7)) */
+
+/* channel enable state */
+#define TIMER_CCX_ENABLE                    ((uint16_t)0x0001U)                     /*!< channel enable */
+#define TIMER_CCX_DISABLE                   ((uint16_t)0x0000U)                     /*!< channel disable */
+
+/* channel complementary output enable state */
+#define TIMER_CCXN_ENABLE                   ((uint16_t)0x0004U)                     /*!< channel complementary enable */
+#define TIMER_CCXN_DISABLE                  ((uint16_t)0x0000U)                     /*!< channel complementary disable */
+
+/* channel output polarity */
+#define TIMER_OC_POLARITY_HIGH              ((uint16_t)0x0000U)                     /*!< channel output polarity is high */
+#define TIMER_OC_POLARITY_LOW               ((uint16_t)0x0002U)                     /*!< channel output polarity is low */
+
+/* channel complementary output polarity */
+#define TIMER_OCN_POLARITY_HIGH             ((uint16_t)0x0000U)                     /*!< channel complementary output polarity is high */
+#define TIMER_OCN_POLARITY_LOW              ((uint16_t)0x0008U)                     /*!< channel complementary output polarity is low */
+
+/* idle state of channel output */ 
+#define TIMER_OC_IDLE_STATE_HIGH            ((uint16_t)0x0100)                      /*!< idle state of channel output is high */
+#define TIMER_OC_IDLE_STATE_LOW             ((uint16_t)0x0000)                      /*!< idle state of channel output is low */
+
+/* idle state of channel complementary output */ 
+#define TIMER_OCN_IDLE_STATE_HIGH           ((uint16_t)0x0200U)                     /*!< idle state of channel complementary output is high */
+#define TIMER_OCN_IDLE_STATE_LOW            ((uint16_t)0x0000U)                     /*!< idle state of channel complementary output is low */
+
+/* channel output compare mode */
+#define TIMER_OC_MODE_TIMING                ((uint16_t)0x0000U)                     /*!< frozen mode */
+#define TIMER_OC_MODE_ACTIVE                ((uint16_t)0x0010U)                     /*!< set the channel output */
+#define TIMER_OC_MODE_INACTIVE              ((uint16_t)0x0020U)                     /*!< clear the channel output */
+#define TIMER_OC_MODE_TOGGLE                ((uint16_t)0x0030U)                     /*!< toggle on match */
+#define TIMER_OC_MODE_LOW                   ((uint16_t)0x0040U)                     /*!< force low mode */
+#define TIMER_OC_MODE_HIGH                  ((uint16_t)0x0050U)                     /*!< force high mode */
+#define TIMER_OC_MODE_PWM0                  ((uint16_t)0x0060U)                     /*!< PWM0 mode */
+#define TIMER_OC_MODE_PWM1                  ((uint16_t)0x0070U)                     /*!< PWM1 mode*/
+
+/* channel output compare shadow enable */
+#define TIMER_OC_SHADOW_ENABLE              ((uint16_t)0x0008U)                     /*!< channel output shadow state enable */
+#define TIMER_OC_SHADOW_DISABLE             ((uint16_t)0x0000U)                     /*!< channel output shadow state disable */
+
+/* channel output compare fast enable */
+#define TIMER_OC_FAST_ENABLE                ((uint16_t)0x0004)                      /*!< channel output fast function enable */
+#define TIMER_OC_FAST_DISABLE               ((uint16_t)0x0000)                      /*!< channel output fast function disable */
+
+/* channel output compare clear enable */
+#define TIMER_OC_CLEAR_ENABLE               ((uint16_t)0x0080U)                     /*!< channel output clear function enable */
+#define TIMER_OC_CLEAR_DISABLE              ((uint16_t)0x0000U)                     /*!< channel output clear function disable */
+
+/* channel control shadow register update control */ 
+#define TIMER_UPDATECTL_CCU                 ((uint32_t)0x00000000U)                 /*!< the shadow registers update by when CMTG bit is set */
+#define TIMER_UPDATECTL_CCUTRI              TIMER_CTL1_CCUC                         /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */
+
+/* channel input capture polarity */
+#define TIMER_IC_POLARITY_RISING            ((uint16_t)0x0000U)                     /*!< input capture rising edge */
+#define TIMER_IC_POLARITY_FALLING           ((uint16_t)0x0002U)                     /*!< input capture falling edge */
+
+/* timer input capture selection */
+#define TIMER_IC_SELECTION_DIRECTTI         ((uint16_t)0x0001U)                     /*!< channel y is configured as input and icy is mapped on CIy */
+#define TIMER_IC_SELECTION_INDIRECTTI       ((uint16_t)0x0002U)                     /*!< channel y is configured as input and icy is mapped on opposite input */
+#define TIMER_IC_SELECTION_ITS              ((uint16_t)0x0003U)                     /*!< channel y is configured as input and icy is mapped on ITS */
+
+/* channel input capture prescaler */
+#define TIMER_IC_PSC_DIV1                   ((uint16_t)0x0000U)                     /*!< no prescaler */
+#define TIMER_IC_PSC_DIV2                   ((uint16_t)0x0004U)                     /*!< divided by 2 */
+#define TIMER_IC_PSC_DIV4                   ((uint16_t)0x0008U)                     /*!< divided by 4 */
+#define TIMER_IC_PSC_DIV8                   ((uint16_t)0x000CU)                     /*!< divided by 8 */
+
+/* trigger selection */
+#define SMCFG_TRGSEL(regval)                (BITS(4, 6) & ((uint32_t)(regval) << 4U))
+#define TIMER_SMCFG_TRGSEL_ITI0             SMCFG_TRGSEL(0)                         /*!< internal trigger 0 */
+#define TIMER_SMCFG_TRGSEL_ITI1             SMCFG_TRGSEL(1)                         /*!< internal trigger 1 */
+#define TIMER_SMCFG_TRGSEL_ITI2             SMCFG_TRGSEL(2)                         /*!< internal trigger 2 */
+#define TIMER_SMCFG_TRGSEL_ITI3             SMCFG_TRGSEL(3)                         /*!< internal trigger 3 */
+#define TIMER_SMCFG_TRGSEL_CI0F_ED          SMCFG_TRGSEL(4)                         /*!< TI0 Edge Detector */
+#define TIMER_SMCFG_TRGSEL_CI0FE0           SMCFG_TRGSEL(5)                         /*!< filtered TIMER input 0 */
+#define TIMER_SMCFG_TRGSEL_CI1FE1           SMCFG_TRGSEL(6)                         /*!< filtered TIMER input 1 */
+#define TIMER_SMCFG_TRGSEL_ETIFP            SMCFG_TRGSEL(7)                         /*!< external trigger */
+
+/* master mode control */
+#define CTL1_MMC(regval)                    (BITS(4, 6) & ((uint32_t)(regval) << 4U))
+#define TIMER_TRI_OUT_SRC_RESET             CTL1_MMC(0)                             /*!< the UPG bit as trigger output */
+#define TIMER_TRI_OUT_SRC_ENABLE            CTL1_MMC(1)                             /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */
+#define TIMER_TRI_OUT_SRC_UPDATE            CTL1_MMC(2)                             /*!< update event as trigger output */
+#define TIMER_TRI_OUT_SRC_CH0               CTL1_MMC(3)                             /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */
+#define TIMER_TRI_OUT_SRC_O0CPRE            CTL1_MMC(4)                             /*!< O0CPRE as trigger output */
+#define TIMER_TRI_OUT_SRC_O1CPRE            CTL1_MMC(5)                             /*!< O1CPRE as trigger output */
+#define TIMER_TRI_OUT_SRC_O2CPRE            CTL1_MMC(6)                             /*!< O2CPRE as trigger output */
+#define TIMER_TRI_OUT_SRC_O3CPRE            CTL1_MMC(7)                             /*!< O3CPRE as trigger output */
+
+/* slave mode control */
+#define SMCFG_SMC(regval)                   (BITS(0, 2) & ((uint32_t)(regval) << 0U)) 
+#define TIMER_SLAVE_MODE_DISABLE            SMCFG_SMC(0)                            /*!< slave mode disable */
+#define TIMER_ENCODER_MODE0                 SMCFG_SMC(1)                            /*!< encoder mode 0 */
+#define TIMER_ENCODER_MODE1                 SMCFG_SMC(2)                            /*!< encoder mode 1 */
+#define TIMER_ENCODER_MODE2                 SMCFG_SMC(3)                            /*!< encoder mode 2 */
+#define TIMER_SLAVE_MODE_RESTART            SMCFG_SMC(4)                            /*!< restart mode */
+#define TIMER_SLAVE_MODE_PAUSE              SMCFG_SMC(5)                            /*!< pause mode */
+#define TIMER_SLAVE_MODE_EVENT              SMCFG_SMC(6)                            /*!< event mode */
+#define TIMER_SLAVE_MODE_EXTERNAL0          SMCFG_SMC(7)                            /*!< external clock mode 0 */
+
+/* master slave mode selection */ 
+#define TIMER_MASTER_SLAVE_MODE_ENABLE      TIMER_SMCFG_MSM                         /*!< master slave mode enable */
+#define TIMER_MASTER_SLAVE_MODE_DISABLE     ((uint32_t)0x00000000U)                 /*!< master slave mode disable */
+
+/* external trigger prescaler */
+#define SMCFG_ETPSC(regval)                 (BITS(12, 13) & ((uint32_t)(regval) << 12U))
+#define TIMER_EXT_TRI_PSC_OFF               SMCFG_ETPSC(0)                          /*!< no divided */
+#define TIMER_EXT_TRI_PSC_DIV2              SMCFG_ETPSC(1)                          /*!< divided by 2 */
+#define TIMER_EXT_TRI_PSC_DIV4              SMCFG_ETPSC(2)                          /*!< divided by 4 */
+#define TIMER_EXT_TRI_PSC_DIV8              SMCFG_ETPSC(3)                          /*!< divided by 8 */
+
+/* external trigger polarity */
+#define TIMER_ETP_FALLING                   TIMER_SMCFG_ETP                         /*!< active low or falling edge active */
+#define TIMER_ETP_RISING                    ((uint32_t)0x00000000U)                 /*!< active high or rising edge active */
+
+/* channel 0 trigger input selection */ 
+#define TIMER_HALLINTERFACE_ENABLE          TIMER_CTL1_TI0S                         /*!< TIMER hall sensor mode enable */
+#define TIMER_HALLINTERFACE_DISABLE         ((uint32_t)0x00000000U)                 /*!< TIMER hall sensor mode disable */
+
+/* TIMERx(x=0..4,7..13) write CHxVAL register selection */
+#define TIMER_CHVSEL_ENABLE                 ((uint16_t)TIMER_CFG_OUTSEL)            /*!< write CHxVAL register selection enable */
+#define TIMER_CHVSEL_DISABLE                ((uint16_t)0x0000U)                     /*!< write CHxVAL register selection disable */
+
+/* function declarations */
+/* TIMER timebase */
+/* deinit a TIMER */
+void timer_deinit(uint32_t timer_periph);
+/* initialize TIMER init parameter struct */
+void timer_struct_para_init(timer_parameter_struct* initpara);
+/* initialize TIMER counter */
+void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);
+/* enable a TIMER */
+void timer_enable(uint32_t timer_periph);
+/* disable a TIMER */
+void timer_disable(uint32_t timer_periph);
+/* enable the auto reload shadow function */
+void timer_auto_reload_shadow_enable(uint32_t timer_periph);
+/* disable the auto reload shadow function */
+void timer_auto_reload_shadow_disable(uint32_t timer_periph);
+/* enable the update event */
+void timer_update_event_enable(uint32_t timer_periph);
+/* disable the update event */
+void timer_update_event_disable(uint32_t timer_periph);
+/* set TIMER counter alignment mode */
+void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned);
+/* set TIMER counter up direction */
+void timer_counter_up_direction(uint32_t timer_periph);
+/* set TIMER counter down direction */
+void timer_counter_down_direction(uint32_t timer_periph);
+/* configure TIMER prescaler */
+void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload);
+/* configure TIMER repetition register value */
+void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition);
+/* configure TIMER autoreload register value */
+void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload);
+/* configure TIMER counter register value */
+void timer_counter_value_config(uint32_t timer_periph, uint32_t counter);
+/* read TIMER counter value */
+uint32_t timer_counter_read(uint32_t timer_periph);
+/* read TIMER prescaler value */
+uint16_t timer_prescaler_read(uint32_t timer_periph);
+/* configure TIMER single pulse mode */
+void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode);
+/* configure TIMER update source */
+void timer_update_source_config(uint32_t timer_periph, uint32_t update);
+
+/* timer DMA and event */
+/* enable the TIMER DMA */
+void timer_dma_enable(uint32_t timer_periph, uint16_t dma);
+/* disable the TIMER DMA */
+void timer_dma_disable(uint32_t timer_periph, uint16_t dma);
+/* channel DMA request source selection */
+void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request);
+/* configure the TIMER DMA transfer */
+void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth);
+/* software generate events */
+void timer_event_software_generate(uint32_t timer_periph, uint16_t event);
+
+/* TIMER channel complementary protection */
+/* initialize TIMER break parameter struct */
+void timer_break_struct_para_init(timer_break_parameter_struct* breakpara);
+/* configure TIMER break function */
+void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara);
+/* enable TIMER break function */
+void timer_break_enable(uint32_t timer_periph);
+/* disable TIMER break function */
+void timer_break_disable(uint32_t timer_periph);
+/* enable TIMER output automatic function */
+void timer_automatic_output_enable(uint32_t timer_periph);
+/* disable TIMER output automatic function */
+void timer_automatic_output_disable(uint32_t timer_periph);
+/* enable or disable TIMER primary output function */
+void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);
+/* enable or disable channel capture/compare control shadow register */
+void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue);
+/* configure TIMER channel control shadow register update control */
+void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl);
+
+/* TIMER channel output */
+/* initialize TIMER channel output parameter struct */
+void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara);
+/* configure TIMER channel output function */
+void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara);
+/* configure TIMER channel output compare mode */
+void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode);
+/* configure TIMER channel output pulse value */
+void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse);
+/* configure TIMER channel output shadow function */
+void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow);
+/* configure TIMER channel output fast function */
+void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast);
+/* configure TIMER channel output clear function */
+void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear);
+/* configure TIMER channel output polarity */
+void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity);
+/* configure TIMER channel complementary output polarity */
+void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity);
+/* configure TIMER channel enable state */
+void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state);
+/* configure TIMER channel complementary output enable state */
+void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate);
+
+/* TIMER channel input */
+/* initialize TIMER channel input parameter struct */
+void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara);
+/* configure TIMER input capture parameter */
+void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara);
+/* configure TIMER channel input capture prescaler value */
+void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler);
+/* read TIMER channel capture compare register value */
+uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel);
+/* configure TIMER input pwm capture function */
+void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm);
+/* configure TIMER hall sensor mode */
+void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode);
+
+/* TIMER master and slave */
+/* select TIMER input trigger source */
+void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger);
+/* select TIMER master mode output trigger source */
+void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger);
+/* select TIMER slave mode */
+void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode);
+/* configure TIMER master slave mode */
+void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave);
+/* configure TIMER external trigger input */
+void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter);
+/* configure TIMER quadrature decoder mode */
+void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity);
+/* configure TIMER internal clock mode */
+void timer_internal_clock_config(uint32_t timer_periph);
+/* configure TIMER the internal trigger as external clock input */
+void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger);
+/* configure TIMER the external trigger as external clock input */
+void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter);
+/* configure TIMER the external clock mode 0 */
+void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter);
+/* configure TIMER the external clock mode 1 */
+void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter);
+/* disable TIMER the external clock mode 1 */
+void timer_external_clock_mode1_disable(uint32_t timer_periph);
+
+/* TIMER interrupt and flag */
+/* enable the TIMER interrupt */
+void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
+/* disable the TIMER interrupt */
+void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt);
+/* get TIMER interrupt flag */
+FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt);
+/* clear TIMER interrupt flag */
+void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt);
+/* get TIMER flag */
+FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag);
+/* clear TIMER flag */
+void timer_flag_clear(uint32_t timer_periph, uint32_t flag);
+
+#endif /* GD32E10X_TIMER_H */

+ 377 - 0
Library/Include/gd32f10x_usart.h

@@ -0,0 +1,377 @@
+/*!
+    \file    gd32f10x_usart.h
+    \brief   definitions for the USART 
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.1, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_USART_H
+#define GD32F10X_USART_H
+
+#include "gd32f10x.h"
+
+/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */
+#define USART1                        USART_BASE                       /*!< USART1 base address */
+#define USART2                        (USART_BASE+(0x00000400U))       /*!< USART2 base address */
+#define UART3                         (USART_BASE+(0x00000800U))       /*!< UART3 base address */
+#define UART4                         (USART_BASE+(0x00000C00U))       /*!< UART4 base address */
+#define USART0                        (USART_BASE+(0x0000F400U))       /*!< USART0 base address */
+
+/* registers definitions */
+#define USART_STAT(usartx)            REG32((usartx) + (0x00000000U))  /*!< USART status register */
+#define USART_DATA(usartx)            REG32((usartx) + (0x00000004U))  /*!< USART data register */
+#define USART_BAUD(usartx)            REG32((usartx) + (0x00000008U))  /*!< USART baud rate register */
+#define USART_CTL0(usartx)            REG32((usartx) + (0x0000000CU))  /*!< USART control register 0 */
+#define USART_CTL1(usartx)            REG32((usartx) + (0x00000010U))  /*!< USART control register 1 */
+#define USART_CTL2(usartx)            REG32((usartx) + (0x00000014U))  /*!< USART control register 2 */
+#define USART_GP(usartx)              REG32((usartx) + (0x00000018U))  /*!< USART guard time and prescaler register */
+
+/* bits definitions */
+/* USARTx_STAT */
+#define USART_STAT_PERR               BIT(0)       /*!< parity error flag */
+#define USART_STAT_FERR               BIT(1)       /*!< frame error flag */
+#define USART_STAT_NERR               BIT(2)       /*!< noise error flag */
+#define USART_STAT_ORERR              BIT(3)       /*!< overrun error */
+#define USART_STAT_IDLEF              BIT(4)       /*!< IDLE frame detected flag */
+#define USART_STAT_RBNE               BIT(5)       /*!< read data buffer not empty */
+#define USART_STAT_TC                 BIT(6)       /*!< transmission complete */
+#define USART_STAT_TBE                BIT(7)       /*!< transmit data buffer empty */
+#define USART_STAT_LBDF               BIT(8)       /*!< LIN break detected flag */
+#define USART_STAT_CTSF               BIT(9)       /*!< CTS change flag */
+
+/* USARTx_DATA */
+#define USART_DATA_DATA               BITS(0,8)    /*!< transmit or read data value */
+
+/* USARTx_BAUD */
+#define USART_BAUD_FRADIV             BITS(0,3)    /*!< fraction part of baud-rate divider */
+#define USART_BAUD_INTDIV             BITS(4,15)   /*!< integer part of baud-rate divider */
+
+/* USARTx_CTL0 */
+#define USART_CTL0_SBKCMD             BIT(0)       /*!< send break command */
+#define USART_CTL0_RWU                BIT(1)       /*!< receiver wakeup from mute mode */
+#define USART_CTL0_REN                BIT(2)       /*!< receiver enable */
+#define USART_CTL0_TEN                BIT(3)       /*!< transmitter enable */
+#define USART_CTL0_IDLEIE             BIT(4)       /*!< idle line detected interrupt enable */
+#define USART_CTL0_RBNEIE             BIT(5)       /*!< read data buffer not empty interrupt and overrun error interrupt enable */
+#define USART_CTL0_TCIE               BIT(6)       /*!< transmission complete interrupt enable */
+#define USART_CTL0_TBEIE              BIT(7)       /*!< transmitter buffer empty interrupt enable */
+#define USART_CTL0_PERRIE             BIT(8)       /*!< parity error interrupt enable */
+#define USART_CTL0_PM                 BIT(9)       /*!< parity mode */
+#define USART_CTL0_PCEN               BIT(10)      /*!< parity check function enable */
+#define USART_CTL0_WM                 BIT(11)      /*!< wakeup method in mute mode */
+#define USART_CTL0_WL                 BIT(12)      /*!< word length */
+#define USART_CTL0_UEN                BIT(13)      /*!< USART enable */
+
+/* USARTx_CTL1 */
+#define USART_CTL1_ADDR               BITS(0,3)    /*!< address of USART */
+#define USART_CTL1_LBLEN              BIT(5)       /*!< LIN break frame length */
+#define USART_CTL1_LBDIE              BIT(6)       /*!< LIN break detected interrupt eanble */
+#define USART_CTL1_CLEN               BIT(8)       /*!< CK length */
+#define USART_CTL1_CPH                BIT(9)       /*!< CK phase */
+#define USART_CTL1_CPL                BIT(10)      /*!< CK polarity */
+#define USART_CTL1_CKEN               BIT(11)      /*!< CK pin enable */
+#define USART_CTL1_STB                BITS(12,13)  /*!< STOP bits length */
+#define USART_CTL1_LMEN               BIT(14)      /*!< LIN mode enable */
+
+/* USARTx_CTL2 */
+#define USART_CTL2_ERRIE              BIT(0)       /*!< error interrupt enable */
+#define USART_CTL2_IREN               BIT(1)       /*!< IrDA mode enable */
+#define USART_CTL2_IRLP               BIT(2)       /*!< IrDA low-power */
+#define USART_CTL2_HDEN               BIT(3)       /*!< half-duplex enable */
+#define USART_CTL2_NKEN               BIT(4)       /*!< NACK enable in smartcard mode */
+#define USART_CTL2_SCEN               BIT(5)       /*!< smartcard mode enable */
+#define USART_CTL2_DENR               BIT(6)       /*!< DMA request enable for reception */
+#define USART_CTL2_DENT               BIT(7)       /*!< DMA request enable for transmission */
+#define USART_CTL2_RTSEN              BIT(8)       /*!< RTS enable */
+#define USART_CTL2_CTSEN              BIT(9)       /*!< CTS enable */
+#define USART_CTL2_CTSIE              BIT(10)      /*!< CTS interrupt enable */
+
+/* USARTx_GP */
+#define USART_GP_PSC                  BITS(0,7)    /*!< prescaler value for dividing the system clock */
+#define USART_GP_GUAT                 BITS(8,15)   /*!< guard time value in smartcard mode */
+
+/* constants definitions */
+/* define the USART bit position and its register index offset */
+#define USART_REGIDX_BIT(regidx, bitpos)     (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
+#define USART_REG_VAL(usartx, offset)        (REG32((usartx) + (((uint32_t)(offset) & (0x0000FFFFU)) >> 6)))
+#define USART_BIT_POS(val)                   ((uint32_t)(val) & (0x0000001FU))
+#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2)   (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\
+                                                              | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)))
+#define USART_REG_VAL2(usartx, offset)       (REG32((usartx) + ((uint32_t)(offset) >> 22)))
+#define USART_BIT_POS2(val)                  (((uint32_t)(val) & (0x001F0000U)) >> 16)
+
+/* register offset */
+#define USART_STAT_REG_OFFSET                     (0x00000000U)        /*!< STAT register offset */
+#define USART_CTL0_REG_OFFSET                     (0x0000000CU)        /*!< CTL0 register offset */
+#define USART_CTL1_REG_OFFSET                     (0x00000010U)        /*!< CTL1 register offset */
+#define USART_CTL2_REG_OFFSET                     (0x00000014U)        /*!< CTL2 register offset */
+
+/* USART flags */
+typedef enum
+{
+    /* flags in STAT register */
+    USART_FLAG_CTSF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 9U),      /*!< CTS change flag */
+    USART_FLAG_LBDF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 8U),      /*!< LIN break detected flag */
+    USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 7U),       /*!< transmit data buffer empty */
+    USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 6U),        /*!< transmission complete */
+    USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 5U),      /*!< read data buffer not empty */
+    USART_FLAG_IDLEF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 4U),     /*!< IDLE frame detected flag */
+    USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 3U),     /*!< overrun error */
+    USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 2U),      /*!< noise error flag */
+    USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 1U),      /*!< frame error flag */
+    USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 0U),      /*!< parity error flag */
+}usart_flag_enum;
+
+/* USART interrupt flags */
+typedef enum
+{
+    /* interrupt flags in CTL0 register */
+    USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT_REG_OFFSET, 0U),       /*!< parity error interrupt and flag */
+    USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT_REG_OFFSET, 7U),        /*!< transmitter buffer empty interrupt and flag */
+    USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 6U),         /*!< transmission complete interrupt and flag */
+    USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 5U),       /*!< read data buffer not empty interrupt and flag */
+    USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */
+    USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT_REG_OFFSET, 4U),       /*!< IDLE line detected interrupt and flag */
+    /* interrupt flags in CTL1 register */
+    USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 8U),        /*!< LIN break detected interrupt and flag */
+    /* interrupt flags in CTL2 register */
+    USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT_REG_OFFSET, 9U),       /*!< CTS interrupt and flag */
+    USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 3U),  /*!< error interrupt and overrun error */
+    USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 2U),   /*!< error interrupt and noise error flag */
+    USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 1U),   /*!< error interrupt and frame error flag */
+}usart_interrupt_flag_enum;
+
+/* USART interrupt enable or disable */
+typedef enum
+{
+    /* interrupt in CTL0 register */
+    USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U),        /*!< parity error interrupt */
+    USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U),         /*!< transmitter buffer empty interrupt */
+    USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U),          /*!< transmission complete interrupt */
+    USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U),        /*!< read data buffer not empty interrupt and overrun error interrupt */
+    USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U),        /*!< IDLE line detected interrupt */
+    /* interrupt in CTL1 register */
+    USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U),         /*!< LIN break detected interrupt */
+    /* interrupt in CTL2 register */
+    USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U),        /*!< CTS interrupt */
+    USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U),         /*!< error interrupt */
+}usart_interrupt_enum;
+
+/* USART receiver configure */
+#define CTL0_REN(regval)              (BIT(2) & ((uint32_t)(regval) << 2))
+#define USART_RECEIVE_ENABLE          CTL0_REN(1)                      /*!< enable receiver */
+#define USART_RECEIVE_DISABLE         CTL0_REN(0)                      /*!< disable receiver */
+
+/* USART transmitter configure */
+#define CTL0_TEN(regval)              (BIT(3) & ((uint32_t)(regval) << 3))
+#define USART_TRANSMIT_ENABLE         CTL0_TEN(1)                      /*!< enable transmitter */
+#define USART_TRANSMIT_DISABLE        CTL0_TEN(0)                      /*!< disable transmitter */
+
+/* USART parity bits definitions */
+#define CTL0_PM(regval)               (BITS(9,10) & ((uint32_t)(regval) << 9))
+#define USART_PM_NONE                 CTL0_PM(0)                       /*!< no parity */
+#define USART_PM_EVEN                 CTL0_PM(2)                       /*!< even parity */
+#define USART_PM_ODD                  CTL0_PM(3)                       /*!< odd parity */
+
+/* USART wakeup method in mute mode */
+#define CTL0_WM(regval)               (BIT(11) & ((uint32_t)(regval) << 11))
+#define USART_WM_IDLE                 CTL0_WM(0)                       /*!< idle line */
+#define USART_WM_ADDR                 CTL0_WM(1)                       /*!< address match */
+
+/* USART word length definitions */
+#define CTL0_WL(regval)               (BIT(12) & ((uint32_t)(regval) << 12))
+#define USART_WL_8BIT                 CTL0_WL(0)                       /*!< 8 bits */
+#define USART_WL_9BIT                 CTL0_WL(1)                       /*!< 9 bits */
+
+/* USART stop bits definitions */
+#define CTL1_STB(regval)              (BITS(12,13) & ((uint32_t)(regval) << 12))
+#define USART_STB_1BIT                CTL1_STB(0)                      /*!< 1 bit */
+#define USART_STB_0_5BIT              CTL1_STB(1)                      /*!< 0.5 bit */
+#define USART_STB_2BIT                CTL1_STB(2)                      /*!< 2 bits */
+#define USART_STB_1_5BIT              CTL1_STB(3)                      /*!< 1.5 bits */
+
+/* USART LIN break frame length */
+#define CTL1_LBLEN(regval)            (BIT(5) & ((uint32_t)(regval) << 5))
+#define USART_LBLEN_10B               CTL1_LBLEN(0)                    /*!< 10 bits */
+#define USART_LBLEN_11B               CTL1_LBLEN(1)                    /*!< 11 bits */
+
+/* USART CK length */
+#define CTL1_CLEN(regval)             (BIT(8) & ((uint32_t)(regval) << 8))
+#define USART_CLEN_NONE               CTL1_CLEN(0)                     /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */
+#define USART_CLEN_EN                 CTL1_CLEN(1)                     /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */
+
+/* USART clock phase */
+#define CTL1_CPH(regval)              (BIT(9) & ((uint32_t)(regval) << 9))
+#define USART_CPH_1CK                 CTL1_CPH(0)                      /*!< first clock transition is the first data capture edge */
+#define USART_CPH_2CK                 CTL1_CPH(1)                      /*!< second clock transition is the first data capture edge */
+
+/* USART clock polarity */
+#define CTL1_CPL(regval)              (BIT(10) & ((uint32_t)(regval) << 10))
+#define USART_CPL_LOW                 CTL1_CPL(0)                      /*!< steady low value on CK pin */
+#define USART_CPL_HIGH                CTL1_CPL(1)                      /*!< steady high value on CK pin */
+
+/* USART DMA request for receive configure */
+#define CLT2_DENR(regval)             (BIT(6) & ((uint32_t)(regval) << 6))
+#define USART_DENR_ENABLE             CLT2_DENR(1)                     /*!< DMA request enable for reception */
+#define USART_DENR_DISABLE            CLT2_DENR(0)                     /*!< DMA request disable for reception */
+
+/* USART DMA request for transmission configure */
+#define CLT2_DENT(regval)             (BIT(7) & ((uint32_t)(regval) << 7))
+#define USART_DENT_ENABLE             CLT2_DENT(1)                     /*!< DMA request enable for transmission */
+#define USART_DENT_DISABLE            CLT2_DENT(0)                     /*!< DMA request disable for transmission */
+
+/* USART RTS configure */
+#define CLT2_RTSEN(regval)            (BIT(8) & ((uint32_t)(regval) << 8))
+#define USART_RTS_ENABLE              CLT2_RTSEN(1)                    /*!< RTS enable */
+#define USART_RTS_DISABLE             CLT2_RTSEN(0)                    /*!< RTS disable */
+
+/* USART CTS configure */
+#define CLT2_CTSEN(regval)            (BIT(9) & ((uint32_t)(regval) << 9))
+#define USART_CTS_ENABLE              CLT2_CTSEN(1)                    /*!< CTS enable */
+#define USART_CTS_DISABLE             CLT2_CTSEN(0)                    /*!< CTS disable */
+
+/* USART IrDA low-power enable */
+#define CTL2_IRLP(regval)             (BIT(2) & ((uint32_t)(regval) << 2))
+#define USART_IRLP_LOW                CTL2_IRLP(1)                     /*!< low-power */
+#define USART_IRLP_NORMAL             CTL2_IRLP(0)                     /*!< normal */
+
+/* function declarations */
+/* initialization functions */
+/* reset USART */
+void usart_deinit(uint32_t usart_periph);
+/* configure USART baud rate value */
+void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval);
+/* configure USART parity function */
+void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg);
+/* configure USART word length */
+void usart_word_length_set(uint32_t usart_periph, uint32_t wlen);
+/* configure USART stop bit length */
+void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen);
+
+/* USART normal mode communication */
+/* enable USART */
+void usart_enable(uint32_t usart_periph);
+/* disable USART */
+void usart_disable(uint32_t usart_periph);
+/* configure USART transmitter */
+void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig);
+/* configure USART receiver */
+void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig);
+/* USART transmit data function */
+void usart_data_transmit(uint32_t usart_periph, uint16_t data);
+/* USART receive data function */
+uint16_t usart_data_receive(uint32_t usart_periph);
+
+/* multi-processor communication */
+/* configure address of the USART */
+void usart_address_config(uint32_t usart_periph, uint8_t addr);
+/* enable mute mode */
+void usart_mute_mode_enable(uint32_t usart_periph);
+/* disable mute mode */
+void usart_mute_mode_disable(uint32_t usart_periph);
+/* configure wakeup method in mute mode */
+void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod);
+
+/* LIN mode communication */
+/* enable LIN mode */
+void usart_lin_mode_enable(uint32_t usart_periph);
+/* disable LIN mode */
+void usart_lin_mode_disable(uint32_t usart_periph);
+/* configure LIN break frame length */
+void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen);
+/* send break frame */
+void usart_send_break(uint32_t usart_periph);
+
+/* half-duplex communication */
+/* enable half-duplex */
+void usart_halfduplex_enable(uint32_t usart_periph);
+/* disable half-duplex */
+void usart_halfduplex_disable(uint32_t usart_periph);
+
+/* synchronous communication */
+/* enable CK pin in synchronous mode */
+void usart_synchronous_clock_enable(uint32_t usart_periph);
+/* disable CK pin in synchronous mode */
+void usart_synchronous_clock_disable(uint32_t usart_periph);
+/* configure usart synchronous mode parameters */
+void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl);
+
+/* smartcard communication */
+/* configure guard time value in smartcard mode */
+void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut);
+/* enable smartcard mode */
+void usart_smartcard_mode_enable(uint32_t usart_periph);
+/* disable smartcard mode */
+void usart_smartcard_mode_disable(uint32_t usart_periph);
+/* enable NACK in smartcard mode */
+void usart_smartcard_mode_nack_enable(uint32_t usart_periph);
+/* disable NACK in smartcard mode */
+void usart_smartcard_mode_nack_disable(uint32_t usart_periph);
+
+/* IrDA communication */
+/* enable IrDA mode */
+void usart_irda_mode_enable(uint32_t usart_periph);
+/* disable IrDA mode */
+void usart_irda_mode_disable(uint32_t usart_periph);
+/* configure the peripheral clock prescaler */
+void usart_prescaler_config(uint32_t usart_periph, uint8_t psc);
+/* configure IrDA low-power */
+void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp);
+
+/* hardware flow communication */
+/* configure hardware flow control RTS */
+void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig);
+/* configure hardware flow control CTS */
+void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig);
+
+/* configure USART DMA for reception */
+void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd);
+/* configure USART DMA for transmission */
+void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd);
+
+/* flag functions */
+/* get flag in STAT register */
+FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag);
+/* clear flag in STAT register */
+void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag);
+
+/* interrupt functions */
+/* enable USART interrupt */
+void usart_interrupt_enable(uint32_t usart_periph, uint32_t interrupt);
+/* disable USART interrupt */
+void usart_interrupt_disable(uint32_t usart_periph, uint32_t interrupt);
+/* get USART interrupt and flag status */
+FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag);
+/* clear interrupt flag in STAT register */
+void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t int_flag);
+#endif /* GD32F10X_USART_H */ 

+ 89 - 0
Library/Include/gd32f10x_wwdgt.h

@@ -0,0 +1,89 @@
+/*!
+    \file    gd32f10x_wwdgt.h
+    \brief   definitions for the WWDGT 
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_WWDGT_H
+#define GD32F10X_WWDGT_H
+
+#include "gd32f10x.h"
+
+/* WWDGT definitions */
+#define WWDGT                       WWDGT_BASE                                /*!< WWDGT base address */
+
+/* registers definitions */
+#define WWDGT_CTL                   REG32((WWDGT) + 0x00U)                    /*!< WWDGT control register */
+#define WWDGT_CFG                   REG32((WWDGT) + 0x04U)                    /*!< WWDGT configuration register */
+#define WWDGT_STAT                  REG32((WWDGT) + 0x08U)                    /*!< WWDGT status register */
+
+/* bits definitions */
+/* WWDGT_CTL */
+#define WWDGT_CTL_CNT               BITS(0,6)                                 /*!< WWDGT counter value */
+#define WWDGT_CTL_WDGTEN            BIT(7)                                    /*!< WWDGT counter enable */
+
+/* WWDGT_CFG */
+#define WWDGT_CFG_WIN               BITS(0,6)                                 /*!< WWDGT counter window value */
+#define WWDGT_CFG_PSC               BITS(7,8)                                 /*!< WWDGT prescaler divider value */
+#define WWDGT_CFG_EWIE              BIT(9)                                    /*!< early wakeup interrupt enable */
+
+/* WWDGT_STAT */
+#define WWDGT_STAT_EWIF             BIT(0)                                    /*!< early wakeup interrupt flag */
+
+/* constants definitions */
+#define CFG_PSC(regval)             (BITS(7,8) & ((uint32_t)(regval) << 7))   /*!< write value to WWDGT_CFG_PSC bit field */
+#define WWDGT_CFG_PSC_DIV1          CFG_PSC(0)                                /*!< the time base of WWDGT = (PCLK1/4096)/1 */
+#define WWDGT_CFG_PSC_DIV2          CFG_PSC(1)                                /*!< the time base of WWDGT = (PCLK1/4096)/2 */
+#define WWDGT_CFG_PSC_DIV4          CFG_PSC(2)                                /*!< the time base of WWDGT = (PCLK1/4096)/4 */
+#define WWDGT_CFG_PSC_DIV8          CFG_PSC(3)                                /*!< the time base of WWDGT = (PCLK1/4096)/8 */
+
+/* function declarations */
+/* reset the window watchdog timer configuration */
+void wwdgt_deinit(void);
+/* start the window watchdog timer counter */
+void wwdgt_enable(void);
+
+/* configure the window watchdog timer counter value */
+void wwdgt_counter_update(uint16_t counter_value);
+/* configure counter value, window value, and prescaler divider value */
+void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler);
+
+/* enable early wakeup interrupt of WWDGT */
+void wwdgt_interrupt_enable(void);
+/* check early wakeup interrupt state of WWDGT */
+FlagStatus wwdgt_flag_get(void);
+/* clear early wakeup interrupt state of WWDGT */
+void wwdgt_flag_clear(void);
+
+#endif /* GD32F10X_WWDGT_H */

+ 932 - 0
Library/Source/gd32f10x_adc.c

@@ -0,0 +1,932 @@
+/*!
+    \file    gd32f10x_adc.c
+    \brief   ADC driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_adc.h"
+
+/* discontinuous mode macro*/
+#define  ADC_CHANNEL_LENGTH_SUBTRACT_ONE            ((uint8_t)1U)
+
+/* ADC regular channel macro */
+#define  ADC_REGULAR_CHANNEL_RANK_SIX               ((uint8_t)6U)
+#define  ADC_REGULAR_CHANNEL_RANK_TWELVE            ((uint8_t)12U)
+#define  ADC_REGULAR_CHANNEL_RANK_SIXTEEN           ((uint8_t)16U)
+#define  ADC_REGULAR_CHANNEL_RANK_LENGTH            ((uint8_t)5U)
+
+/* ADC sampling time macro */
+#define  ADC_CHANNEL_SAMPLE_TEN                     ((uint8_t)10U)
+#define  ADC_CHANNEL_SAMPLE_EIGHTEEN                ((uint8_t)18U)
+#define  ADC_CHANNEL_SAMPLE_LENGTH                  ((uint8_t)3U)
+
+/* ADC inserted channel macro */
+#define  ADC_INSERTED_CHANNEL_RANK_LENGTH           ((uint8_t)5U)
+#define  ADC_INSERTED_CHANNEL_SHIFT_LENGTH          ((uint8_t)15U)
+
+/* ADC inserted channel offset macro */
+#define  ADC_OFFSET_LENGTH                          ((uint8_t)3U)
+#define  ADC_OFFSET_SHIFT_LENGTH                    ((uint8_t)4U)
+
+/*!
+    \brief      reset ADC 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_deinit(uint32_t adc_periph)
+{
+    switch(adc_periph){
+    case ADC0:
+        /* reset ADC0 */
+        rcu_periph_reset_enable(RCU_ADC0RST);
+        rcu_periph_reset_disable(RCU_ADC0RST);
+        break;
+    case ADC1:
+        /* reset ADC1 */
+        rcu_periph_reset_enable(RCU_ADC1RST);
+        rcu_periph_reset_disable(RCU_ADC1RST);
+        break;
+#ifndef GD32F10X_CL
+    case ADC2:
+        rcu_periph_reset_enable(RCU_ADC2RST);
+        rcu_periph_reset_disable(RCU_ADC2RST);
+        break;
+#endif /* GD32F10X_CL */
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure the ADC sync mode
+    \param[in]  mode: ADC mode
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_MODE_FREE: all the ADCs work independently
+      \arg        ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode
+      \arg        ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode
+      \arg        ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode
+      \arg        ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode
+      \arg        ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only
+      \arg        ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only
+      \arg        ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only
+      \arg        ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only
+      \arg        ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only
+    \param[out] none
+    \retval     none
+*/
+void adc_mode_config(uint32_t mode)
+{
+    ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM);
+    ADC_CTL0(ADC0) |= mode;
+}
+
+/*!
+    \brief      enable or disable ADC special function
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  function: the function to config
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_SCAN_MODE: scan mode select
+      \arg        ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically
+      \arg        ADC_CONTINUOUS_MODE: continuous mode select
+    \param[in]  newvalue: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue)
+{
+    if(newvalue){
+        if(0U != (function & ADC_SCAN_MODE)){
+            /* enable scan mode */
+            ADC_CTL0(adc_periph) |= ADC_SCAN_MODE;
+        }
+        if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
+            /* enable inserted channel group convert automatically */
+            ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO;
+        } 
+        if(0U != (function & ADC_CONTINUOUS_MODE)){
+            /* enable continuous mode */
+            ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE;
+        }        
+    }else{
+        if(0U != (function & ADC_SCAN_MODE)){
+            /* disable scan mode */
+            ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE;
+        }
+        if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
+            /* disable inserted channel group convert automatically */
+            ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO;
+        } 
+        if(0U != (function & ADC_CONTINUOUS_MODE)){
+            /* disable continuous mode */
+            ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE;
+        }       
+    }
+}
+
+/*!
+    \brief      configure ADC data alignment 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  data_alignment: data alignment select
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_DATAALIGN_RIGHT: LSB alignment
+      \arg        ADC_DATAALIGN_LEFT: MSB alignment
+    \param[out] none
+    \retval     none
+*/
+void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment)
+{
+    if(ADC_DATAALIGN_RIGHT != data_alignment){
+        /* MSB alignment */
+        ADC_CTL1(adc_periph) |= ADC_CTL1_DAL;
+    }else{
+        /* LSB alignment */
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL);
+    }
+}
+
+/*!
+    \brief      enable ADC interface
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_enable(uint32_t adc_periph)
+{
+    if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){
+        /* enable ADC */
+        ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
+    }       
+}
+
+/*!
+    \brief      disable ADC interface
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_disable(uint32_t adc_periph)
+{
+    /* disable ADC */
+    ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON);
+}
+
+/*!
+    \brief      ADC calibration and reset calibration
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_calibration_enable(uint32_t adc_periph)
+{
+    /* reset the selected ADC1 calibration registers */
+    ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB;
+    /* check the RSTCLB bit state */
+    while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){
+    }
+    /* enable ADC calibration process */
+    ADC_CTL1(adc_periph) |= ADC_CTL1_CLB;
+    /* check the CLB bit state */
+    while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){
+    }
+}
+
+/*!
+    \brief      enable the temperature sensor and Vrefint channel
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void adc_tempsensor_vrefint_enable(void)
+{
+    /* enable the temperature sensor and Vrefint channel */
+    ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN;
+}
+
+/*!
+    \brief      disable the temperature sensor and Vrefint channel
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void adc_tempsensor_vrefint_disable(void)
+{
+    /* disable the temperature sensor and Vrefint channel */
+    ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN;
+}
+
+/*!
+    \brief      enable DMA request 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_dma_mode_enable(uint32_t adc_periph)
+{
+    /* enable DMA request */
+    ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA);
+}
+
+/*!
+    \brief      disable DMA request 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_dma_mode_disable(uint32_t adc_periph)
+{
+    /* disable DMA request */
+    ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA);
+}
+
+/*!
+    \brief      configure ADC discontinuous mode 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: select the channel group
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+      \arg        ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel
+    \param[in]  length: number of conversions in discontinuous mode,the number can be 1..8
+                        for regular channel, the number has no effect for inserted channel
+    \param[out] none
+    \retval     none
+*/
+void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length)
+{
+    /* disable discontinuous mode of regular & inserted channel */
+    ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC));
+    switch(adc_channel_group){
+    case ADC_REGULAR_CHANNEL:
+        /* config the number of conversions in discontinuous mode */
+        ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM);
+        ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
+        /* enable regular channel group discontinuous mode */
+        ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        /* enable inserted channel group discontinuous mode */
+        ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC;
+        break;
+    case ADC_CHANNEL_DISCON_DISABLE:
+        /* disable discontinuous mode of regular & inserted channel */
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure the length of regular channel group or inserted channel group
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: select the channel group
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+    \param[in]  length: the length of the channel
+                        regular channel 1-16
+                        inserted channel 1-4
+    \param[out] none
+    \retval     none
+*/
+void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length)
+{
+    switch(adc_channel_group){
+    case ADC_REGULAR_CHANNEL:
+        /* configure the length of regular channel group */
+        ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL);
+        ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
+        break;
+    case ADC_INSERTED_CHANNEL:
+        /* configure the length of inserted channel group */
+        ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL);
+        ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure ADC regular channel 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  rank: the regular group sequence rank,this parameter must be between 0 to 15
+    \param[in]  adc_channel: the selected ADC channel
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx 
+    \param[in]  sample_time: the sample time value
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_SAMPLETIME_1POINT5: 1.5 cycles
+      \arg        ADC_SAMPLETIME_7POINT5: 7.5 cycles
+      \arg        ADC_SAMPLETIME_13POINT5: 13.5 cycles
+      \arg        ADC_SAMPLETIME_28POINT5: 28.5 cycles
+      \arg        ADC_SAMPLETIME_41POINT5: 41.5 cycles
+      \arg        ADC_SAMPLETIME_55POINT5: 55.5 cycles
+      \arg        ADC_SAMPLETIME_71POINT5: 71.5 cycles
+      \arg        ADC_SAMPLETIME_239POINT5: 239.5 cycles
+    \param[out] none
+    \retval     none
+*/
+void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time)
+{
+    uint32_t rsq,sampt;
+    
+    /* ADC regular sequence config */
+    if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){
+        /* the regular group sequence rank is smaller than six */
+        rsq = ADC_RSQ2(adc_periph);
+        rsq &=  ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)));
+        /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
+        rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank));
+        ADC_RSQ2(adc_periph) = rsq;
+    }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){
+        /* the regular group sequence rank is smaller than twelve */
+        rsq = ADC_RSQ1(adc_periph);
+        rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))));
+        /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
+        rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)));
+        ADC_RSQ1(adc_periph) = rsq;
+    }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){
+        /* the regular group sequence rank is smaller than sixteen */
+        rsq = ADC_RSQ0(adc_periph);
+        rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))));
+        /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
+        rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)));
+        ADC_RSQ0(adc_periph) = rsq;
+    }else{
+    }
+    
+    /* ADC sampling time config */
+    if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
+        /* the regular group sequence rank is smaller than ten */
+        sampt = ADC_SAMPT1(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
+        /* channel sample time set*/
+        sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel));
+        ADC_SAMPT1(adc_periph) = sampt;
+    }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
+        /* the regular group sequence rank is smaller than eighteen */
+        sampt = ADC_SAMPT0(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
+        /* channel sample time set*/
+        sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
+        ADC_SAMPT0(adc_periph) = sampt;
+    }else{
+    }
+}
+
+/*!
+    \brief      configure ADC inserted channel 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  rank: the inserted group sequencer rank,this parameter must be between 0 to 3
+    \param[in]  adc_channel: the selected ADC channel
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx
+    \param[in]  sample_time: The sample time value
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_SAMPLETIME_1POINT5: 1.5 cycles
+      \arg        ADC_SAMPLETIME_7POINT5: 7.5 cycles
+      \arg        ADC_SAMPLETIME_13POINT5: 13.5 cycles
+      \arg        ADC_SAMPLETIME_28POINT5: 28.5 cycles
+      \arg        ADC_SAMPLETIME_41POINT5: 41.5 cycles
+      \arg        ADC_SAMPLETIME_55POINT5: 55.5 cycles
+      \arg        ADC_SAMPLETIME_71POINT5: 71.5 cycles
+      \arg        ADC_SAMPLETIME_239POINT5: 239.5 cycles
+    \param[out] none
+    \retval     none
+*/
+void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time)
+{
+    uint8_t inserted_length;
+    uint32_t isq,sampt;
+    /* get inserted channel group length */
+    inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
+    /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */
+    isq = ADC_ISQ(adc_periph);
+    isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH)));
+    isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH));
+    ADC_ISQ(adc_periph) = isq;
+
+    /* ADC sampling time config */  
+    if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
+        /* the inserted group sequence rank is smaller than ten */
+        sampt = ADC_SAMPT1(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
+        /* channel sample time set*/
+        sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel);
+        ADC_SAMPT1(adc_periph) = sampt;
+    }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
+        /* the inserted group sequence rank is smaller than eighteen */
+        sampt = ADC_SAMPT0(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
+        /* channel sample time set*/
+        sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
+        ADC_SAMPT0(adc_periph) = sampt;
+    }else{
+    }
+}
+
+/*!
+    \brief      configure ADC inserted channel offset 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  inserted_channel: insert channel select
+                only one parameter can be selected
+      \arg        ADC_INSERTED_CHANNEL_0: inserted channel0
+      \arg        ADC_INSERTED_CHANNEL_1: inserted channel1
+      \arg        ADC_INSERTED_CHANNEL_2: inserted channel2
+      \arg        ADC_INSERTED_CHANNEL_3: inserted channel3
+    \param[in]  offset: the offset data
+    \param[out] none
+    \retval     none
+*/
+void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset)
+{
+    uint8_t inserted_length;
+    uint32_t num = 0U;
+
+    inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
+    num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel));
+    
+    if(num <= ADC_OFFSET_LENGTH){
+        /* calculate the offset of the register */
+        num = num * ADC_OFFSET_SHIFT_LENGTH;
+        /* config the offset of the selected channels */
+        REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset);
+    }  
+}
+
+/*!
+    \brief      configure ADC external trigger source 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: select the channel group
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+    \param[in]  external_trigger_source: regular or inserted group trigger source
+                only one parameter can be selected
+                for regular channel:
+      \arg        ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 
+      \arg        ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select
+      \arg        ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger      
+                for inserted channel:
+      \arg        ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select
+      \arg        ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select
+      \arg        ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger      
+    \param[out] none
+    \retval     none
+*/
+void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source)
+{   
+    switch(adc_channel_group){
+    case ADC_REGULAR_CHANNEL:
+        /* configure ADC regular group external trigger source */
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC);
+        ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        /* configure ADC inserted group external trigger source */
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC);
+        ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure ADC external trigger 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: select the channel group
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+    \param[in]  newvalue: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue)
+{
+    if(newvalue){
+        if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
+            /* enable ADC regular channel group external trigger */
+            ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC;
+        }
+        if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+            /* enable ADC inserted channel group external trigger */
+            ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC;
+        }        
+    }else{
+        if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
+            /* disable ADC regular channel group external trigger */
+            ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC;
+        }
+        if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+            /* disable ADC regular channel group external trigger */
+            ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC;
+        }      
+    }
+}
+
+/*!
+    \brief      enable ADC software trigger 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: select the channel group
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+    \param[out] none
+    \retval     none
+*/
+void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group)
+{
+    if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
+        /* enable ADC regular channel group software trigger */
+        ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST;
+    }
+    if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+        /* enable ADC inserted channel group software trigger */
+        ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST;
+    }
+}
+
+/*!
+    \brief      read ADC regular group data register 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  none
+    \param[out] none
+    \retval     the conversion value
+*/
+uint16_t adc_regular_data_read(uint32_t adc_periph)
+{
+    return (uint16_t)(ADC_RDATA(adc_periph));
+}
+
+/*!
+    \brief      read ADC inserted group data register 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  inserted_channel: insert channel select
+                only one parameter can be selected
+      \arg        ADC_INSERTED_CHANNEL_0: inserted Channel0
+      \arg        ADC_INSERTED_CHANNEL_1: inserted channel1
+      \arg        ADC_INSERTED_CHANNEL_2: inserted Channel2
+      \arg        ADC_INSERTED_CHANNEL_3: inserted Channel3
+    \param[out] none
+    \retval     the conversion value
+*/
+uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel)
+{
+    uint32_t idata;
+    /* read the data of the selected channel */
+    switch(inserted_channel){
+    case ADC_INSERTED_CHANNEL_0:
+        /* read the data of channel 0 */
+        idata = ADC_IDATA0(adc_periph);
+        break;
+    case ADC_INSERTED_CHANNEL_1:
+        /* read the data of channel 1 */
+        idata = ADC_IDATA1(adc_periph);
+        break;
+    case ADC_INSERTED_CHANNEL_2:
+        /* read the data of channel 2 */
+        idata = ADC_IDATA2(adc_periph);
+        break;
+    case ADC_INSERTED_CHANNEL_3:
+        /* read the data of channel 3 */
+        idata = ADC_IDATA3(adc_periph);
+        break;
+    default:
+        idata = 0U;
+        break;
+    }
+    return (uint16_t)idata;
+}
+
+/*!
+    \brief      read the last ADC0 and ADC1 conversion result data in sync mode
+    \param[in]  none
+    \param[out] none
+    \retval     the conversion value
+*/
+uint32_t adc_sync_mode_convert_value_read(void)
+{
+    /* return conversion value */
+    return ADC_RDATA(ADC0);
+}
+
+
+/*!
+    \brief      configure ADC analog watchdog single channel 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel: the selected ADC channel
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0)
+    \param[out] none
+    \retval     none
+*/
+void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel)
+{
+    ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
+    /* analog watchdog channel select */
+    ADC_CTL0(adc_periph) |= (uint32_t)adc_channel;
+    ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
+}
+
+/*!
+    \brief      configure ADC analog watchdog group channel 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_channel_group: the channel group use analog watchdog
+                only one parameter can be selected which is shown as below: 
+      \arg        ADC_REGULAR_CHANNEL: regular channel group
+      \arg        ADC_INSERTED_CHANNEL: inserted channel group
+      \arg        ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group
+    \param[out] none
+    \retval     none
+*/
+void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group)
+{
+    ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
+    /* select the group */
+    switch(adc_channel_group){
+    case ADC_REGULAR_CHANNEL:
+        /* regular channel analog watchdog enable */
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        /* inserted channel analog watchdog enable */
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN;
+        break;
+    case ADC_REGULAR_INSERTED_CHANNEL:
+        /* regular and inserted channel analog watchdog enable */
+        ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      disable ADC analog watchdog 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[out] none
+    \retval     none
+*/
+void adc_watchdog_disable(uint32_t adc_periph)
+{
+    ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
+}
+
+/*!
+    \brief      configure ADC analog watchdog threshold 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  low_threshold: analog watchdog low threshold, 0..4095
+    \param[in]  high_threshold: analog watchdog high threshold, 0..4095
+    \param[out] none
+    \retval     none
+*/
+void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold)
+{
+    ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold);
+    ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold);
+}
+
+/*!
+    \brief      get the ADC flag bits
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_flag: the adc flag bits
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_FLAG_WDE: analog watchdog event flag
+      \arg        ADC_FLAG_EOC: end of group conversion flag
+      \arg        ADC_FLAG_EOIC: end of inserted group conversion flag
+      \arg        ADC_FLAG_STIC: start flag of inserted channel group
+      \arg        ADC_FLAG_STRC: start flag of regular channel group
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag)
+{
+    FlagStatus reval = RESET;
+    if(ADC_STAT(adc_periph) & adc_flag){
+        reval = SET;
+    }
+    return reval;
+}
+
+/*!
+    \brief      clear the ADC flag bits
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_flag: the adc flag bits
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_FLAG_WDE: analog watchdog event flag
+      \arg        ADC_FLAG_EOC: end of group conversion flag
+      \arg        ADC_FLAG_EOIC: end of inserted group conversion flag
+      \arg        ADC_FLAG_STIC: start flag of inserted channel group
+      \arg        ADC_FLAG_STRC: start flag of regular channel group
+    \param[out] none
+    \retval     none
+*/
+void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag)
+{
+    ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag);
+}
+
+/*!
+    \brief      get the bit state of ADCx software start conversion
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph)
+{
+    FlagStatus reval = RESET;
+    if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWRCST)){
+        reval = SET;
+    }
+    return reval;
+}
+
+/*!
+    \brief      get the bit state of ADCx software inserted channel start conversion
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph)
+{
+    FlagStatus reval = RESET;
+    if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWICST)){
+        reval = SET;
+    }
+    return reval;
+}
+
+/*!
+    \brief      get the ADC interrupt bits
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_interrupt: the adc interrupt bits
+                only one parameter can be selected which is shown as below:
+      \arg        ADC_INT_FLAG_WDE: analog watchdog interrupt
+      \arg        ADC_INT_FLAG_EOC: end of group conversion interrupt
+      \arg        ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt)
+{
+    FlagStatus interrupt_flag = RESET;
+    uint32_t state;
+    /* check the interrupt bits */
+    switch(adc_interrupt){
+    case ADC_INT_FLAG_WDE:
+        /* get the ADC analog watchdog interrupt bits */
+        state = ADC_STAT(adc_periph) & ADC_STAT_WDE;
+        if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){
+          interrupt_flag = SET;
+        }
+        break;
+    case ADC_INT_FLAG_EOC:
+        /* get the ADC end of group conversion interrupt bits */
+        state = ADC_STAT(adc_periph) & ADC_STAT_EOC;
+          if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){
+            interrupt_flag = SET;
+          }
+        break;
+    case ADC_INT_FLAG_EOIC:
+        /* get the ADC end of inserted group conversion interrupt bits */
+        state = ADC_STAT(adc_periph) & ADC_STAT_EOIC;
+        if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){
+            interrupt_flag = SET;
+        }
+        break;
+    default:
+        break;
+    }
+    return interrupt_flag;
+}
+
+/*!
+    \brief      clear the ADC flag
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_interrupt: the adc status flag
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_INT_FLAG_WDE: analog watchdog interrupt
+      \arg        ADC_INT_FLAG_EOC: end of group conversion interrupt
+      \arg        ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
+    \param[out] none
+    \retval     none
+*/
+void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt)
+{
+    ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt);
+}
+
+/*!
+    \brief      enable ADC interrupt 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_interrupt: the adc interrupt
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_INT_WDE: analog watchdog interrupt flag
+      \arg        ADC_INT_EOC: end of group conversion interrupt flag
+      \arg        ADC_INT_EOIC: end of inserted group conversion interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt)
+{
+    /* enable ADC analog watchdog interrupt */
+    if(0U != (adc_interrupt & ADC_INT_WDE)){
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE;
+    }  
+    /* enable ADC end of group conversion interrupt */
+    if(0U != (adc_interrupt & ADC_INT_EOC)){      
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE;
+    }  
+    /* enable ADC end of inserted group conversion interrupt */
+    if(0U != (adc_interrupt & ADC_INT_EOIC)){      
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE;
+    }
+}
+
+/*!
+    \brief      disable ADC interrupt 
+    \param[in]  adc_periph: ADCx, x=0,1,2
+    \param[in]  adc_interrupt: the adc interrupt flag
+                one or more parameters can be selected which are shown as below:
+      \arg        ADC_INT_WDE: analog watchdog interrupt flag
+      \arg        ADC_INT_EOC: end of group conversion interrupt flag
+      \arg        ADC_INT_EOIC: end of inserted group conversion interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt)
+{  
+    /* disable ADC analog watchdog interrupt */
+    if(0U != (adc_interrupt & ADC_INT_WDE)){  
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE;
+    }  
+    /* disable ADC end of group conversion interrupt */
+    if(0U != (adc_interrupt & ADC_INT_EOC)){      
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE;
+    }  
+    /* disable ADC end of inserted group conversion interrupt */
+    if(0U != (adc_interrupt & ADC_INT_EOIC)){      
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE;
+    }
+}

+ 295 - 0
Library/Source/gd32f10x_bkp.c

@@ -0,0 +1,295 @@
+/*!
+    \file    gd32f10x_bkp.c
+    \brief   BKP driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_bkp.h"
+
+/* BKP register bits offset */
+#define BKP_TAMPER_BITS_OFFSET          ((uint32_t)8U)
+
+/*!
+    \brief      reset BKP registers
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_deinit(void)
+{
+    /* reset BKP domain register*/
+    rcu_bkp_reset_enable();
+    rcu_bkp_reset_disable();
+}
+
+/*!
+    \brief      write BKP data register
+    \param[in]  register_number: refer to bkp_data_register_enum
+                only one parameter can be selected which is shown as below:
+      \arg        BKP_DATA_x(x = 0..41): bkp data register number x
+    \param[in]  data: the data to be write in BKP data register
+    \param[out] none
+    \retval     none
+*/
+void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)
+{
+    if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
+        BKP_DATA10_41(register_number - 1U) = data;
+    }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
+        BKP_DATA0_9(register_number - 1U) = data;
+    }else{
+        /* illegal parameters */
+    }
+}
+
+/*!
+    \brief      read BKP data register
+    \param[in]  register_number: refer to bkp_data_register_enum
+                only one parameter can be selected which is shown as below:
+      \arg        BKP_DATA_x(x = 0..41): bkp data register number x
+    \param[out] none
+    \retval     data of BKP data register
+*/
+uint16_t bkp_data_read(bkp_data_register_enum register_number)
+{
+    uint16_t data = 0U;
+    
+    /* get the data from the BKP data register */
+    if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
+        data = BKP_DATA10_41(register_number - 1U);
+    }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
+        data = BKP_DATA0_9(register_number - 1U);
+    }else{
+        /* illegal parameters */
+    }
+    return data;
+}
+
+/*!
+    \brief      enable RTC clock calibration output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_calibration_output_enable(void)
+{
+    BKP_OCTL |= (uint16_t)BKP_OCTL_COEN;
+}
+
+/*!
+    \brief      disable RTC clock calibration output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_calibration_output_disable(void)
+{
+    BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN;
+}
+
+/*!
+    \brief      enable RTC alarm or second signal output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_signal_output_enable(void)
+{
+    BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN;
+}
+
+/*!
+    \brief      disable RTC alarm or second signal output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_signal_output_disable(void)
+{
+    BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN;
+}
+
+/*!
+    \brief      select RTC output
+    \param[in]  outputsel: RTC output selection
+                only one parameter can be selected which is shown as below:
+      \arg        RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output
+      \arg        RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_output_select(uint16_t outputsel)
+{
+    uint16_t ctl = 0U;
+    
+    /* configure BKP_OCTL_ROSEL with outputsel */
+    ctl = BKP_OCTL;
+    ctl &= (uint16_t)~BKP_OCTL_ROSEL;
+    ctl |= outputsel;
+    BKP_OCTL = ctl;
+}
+
+/*!
+    \brief      set RTC clock calibration value 
+    \param[in]  value: RTC clock calibration value
+      \arg        0x00 - 0x7F
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_calibration_value_set(uint8_t value)
+{
+    uint16_t ctl;
+    
+    /* configure BKP_OCTL_RCCV with value */
+    ctl = BKP_OCTL;
+    ctl &= (uint16_t)~BKP_OCTL_RCCV;
+    ctl |= (uint16_t)OCTL_RCCV(value);
+    BKP_OCTL = ctl;
+}
+
+/*!
+    \brief      enable tamper detection
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_tamper_detection_enable(void)
+{
+    BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN;
+}
+
+/*!
+    \brief      disable tamper detection
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_tamper_detection_disable(void)
+{
+    BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN;
+}
+
+/*!
+    \brief      set tamper pin active level
+    \param[in]  level: tamper active level
+                only one parameter can be selected which is shown as below:
+      \arg        TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high
+      \arg        TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low
+    \param[out] none
+    \retval     none
+*/
+void bkp_tamper_active_level_set(uint16_t level)
+{
+    uint16_t ctl = 0U;
+    
+    /* configure BKP_TPCTL_TPAL with level */
+    ctl = BKP_TPCTL;
+    ctl &= (uint16_t)~BKP_TPCTL_TPAL;
+    ctl |= level;
+    BKP_TPCTL = ctl;
+}
+
+/*!
+    \brief      enable tamper interrupt
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_interrupt_enable(void)
+{
+    BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE;
+}
+
+/*!
+    \brief      disable tamper interrupt
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_interrupt_disable(void)
+{
+    BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE;
+}
+
+/*!
+    \brief      get tamper flag state
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus bkp_flag_get(void)
+{
+    if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear tamper flag state
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_flag_clear(void)
+{
+    BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
+}
+
+/*!
+    \brief      get tamper interrupt flag state
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus bkp_interrupt_flag_get(void)
+{
+    if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear tamper interrupt flag state
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_interrupt_flag_clear(void)
+{
+    BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
+}

+ 1054 - 0
Library/Source/gd32f10x_can.c

@@ -0,0 +1,1054 @@
+/*!
+    \file  gd32f10x_can.c
+    \brief CAN driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-11-27, V2.1.1, firmware for GD32F10x
+    \version 2020-07-14, V2.1.2, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+    \version 2021-07-21, V2.2.1, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_can.h"
+
+#define CAN_ERROR_HANDLE(s)     do{}while(1)
+    
+#define RFO1_CLEAR_VAL           ((uint32_t)0x00000000U)             /*!< RFO1 clear value */ 
+#define RFF1_CLEAR_VAL           ((uint32_t)0x00000018U)             /*!< RFF1 clear value */ 
+
+/*!
+    \brief      deinitialize CAN 
+    \param[in]  can_periph
+    \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     none
+*/
+void can_deinit(uint32_t can_periph)
+{
+#ifdef GD32F10x_CL
+    if(CAN0 == can_periph){
+        rcu_periph_reset_enable(RCU_CAN0RST);
+        rcu_periph_reset_disable(RCU_CAN0RST);
+    }else{
+        rcu_periph_reset_enable(RCU_CAN1RST);
+        rcu_periph_reset_disable(RCU_CAN1RST);
+    }
+#else
+    if(CAN0 == can_periph){
+        rcu_periph_reset_enable(RCU_CAN0RST);
+        rcu_periph_reset_disable(RCU_CAN0RST);
+    }
+#endif
+}
+
+/*!
+    \brief      initialize CAN parameter struct with a default value
+    \param[in]  type: the type of CAN parameter struct  
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_INIT_STRUCT: the CAN initial struct
+      \arg        CAN_FILTER_STRUCT: the CAN filter struct
+      \arg        CAN_TX_MESSAGE_STRUCT: the CAN TX message struct
+      \arg        CAN_RX_MESSAGE_STRUCT: the CAN RX message struct
+    \param[in]  p_struct: the pointer of the specific struct 
+    \param[out] none
+    \retval     none
+*/
+void can_struct_para_init(can_struct_type_enum type, void* p_struct)
+{
+    uint8_t i;
+    
+    /* get type of the struct */
+    switch(type){
+        /* used for can_init() */
+        case CAN_INIT_STRUCT:
+            ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE;
+            ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE;
+            ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE;
+            ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; 
+            ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; 
+            ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ;
+            ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ;
+            ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ;
+            ((can_parameter_struct*)p_struct)->time_triggered = DISABLE;
+            ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE;
+            ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE;
+            
+            break;
+        /* used for can_filter_init() */
+        case CAN_FILTER_STRUCT:
+            ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT;
+            ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE;
+            ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0;
+            ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U;
+            ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U;
+            ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U;
+            ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U;
+            ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK;
+            ((can_filter_parameter_struct*)p_struct)->filter_number = 0U;
+
+            break;
+        /* used for can_message_transmit() */
+        case CAN_TX_MESSAGE_STRUCT:
+            for(i = 0U; i < 8U; i++){
+                ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U;
+            }
+            
+            ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u;
+            ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U;
+            ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD;
+            ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA;
+            ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U;
+            
+            break;
+        /* used for can_message_receive() */
+        case CAN_RX_MESSAGE_STRUCT:
+            for(i = 0U; i < 8U; i++){
+                ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U;
+            }
+            
+            ((can_receive_message_struct*)p_struct)->rx_dlen = 0U;
+            ((can_receive_message_struct*)p_struct)->rx_efid = 0U;
+            ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD;
+            ((can_receive_message_struct*)p_struct)->rx_fi = 0U;
+            ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA;
+            ((can_receive_message_struct*)p_struct)->rx_sfid = 0U;
+            
+            break;
+
+        default:
+            CAN_ERROR_HANDLE("parameter is invalid \r\n");
+    }
+}
+
+/*!
+    \brief      initialize CAN
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  can_parameter_init: parameters for CAN initializtion
+      \arg        working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE
+      \arg        resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4)
+      \arg        time_segment_1: CAN_BT_BS1_xTQ(1..16)
+      \arg        time_segment_2: CAN_BT_BS2_xTQ(1..8)
+      \arg        time_triggered: ENABLE or DISABLE
+      \arg        auto_bus_off_recovery: ENABLE or DISABLE
+      \arg        auto_wake_up: ENABLE or DISABLE
+      \arg        no_auto_retrans: ENABLE or DISABLE
+      \arg        rec_fifo_overwrite: ENABLE or DISABLE
+      \arg        trans_fifo_order: ENABLE or DISABLE
+      \arg        prescaler: 0x0001 - 0x0400
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init)
+{
+    uint32_t timeout = CAN_TIMEOUT;
+    ErrStatus flag = ERROR;
+    
+    /* disable sleep mode */
+    CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
+    /* enable initialize mode */
+    CAN_CTL(can_periph) |= CAN_CTL_IWMOD;
+    /* wait ACK */
+    while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
+        timeout--;
+    }
+    /* check initialize working success */
+    if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
+        flag = ERROR;
+    }else{
+        /* set the bit timing register */
+        CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \
+                              BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \
+                              BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \
+                              BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \
+                              BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U)));
+
+        /* time trigger communication mode */
+        if(ENABLE == can_parameter_init->time_triggered){
+            CAN_CTL(can_periph) |= CAN_CTL_TTC;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_TTC;
+        }
+        /* automatic bus-off managment */
+        if(ENABLE == can_parameter_init->auto_bus_off_recovery){
+            CAN_CTL(can_periph) |= CAN_CTL_ABOR;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_ABOR;
+        }
+        /* automatic wakeup mode */
+        if(ENABLE == can_parameter_init->auto_wake_up){
+            CAN_CTL(can_periph) |= CAN_CTL_AWU;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_AWU;
+        }
+        /* automatic retransmission mode disable */
+        if(ENABLE == can_parameter_init->no_auto_retrans){
+            CAN_CTL(can_periph) |= CAN_CTL_ARD;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_ARD;
+        }
+        /* receive fifo overwrite mode */        
+        if(ENABLE == can_parameter_init->rec_fifo_overwrite){
+            CAN_CTL(can_periph) |= CAN_CTL_RFOD;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_RFOD;
+        } 
+        /* transmit fifo order */
+        if(ENABLE == can_parameter_init->trans_fifo_order){
+            CAN_CTL(can_periph) |= CAN_CTL_TFO;
+        }else{
+            CAN_CTL(can_periph) &= ~CAN_CTL_TFO;
+        }  
+        /* disable initialize mode */
+        CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD;
+        timeout = CAN_TIMEOUT;
+        /* wait the ACK */
+        while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
+            timeout--;
+        }
+        /* check exit initialize mode */
+        if(0U != timeout){
+            flag = SUCCESS;
+        }
+    }  
+    return flag;
+}
+
+/*!
+    \brief      initialize CAN filter 
+    \param[in]  can_filter_parameter_init: struct for CAN filter initialization
+      \arg        filter_list_high: 0x0000 - 0xFFFF
+      \arg        filter_list_low: 0x0000 - 0xFFFF
+      \arg        filter_mask_high: 0x0000 - 0xFFFF
+      \arg        filter_mask_low: 0x0000 - 0xFFFF
+      \arg        filter_fifo_number: CAN_FIFO0, CAN_FIFO1 
+      \arg        filter_number: 0 - 27
+      \arg        filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST
+      \arg        filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT 
+      \arg        filter_enable: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init)
+{
+    uint32_t val = 0U;
+    
+    val = ((uint32_t)1) << (can_filter_parameter_init->filter_number);
+    /* filter lock disable */
+    CAN_FCTL(CAN0) |= CAN_FCTL_FLD;
+    /* disable filter */
+    CAN_FW(CAN0) &= ~(uint32_t)val;
+    
+    /* filter 16 bits */
+    if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){
+        /* set filter 16 bits */
+        CAN_FSCFG(CAN0) &= ~(uint32_t)val;
+        /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */
+        CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \
+                                FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \
+                                FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS);
+        /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */
+        CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \
+                                FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \
+                                FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS);
+    }
+    /* filter 32 bits */
+    if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){
+        /* set filter 32 bits */
+        CAN_FSCFG(CAN0) |= (uint32_t)val;
+        /* 32 bits list or first 32 bits list */
+        CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \
+                                FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) |
+                                FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS);
+        /* 32 bits mask or second 32 bits list */
+        CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \
+                                FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) |
+                                FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS);
+    }
+    
+    /* filter mode */
+    if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){
+        /* mask mode */
+        CAN_FMCFG(CAN0) &= ~(uint32_t)val;
+    }else{
+        /* list mode */
+        CAN_FMCFG(CAN0) |= (uint32_t)val;
+    }
+    
+    /* filter FIFO */
+    if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){
+        /* FIFO0 */
+        CAN_FAFIFO(CAN0) &= ~(uint32_t)val;
+    }else{
+        /* FIFO1 */
+        CAN_FAFIFO(CAN0) |= (uint32_t)val;
+    }
+    
+    /* filter working */
+    if(ENABLE == can_filter_parameter_init->filter_enable){
+        
+        CAN_FW(CAN0) |= (uint32_t)val;
+    }
+    
+    /* filter lock enable */
+    CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD;
+}
+
+/*!
+    \brief      set CAN1 fliter start bank number
+    \param[in]  start_bank: CAN1 start bank number
+                only one parameter can be selected which is shown as below:
+      \arg        (1..27)
+    \param[out] none
+    \retval     none
+*/
+void can1_filter_start_bank(uint8_t start_bank)
+{
+    /* filter lock disable */
+    CAN_FCTL(CAN0) |= CAN_FCTL_FLD;
+    /* set CAN1 filter start number */
+    CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F;
+    CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank);
+    /* filter lock enaable */
+    CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD;
+}
+
+/*!
+    \brief      enable CAN debug freeze
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     none
+*/
+void can_debug_freeze_enable(uint32_t can_periph)
+{
+    /* set DFZ bit */
+    CAN_CTL(can_periph) |= CAN_CTL_DFZ;
+#ifdef GD32F10x_CL
+    if(CAN0 == can_periph){
+        dbg_periph_enable(DBG_CAN0_HOLD);
+    }else{
+        dbg_periph_enable(DBG_CAN1_HOLD);
+    }
+#else
+    if(CAN0 == can_periph){
+        dbg_periph_enable(DBG_CAN0_HOLD);
+    }
+#endif
+}
+
+/*!
+    \brief      disable CAN debug freeze
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     none
+*/
+void can_debug_freeze_disable(uint32_t can_periph)
+{
+    /* set DFZ bit */
+    CAN_CTL(can_periph) &= ~CAN_CTL_DFZ;
+#ifdef GD32F10x_CL
+    if(CAN0 == can_periph){
+        dbg_periph_disable(DBG_CAN0_HOLD);
+    }else{
+        dbg_periph_disable(DBG_CAN1_HOLD);
+    }
+#else
+    if(CAN0 == can_periph){
+        dbg_periph_enable(DBG_CAN0_HOLD);
+    }
+#endif
+}
+
+/*!
+    \brief      enable CAN time trigger mode
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     none
+*/
+void can_time_trigger_mode_enable(uint32_t can_periph)
+{
+    uint8_t mailbox_number;
+    
+    /* enable the tcc mode */
+    CAN_CTL(can_periph) |= CAN_CTL_TTC;
+    /* enable time stamp */
+    for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){
+        CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN;
+    }
+}
+
+/*!
+    \brief      disable CAN time trigger mode
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     none
+*/
+void can_time_trigger_mode_disable(uint32_t can_periph)
+{
+    uint8_t mailbox_number; 
+    
+    /* disable the TCC mode */
+    CAN_CTL(can_periph) &= ~CAN_CTL_TTC;
+    /* reset TSEN bits */
+    for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){
+        CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN;
+    }
+}
+
+/*!
+    \brief       transmit CAN message
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  transmit_message: struct for CAN transmit message
+      \arg        tx_sfid: 0x00000000 - 0x000007FF
+      \arg        tx_efid: 0x00000000 - 0x1FFFFFFF
+      \arg        tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED
+      \arg        tx_ft: CAN_FT_DATA, CAN_FT_REMOTE
+      \arg        tx_dlen: 0 - 8
+      \arg        tx_data[]: 0x00 - 0xFF
+    \param[out] none
+    \retval     mailbox_number
+*/
+uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message)
+{
+    uint8_t mailbox_number = CAN_MAILBOX0;
+
+    /* select one empty mailbox */
+    if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){
+        mailbox_number = CAN_MAILBOX0;
+    }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){
+        mailbox_number = CAN_MAILBOX1;
+    }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){
+        mailbox_number = CAN_MAILBOX2;
+    }else{
+        mailbox_number = CAN_NOMAILBOX;
+    }
+    /* return no mailbox empty */
+    if(CAN_NOMAILBOX == mailbox_number){
+        return CAN_NOMAILBOX;
+    }
+    
+    CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
+    if(CAN_FF_STANDARD == transmit_message->tx_ff){
+        /* set transmit mailbox standard identifier */
+        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
+                                                transmit_message->tx_ft);
+    }else{
+        /* set transmit mailbox extended identifier */
+        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
+                                                transmit_message->tx_ff | \
+                                                transmit_message->tx_ft);
+    }
+    /* set the data length */
+    CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC;
+    CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
+    /* set the data */
+    CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
+                                              TMDATA0_DB2(transmit_message->tx_data[2]) | \
+                                              TMDATA0_DB1(transmit_message->tx_data[1]) | \
+                                              TMDATA0_DB0(transmit_message->tx_data[0]);
+    CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
+                                              TMDATA1_DB6(transmit_message->tx_data[6]) | \
+                                              TMDATA1_DB5(transmit_message->tx_data[5]) | \
+                                              TMDATA1_DB4(transmit_message->tx_data[4]);
+    /* enable transmission */
+    CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;
+
+    return mailbox_number;
+}
+
+/*!
+    \brief      get CAN transmit state 
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  mailbox_number
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_MAILBOX(x=0,1,2)
+    \param[out] none
+    \retval     can_transmit_state_enum
+*/
+can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number)
+{
+    can_transmit_state_enum state = CAN_TRANSMIT_FAILED;
+    uint32_t val = 0U;
+    
+    /* check selected mailbox state */    
+    switch(mailbox_number){
+    /* mailbox0 */
+    case CAN_MAILBOX0:
+        val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0);
+        break;
+    /* mailbox1 */
+    case CAN_MAILBOX1:
+        val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1);
+        break;
+    /* mailbox2 */
+    case CAN_MAILBOX2:
+        val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2);
+        break;
+    default:
+        val = CAN_TRANSMIT_FAILED;
+        break;
+    }
+    
+    switch(val){
+        /* transmit pending */
+    case (CAN_STATE_PENDING): 
+        state = CAN_TRANSMIT_PENDING;
+        break;
+        /* mailbox0 transmit succeeded */
+    case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0):
+        state = CAN_TRANSMIT_OK;
+        break;
+        /* mailbox1 transmit succeeded */
+    case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1):
+        state = CAN_TRANSMIT_OK;
+        break;
+        /* mailbox2 transmit succeeded */
+    case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2):
+        state = CAN_TRANSMIT_OK;
+        break;
+        /* transmit failed */
+    default: 
+        state = CAN_TRANSMIT_FAILED;
+        break;
+    }
+    return state;
+}
+
+/*!
+    \brief      stop CAN transmission
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  mailbox_number
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_MAILBOXx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
+{
+    if(CAN_MAILBOX0 == mailbox_number){
+        CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
+        while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
+        }
+    }else if(CAN_MAILBOX1 == mailbox_number){
+        CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
+        while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
+        }
+    }else if(CAN_MAILBOX2 == mailbox_number){
+        CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
+        while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){
+        }
+    }else{
+        /* illegal parameters */
+    }
+}
+
+/*!
+    \brief      CAN receive message
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  fifo_number
+      \arg        CAN_FIFOx(x=0,1)
+    \param[out] receive_message: struct for CAN receive message
+      \arg        rx_sfid: 0x00000000 - 0x000007FF
+      \arg        rx_efid: 0x00000000 - 0x1FFFFFFF
+      \arg        rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED
+      \arg        rx_ft: CAN_FT_DATA, CAN_FT_REMOTE
+      \arg        rx_dlen: 0 - 8
+      \arg        rx_data[]: 0x00 - 0xFF
+      \arg        rx_fi: 0 - 27
+    \retval     none
+*/
+void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message)
+{
+    /* get the frame format */
+    receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number));
+    if(CAN_FF_STANDARD == receive_message->rx_ff){
+        /* get standard identifier */
+        receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number)));
+    }else{
+        /* get extended identifier */
+        receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number)));
+    }
+    
+    /* get frame type */
+    receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number));        
+    /* filtering index */
+    receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number)));
+    /* get recevie data length */
+    receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number)));
+    
+    /* receive data */
+    receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number)));
+    receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number)));
+    receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number)));
+    receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number)));
+    receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number)));
+    receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number)));
+    receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number)));
+    receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number)));
+    
+    /* release FIFO */
+    if(CAN_FIFO0 == fifo_number){
+        CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0;
+    }else{
+        CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1;
+    }
+}
+
+/*!
+    \brief      release FIFO0
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  fifo_number
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_FIFOx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void can_fifo_release(uint32_t can_periph, uint8_t fifo_number)
+{
+    if(CAN_FIFO0 == fifo_number){
+        CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0;
+    }else if(CAN_FIFO1 == fifo_number){
+        CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1;
+    }else{
+        /* illegal parameters */
+        CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n");
+    }
+}
+
+/*!
+    \brief      CAN receive message length
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  fifo_number
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_FIFOx(x=0,1) 
+    \param[out] none
+    \retval     message length
+*/
+uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number)
+{
+    uint8_t val = 0U;
+    
+    if(CAN_FIFO0 == fifo_number){
+        /* FIFO0 */
+        val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK);
+    }else if(CAN_FIFO1 == fifo_number){
+        /* FIFO1 */
+        val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK);
+    }else{
+        /* illegal parameters */
+    }
+    return val;
+}
+
+/*!
+    \brief      set CAN working mode
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  can_working_mode
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_MODE_INITIALIZE
+      \arg        CAN_MODE_NORMAL
+      \arg        CAN_MODE_SLEEP
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode)
+{
+    ErrStatus flag = ERROR;
+    /* timeout for IWS or also for SLPWS bits */
+    uint32_t timeout = CAN_TIMEOUT; 
+    
+    if(CAN_MODE_INITIALIZE == working_mode){
+        /* disable sleep mode */
+        CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD);
+        /* set initialize mode */
+        CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD;
+        /* wait the acknowledge */
+        while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
+            timeout--;
+        }
+        if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
+            flag = ERROR;
+        }else{
+            flag = SUCCESS;
+        }
+    }else if(CAN_MODE_NORMAL == working_mode){
+        /* enter normal mode */
+        CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD);
+        /* wait the acknowledge */
+        while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){
+            timeout--;
+        }
+        if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){
+            flag = ERROR;
+        }else{
+            flag = SUCCESS;
+        }
+    }else if(CAN_MODE_SLEEP == working_mode){
+        /* disable initialize mode */
+        CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD);
+        /* set sleep mode */
+        CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD;
+        /* wait the acknowledge */
+        while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){
+            timeout--;
+        }
+        if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){
+            flag = ERROR;
+        }else{
+            flag = SUCCESS;
+        }
+    }else{
+        flag = ERROR;
+    }
+    return flag;
+}
+
+/*!
+    \brief      wake up CAN
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus can_wakeup(uint32_t can_periph)
+{
+    ErrStatus flag = ERROR;
+    uint32_t timeout = CAN_TIMEOUT;
+    
+    /* wakeup */
+    CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
+    
+    while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){
+        timeout--;
+    }
+    /* check state */
+    if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){
+        flag = ERROR;
+    }else{
+        flag = SUCCESS;
+    }
+    return flag;
+}
+
+/*!
+    \brief      get CAN error type
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     can_error_enum
+      \arg        CAN_ERROR_NONE: no error
+      \arg        CAN_ERROR_FILL: fill error
+      \arg        CAN_ERROR_FORMATE: format error
+      \arg        CAN_ERROR_ACK: ACK error
+      \arg        CAN_ERROR_BITRECESSIVE: bit recessive
+      \arg        CAN_ERROR_BITDOMINANTER: bit dominant error
+      \arg        CAN_ERROR_CRC: CRC error
+      \arg        CAN_ERROR_SOFTWARECFG: software configure
+*/
+can_error_enum can_error_get(uint32_t can_periph)
+{
+    can_error_enum error;
+    error = CAN_ERROR_NONE;
+    
+    /* get error type */
+    error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph)));
+    return error;
+}
+
+/*!
+    \brief      get CAN receive error number
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     error number
+*/
+uint8_t can_receive_error_number_get(uint32_t can_periph)
+{
+    uint8_t val;
+    
+    /* get error count */
+    val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph)));
+    return val;
+}
+
+/*!
+    \brief      get CAN transmit error number
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[out] none
+    \retval     error number
+*/
+uint8_t can_transmit_error_number_get(uint32_t can_periph)
+{
+    uint8_t val;
+    
+    val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph)));
+    return val;
+}
+
+/*!
+    \brief      enable CAN interrupt 
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  interrupt 
+                one or more parameters can be selected which are shown as below:
+      \arg        CAN_INT_TME: transmit mailbox empty interrupt enable
+      \arg        CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable
+      \arg        CAN_INT_RFF0: receive FIFO0 full interrupt enable
+      \arg        CAN_INT_RFO0: receive FIFO0 overfull interrupt enable
+      \arg        CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable
+      \arg        CAN_INT_RFF1: receive FIFO1 full interrupt enable
+      \arg        CAN_INT_RFO1: receive FIFO1 overfull interrupt enable
+      \arg        CAN_INT_WERR: warning error interrupt enable
+      \arg        CAN_INT_PERR: passive error interrupt enable
+      \arg        CAN_INT_BO: bus-off interrupt enable
+      \arg        CAN_INT_ERRN: error number interrupt enable
+      \arg        CAN_INT_ERR: error interrupt enable
+      \arg        CAN_INT_WAKEUP: wakeup interrupt enable
+      \arg        CAN_INT_SLPW: sleep working interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt)
+{
+    CAN_INTEN(can_periph) |= interrupt;
+}
+
+/*!
+    \brief      disable CAN interrupt 
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  interrupt
+                one or more parameters can be selected which are shown as below:
+      \arg        CAN_INT_TME: transmit mailbox empty interrupt enable
+      \arg        CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable
+      \arg        CAN_INT_RFF0: receive FIFO0 full interrupt enable
+      \arg        CAN_INT_RFO0: receive FIFO0 overfull interrupt enable
+      \arg        CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable
+      \arg        CAN_INT_RFF1: receive FIFO1 full interrupt enable
+      \arg        CAN_INT_RFO1: receive FIFO1 overfull interrupt enable
+      \arg        CAN_INT_WERR: warning error interrupt enable
+      \arg        CAN_INT_PERR: passive error interrupt enable
+      \arg        CAN_INT_BO: bus-off interrupt enable
+      \arg        CAN_INT_ERRN: error number interrupt enable
+      \arg        CAN_INT_ERR: error interrupt enable
+      \arg        CAN_INT_WAKEUP: wakeup interrupt enable
+      \arg        CAN_INT_SLPW: sleep working interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt)
+{
+    CAN_INTEN(can_periph) &= ~interrupt;
+}
+
+/*!
+    \brief      get CAN flag state
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  flag: CAN flags, refer to can_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_FLAG_RXL: RX level
+      \arg        CAN_FLAG_LASTRX: last sample value of RX pin
+      \arg        CAN_FLAG_RS: receiving state
+      \arg        CAN_FLAG_TS: transmitting state
+      \arg        CAN_FLAG_SLPIF: status change flag of entering sleep working mode
+      \arg        CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode
+      \arg        CAN_FLAG_ERRIF: error flag
+      \arg        CAN_FLAG_SLPWS: sleep working state
+      \arg        CAN_FLAG_IWS: initial working state
+      \arg        CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO
+      \arg        CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO
+      \arg        CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO
+      \arg        CAN_FLAG_TME2: transmit mailbox 2 empty
+      \arg        CAN_FLAG_TME1: transmit mailbox 1 empty
+      \arg        CAN_FLAG_TME0: transmit mailbox 0 empty
+      \arg        CAN_FLAG_MTE2: mailbox 2 transmit error
+      \arg        CAN_FLAG_MTE1: mailbox 1 transmit error
+      \arg        CAN_FLAG_MTE0: mailbox 0 transmit error
+      \arg        CAN_FLAG_MAL2: mailbox 2 arbitration lost
+      \arg        CAN_FLAG_MAL1: mailbox 1 arbitration lost
+      \arg        CAN_FLAG_MAL0: mailbox 0 arbitration lost
+      \arg        CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error
+      \arg        CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error
+      \arg        CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error
+      \arg        CAN_FLAG_MTF2: mailbox 2 transmit finished
+      \arg        CAN_FLAG_MTF1: mailbox 1 transmit finished
+      \arg        CAN_FLAG_MTF0: mailbox 0 transmit finished
+      \arg        CAN_FLAG_RFO0: receive FIFO0 overfull
+      \arg        CAN_FLAG_RFF0: receive FIFO0 full
+      \arg        CAN_FLAG_RFO1: receive FIFO1 overfull
+      \arg        CAN_FLAG_RFF1: receive FIFO1 full
+      \arg        CAN_FLAG_BOERR: bus-off error
+      \arg        CAN_FLAG_PERR: passive error
+      \arg        CAN_FLAG_WERR: warning error
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag)
+{  
+    /* get flag and interrupt enable state */
+    if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear CAN flag state
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  flag: CAN flags, refer to can_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_FLAG_SLPIF: status change flag of entering sleep working mode
+      \arg        CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode
+      \arg        CAN_FLAG_ERRIF: error flag
+      \arg        CAN_FLAG_MTE2: mailbox 2 transmit error
+      \arg        CAN_FLAG_MTE1: mailbox 1 transmit error
+      \arg        CAN_FLAG_MTE0: mailbox 0 transmit error
+      \arg        CAN_FLAG_MAL2: mailbox 2 arbitration lost
+      \arg        CAN_FLAG_MAL1: mailbox 1 arbitration lost
+      \arg        CAN_FLAG_MAL0: mailbox 0 arbitration lost
+      \arg        CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error
+      \arg        CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error
+      \arg        CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error
+      \arg        CAN_FLAG_MTF2: mailbox 2 transmit finished
+      \arg        CAN_FLAG_MTF1: mailbox 1 transmit finished
+      \arg        CAN_FLAG_MTF0: mailbox 0 transmit finished
+      \arg        CAN_FLAG_RFO0: receive FIFO0 overfull
+      \arg        CAN_FLAG_RFF0: receive FIFO0 full
+      \arg        CAN_FLAG_RFO1: receive FIFO1 overfull
+      \arg        CAN_FLAG_RFF1: receive FIFO1 full
+    \param[out] none
+    \retval     none
+*/
+void can_flag_clear(uint32_t can_periph, can_flag_enum flag)
+{
+    if (flag == CAN_FLAG_RFO1){
+        CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL;
+    } else if (flag == CAN_FLAG_RFF1){
+        CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL;
+    } else {
+        CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag));
+    }
+}
+
+/*!
+    \brief      get CAN interrupt flag state
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  flag: CAN interrupt flags, refer to can_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering
+      \arg        CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode
+      \arg        CAN_INT_FLAG_ERRIF: error interrupt flag
+      \arg        CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag
+      \arg        CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag
+      \arg        CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag
+      \arg        CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag
+      \arg        CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag
+      \arg        CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag
+      \arg        CAN_INT_FLAG_ERRN: error number interrupt flag
+      \arg        CAN_INT_FLAG_BOERR: bus-off error interrupt flag
+      \arg        CAN_INT_FLAG_PERR: passive error interrupt flag
+      \arg        CAN_INT_FLAG_WERR: warning error interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag)
+{
+    uint32_t ret1 = RESET;
+    uint32_t ret2 = RESET;
+    
+    /* get the staus of interrupt flag */
+    if (flag == CAN_INT_FLAG_RFL0) {
+        ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0);
+    } else if (flag == CAN_INT_FLAG_RFL1) {
+        ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1);
+    } else if (flag == CAN_INT_FLAG_ERRN) {
+        ret1 = can_error_get(can_periph);
+    } else {
+        ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag));
+    }
+    /* get the staus of interrupt enale bit */
+    ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag));
+    if(ret1 && ret2){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear CAN interrupt flag state
+    \param[in]  can_periph
+      \arg        CANx(x=0,1),the CAN1 only for GD32F10x_CL 
+    \param[in]  flag: CAN interrupt flags, refer to can_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering
+      \arg        CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode
+      \arg        CAN_INT_FLAG_ERRIF: error interrupt flag
+      \arg        CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag
+      \arg        CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag
+      \arg        CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag
+      \arg        CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag
+      \arg        CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag)
+{
+    if (flag == CAN_INT_FLAG_RFO1){
+        CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL;
+    } else if (flag == CAN_INT_FLAG_RFF1){
+        CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL;
+    } else {
+        CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag));
+    }
+}

+ 130 - 0
Library/Source/gd32f10x_crc.c

@@ -0,0 +1,130 @@
+/*!
+    \file  gd32f10x_crc.c
+    \brief CRC driver
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_crc.h"
+
+#define CRC_DATA_RESET_VALUE      ((uint32_t)0xFFFFFFFFU)
+#define CRC_FDATA_RESET_VALUE     ((uint32_t)0x00000000U)
+
+/*!
+    \brief      deinit CRC calculation unit
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void crc_deinit(void)
+{
+    CRC_DATA  = CRC_DATA_RESET_VALUE;
+    CRC_FDATA = CRC_FDATA_RESET_VALUE;
+    CRC_CTL   = (uint32_t)CRC_CTL_RST;
+}
+
+/*!
+    \brief      reset data register to the value of initializaiton data register
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void crc_data_register_reset(void)
+{
+    CRC_CTL |= (uint32_t)CRC_CTL_RST;
+}
+
+/*!
+    \brief      read the value of the data register 
+    \param[in]  none
+    \param[out] none
+    \retval     32-bit value of the data register
+*/
+uint32_t crc_data_register_read(void)
+{
+    uint32_t data;
+    data = CRC_DATA;
+    return (data);
+}
+
+/*!
+    \brief      read the value of the free data register
+    \param[in]  none
+    \param[out] none
+    \retval     8-bit value of the free data register
+*/
+uint8_t crc_free_data_register_read(void)
+{
+    uint8_t fdata;
+    fdata = (uint8_t)CRC_FDATA;
+    return (fdata);
+}
+
+/*!
+    \brief      write data to the free data register
+    \param[in]  free_data: specify 8-bit data
+    \param[out] none
+    \retval     none
+*/
+void crc_free_data_register_write(uint8_t free_data)
+{
+    CRC_FDATA = (uint32_t)free_data;
+}
+
+/*!
+    \brief      calculate the CRC value of a 32-bit data
+    \param[in]  sdata: specified 32-bit data
+    \param[out] none
+    \retval     32-bit value calculated by CRC
+*/
+uint32_t crc_single_data_calculate(uint32_t sdata)
+{
+    CRC_DATA = sdata;
+    return (CRC_DATA);
+}
+
+/*!
+    \brief      calculate the CRC value of an array of 32-bit values
+    \param[in]  array: pointer to an array of 32-bit values
+    \param[in]  size: size of the array
+    \param[out] none
+    \retval     32-bit value calculated by CRC
+*/
+uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size)
+{
+    uint32_t index;
+    for(index = 0U; index < size; index++){
+        CRC_DATA = array[index];
+    }
+    return (CRC_DATA);
+}

+ 558 - 0
Library/Source/gd32f10x_dac.c

@@ -0,0 +1,558 @@
+/*!
+    \file    gd32f10x_dac.c
+    \brief   DAC driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_dac.h"
+
+/* DAC register bit offset */
+#define DAC1_REG_OFFSET           ((uint32_t)16U)
+#define DH_12BIT_OFFSET           ((uint32_t)16U)
+#define DH_8BIT_OFFSET            ((uint32_t)8U)
+
+/*!
+    \brief      deinitialize DAC
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_deinit(void)
+{
+    rcu_periph_reset_enable(RCU_DACRST);
+    rcu_periph_reset_disable(RCU_DACRST);
+}
+
+/*!
+    \brief      enable DAC
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_enable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL |= DAC_CTL_DEN0;
+    }else{
+        DAC_CTL |= DAC_CTL_DEN1;
+    }
+} 
+
+/*!
+    \brief      disable DAC
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_disable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL &= ~DAC_CTL_DEN0;
+    }else{
+        DAC_CTL &= ~DAC_CTL_DEN1;
+    }
+}
+
+/*!
+    \brief      enable DAC DMA function
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_dma_enable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL |= DAC_CTL_DDMAEN0;
+    }else{
+        DAC_CTL |= DAC_CTL_DDMAEN1;
+    }
+}
+
+/*!
+    \brief      disable DAC DMA function
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_dma_disable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL &= ~DAC_CTL_DDMAEN0;
+    }else{
+        DAC_CTL &= ~DAC_CTL_DDMAEN1;
+    }
+}
+
+/*!
+    \brief      enable DAC output buffer
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_output_buffer_enable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL &= ~DAC_CTL_DBOFF0;
+    }else{
+        DAC_CTL &= ~DAC_CTL_DBOFF1;
+    }
+}
+
+/*!
+    \brief      disable DAC output buffer
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_output_buffer_disable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL |= DAC_CTL_DBOFF0;
+    }else{
+        DAC_CTL |= DAC_CTL_DBOFF1;
+    }
+}
+
+/*!
+    \brief      get DAC output value
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     DAC output data
+*/
+uint16_t dac_output_value_get(uint32_t dac_periph)
+{
+    uint16_t data = 0U;
+    if(DAC0 == dac_periph){
+        /* store the DAC0 output value */
+        data = (uint16_t)DAC0_DO;
+    }else{
+        /* store the DAC1 output value */
+        data = (uint16_t)DAC1_DO;
+    }
+    return data;
+}
+
+/*!
+    \brief      set the DAC specified data holding register value
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  dac_align
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_ALIGN_8B_R: data right 8b alignment
+      \arg        DAC_ALIGN_12B_R: data right 12b alignment
+      \arg        DAC_ALIGN_12B_L: data left 12b alignment
+    \param[in]  data: data to be loaded
+    \param[out] none
+    \retval     none
+*/
+void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data)
+{
+    if(DAC0 == dac_periph){
+        switch(dac_align){
+        /* data right 12b alignment */
+        case DAC_ALIGN_12B_R:
+            DAC0_R12DH = data;
+            break;
+        /* data left 12b alignment */
+        case DAC_ALIGN_12B_L:
+            DAC0_L12DH = data;
+            break;
+        /* data right 8b alignment */
+        case DAC_ALIGN_8B_R:
+            DAC0_R8DH = data;
+            break;
+        default:
+            break;
+        }
+    }else{
+        switch(dac_align){
+        /* data right 12b alignment */
+        case DAC_ALIGN_12B_R:
+            DAC1_R12DH = data;
+            break;
+        /* data left 12b alignment */
+        case DAC_ALIGN_12B_L:
+            DAC1_L12DH = data;
+            break;
+        /* data right 8b alignment */
+        case DAC_ALIGN_8B_R:
+            DAC1_R8DH = data;
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+/*!
+    \brief      enable DAC trigger
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_trigger_enable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL |= DAC_CTL_DTEN0;
+    }else{
+        DAC_CTL |= DAC_CTL_DTEN1;
+    }
+}
+
+/*!
+    \brief      disable DAC trigger
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_trigger_disable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_CTL &= ~DAC_CTL_DTEN0;
+    }else{
+        DAC_CTL &= ~DAC_CTL_DTEN1;
+    }
+}
+
+/*!
+    \brief      set DAC trigger source
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  triggersource: external triggers of DAC
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_TRIGGER_T1_TRGO: TIMER1 TRGO
+      \arg        DAC_TRIGGER_T2_TRGO: TIMER2 TRGO (for GD32F10X_CL)
+      \arg        DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
+      \arg        DAC_TRIGGER_T4_TRGO: TIMER4 TRGO
+      \arg        DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
+      \arg        DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
+      \arg        DAC_TRIGGER_T7_TRGO: TIMER7 TRGO (for GD32F10X_MD and GD32F10X_HD and GD32F10X_XD)
+      \arg        DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
+      \arg        DAC_TRIGGER_SOFTWARE: software trigger
+    \param[out] none
+    \retval     none
+*/
+void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)
+{
+    if(DAC0 == dac_periph){
+        /* configure DAC0 trigger source */
+        DAC_CTL &= ~DAC_CTL_DTSEL0;
+        DAC_CTL |= triggersource;
+    }else{
+        /* configure DAC1 trigger source */
+        DAC_CTL &= ~DAC_CTL_DTSEL1;
+        DAC_CTL |= (triggersource << DAC1_REG_OFFSET);
+    }
+}
+
+/*!
+    \brief      enable DAC software trigger
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \retval     none
+*/
+void dac_software_trigger_enable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_SWT |= DAC_SWT_SWTR0;
+    }else{
+        DAC_SWT |= DAC_SWT_SWTR1;
+    }
+}
+
+/*!
+    \brief      disable DAC software trigger
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void dac_software_trigger_disable(uint32_t dac_periph)
+{
+    if(DAC0 == dac_periph){
+        DAC_SWT &= ~DAC_SWT_SWTR0;
+    }else{
+        DAC_SWT &= ~DAC_SWT_SWTR1;
+    }
+}
+
+/*!
+    \brief      configure DAC wave mode
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  wave_mode
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_WAVE_DISABLE: wave disable
+      \arg        DAC_WAVE_MODE_LFSR: LFSR noise mode
+      \arg        DAC_WAVE_MODE_TRIANGLE: triangle noise mode
+    \param[out] none
+    \retval     none
+*/
+void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode)
+{
+    if(DAC0 == dac_periph){
+        /* configure DAC0 wave mode */
+        DAC_CTL &= ~DAC_CTL_DWM0;
+        DAC_CTL |= wave_mode;
+    }else{
+        /* configure DAC1 wave mode */
+        DAC_CTL &= ~DAC_CTL_DWM1;
+        DAC_CTL |= (wave_mode << DAC1_REG_OFFSET);
+    }
+}
+
+/*!
+    \brief      configure DAC wave bit width
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  bit_width
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1
+      \arg        DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2
+      \arg        DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3
+      \arg        DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4
+      \arg        DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5
+      \arg        DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6
+      \arg        DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7
+      \arg        DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8
+      \arg        DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9
+      \arg        DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10
+      \arg        DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11
+      \arg        DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12
+    \param[out] none
+    \retval     none
+*/
+void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width)
+{
+    if(DAC0 == dac_periph){
+        /* configure DAC0 wave bit width */
+        DAC_CTL &= ~DAC_CTL_DWBW0;
+        DAC_CTL |= bit_width;
+    }else{
+        /* configure DAC1 wave bit width */
+        DAC_CTL &= ~DAC_CTL_DWBW1;
+        DAC_CTL |= (bit_width << DAC1_REG_OFFSET);
+    }
+}
+
+/*!
+    \brief      configure DAC LFSR noise mode
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  unmask_bits
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_LFSR_BIT0: unmask the LFSR bit0
+      \arg        DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
+      \arg        DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
+      \arg        DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
+      \arg        DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
+      \arg        DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
+      \arg        DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
+      \arg        DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
+      \arg        DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
+      \arg        DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
+      \arg        DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
+      \arg        DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
+    \param[out] none
+    \retval     none
+*/
+void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits)
+{
+    if(DAC0 == dac_periph){
+        /* configure DAC0 LFSR noise mode */
+        DAC_CTL &= ~DAC_CTL_DWBW0;
+        DAC_CTL |= unmask_bits;
+    }else{
+        /* configure DAC1 LFSR noise mode */
+        DAC_CTL &= ~DAC_CTL_DWBW1;
+        DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET);
+    }
+}
+
+/*!
+    \brief      configure DAC triangle noise mode
+    \param[in]  dac_periph
+      \arg        DACx(x=0,1)
+    \param[in]  amplitude
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
+      \arg        DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
+      \arg        DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
+      \arg        DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
+      \arg        DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
+      \arg        DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
+      \arg        DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
+      \arg        DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
+      \arg        DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
+      \arg        DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
+      \arg        DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
+      \arg        DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
+    \param[out] none
+    \retval     none
+*/
+void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude)
+{
+    if(DAC0 == dac_periph){
+        /* configure DAC0 triangle noise mode */
+        DAC_CTL &= ~DAC_CTL_DWBW0;
+        DAC_CTL |= amplitude;
+    }else{
+        /* configure DAC1 triangle noise mode */
+        DAC_CTL &= ~DAC_CTL_DWBW1;
+        DAC_CTL |= (amplitude << DAC1_REG_OFFSET);
+    }
+}
+
+/*!
+    \brief      enable DAC concurrent mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_enable(void)
+{
+    uint32_t ctl = 0U;
+    ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
+    DAC_CTL |= (ctl);
+}
+
+/*!
+    \brief      disable DAC concurrent mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_disable(void)
+{
+    uint32_t ctl = 0U;
+    ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
+    DAC_CTL &= (~ctl);
+}
+
+/*!
+    \brief      enable DAC concurrent software trigger function
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_software_trigger_enable(void)
+{
+    uint32_t swt = 0U;
+    swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
+    DAC_SWT |= (swt); 
+}
+
+/*!
+    \brief      disable DAC concurrent software trigger function
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_software_trigger_disable(void)
+{
+    uint32_t swt = 0U;
+    swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
+    DAC_SWT &= (~swt);
+}
+
+/*!
+    \brief      enable DAC concurrent buffer function
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_output_buffer_enable(void)
+{
+    uint32_t ctl = 0U;
+    ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
+    DAC_CTL &= (~ctl);
+}
+
+/*!
+    \brief      disable DAC concurrent buffer function
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_output_buffer_disable(void)
+{
+    uint32_t ctl = 0U;
+    ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
+    DAC_CTL |= (ctl);
+}
+
+/*!
+    \brief      set DAC concurrent mode data holding register value
+    \param[in]  dac_align
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_ALIGN_8B_R: data right 8b alignment
+      \arg        DAC_ALIGN_12B_R: data right 12b alignment
+      \arg        DAC_ALIGN_12B_L: data left 12b alignment
+    \param[in]  data0: data to be loaded
+    \param[in]  data1: data to be loaded
+    \param[out] none
+    \retval     none
+*/
+void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1)
+{
+    uint32_t data = 0U;
+    switch(dac_align){
+    /* data right 12b alignment */
+    case DAC_ALIGN_12B_R:
+        data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
+        DACC_R12DH = data;
+        break;
+    /* data left 12b alignment */
+    case DAC_ALIGN_12B_L:
+        data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
+        DACC_L12DH = data;
+        break;
+    /* data right 8b alignment */
+    case DAC_ALIGN_8B_R:
+        data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0;
+        DACC_R8DH = data;
+        break;
+    default:
+        break;
+    }
+}

+ 152 - 0
Library/Source/gd32f10x_dbg.c

@@ -0,0 +1,152 @@
+/*!
+    \file    gd32f10x_dbg.c
+    \brief   DBG driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_dbg.h"
+
+/*!
+    \brief      read DBG_ID code register
+    \param[in]  none
+    \param[out] none
+    \retval     DBG_ID code
+*/
+uint32_t dbg_id_get(void)
+{
+    return DBG_ID;
+}
+
+/*!
+    \brief      enable low power behavior when the mcu is in debug mode
+    \param[in]  dbg_low_power:
+                one or more parameters can be selected which are shown as below:
+      \arg        DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
+      \arg        DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
+      \arg        DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
+    \param[out] none
+    \retval     none
+*/
+void dbg_low_power_enable(uint32_t dbg_low_power)
+{
+    DBG_CTL |= dbg_low_power;
+}
+
+/*!
+    \brief      disable low power behavior when the mcu is in debug mode
+    \param[in]  dbg_low_power:
+                one or more parameters can be selected which are shown as below:
+      \arg        DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode
+      \arg        DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode
+      \arg        DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode
+    \param[out] none
+    \retval     none
+*/
+void dbg_low_power_disable(uint32_t dbg_low_power)
+{
+    DBG_CTL &= ~dbg_low_power;
+}
+
+/*!
+    \brief      enable peripheral behavior when the mcu is in debug mode
+    \param[in]  dbg_periph: refer to dbg_periph_enum
+                one or more parameters can be selected which are shown as below:
+      \arg        DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
+      \arg        DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
+      \arg        DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted
+      \arg        DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
+      \arg        DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted
+    \param[out] none
+    \retval     none
+*/
+void dbg_periph_enable(dbg_periph_enum dbg_periph)
+{
+    DBG_CTL |= (uint32_t)dbg_periph;
+}
+
+/*!
+    \brief      disable peripheral behavior when the mcu is in debug mode
+    \param[in]  dbg_periph: refer to dbg_periph_enum
+                one or more parameters can be selected which are shown as below:
+      \arg        DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
+      \arg        DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
+      \arg        DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted
+      \arg        DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
+      \arg        DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD and CL series): hold TIMERx counter when core is halted
+    \param[out] none
+    \retval     none
+*/
+void dbg_periph_disable(dbg_periph_enum dbg_periph)
+{
+    DBG_CTL &= ~(uint32_t)dbg_periph;
+}
+
+/*!
+    \brief      enable trace pin assignment
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dbg_trace_pin_enable(void)
+{
+    DBG_CTL |= DBG_CTL_TRACE_IOEN;
+}
+
+/*!
+    \brief      disable trace pin assignment
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dbg_trace_pin_disable(void)
+{
+    DBG_CTL &= ~DBG_CTL_TRACE_IOEN;
+}
+
+/*!
+    \brief      trace pin mode selection 
+    \param[in]  trace_mode:
+                only one parameter can be selected which is shown as below:
+      \arg        TRACE_MODE_ASYNC: trace pin used for async mode 
+      \arg        TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1
+      \arg        TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2
+      \arg        TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4
+    \param[out] none
+    \retval     none
+*/
+void dbg_trace_pin_mode_set(uint32_t trace_mode)
+{
+    DBG_CTL &= ~DBG_CTL_TRACE_MODE;
+    DBG_CTL |= trace_mode;
+}

+ 737 - 0
Library/Source/gd32f10x_dma.c

@@ -0,0 +1,737 @@
+/*!
+    \file    gd32f10x_dma.c
+    \brief   DMA driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-10-30, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_dma.h"
+
+#define DMA_WRONG_HANDLE        while(1){}
+
+  /* check whether peripheral matches channels or not */
+static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
+
+/*!
+    \brief      deinitialize DMA a channel registers 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel is deinitialized
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    /* disable DMA a channel */
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
+    /* reset DMA channel registers */
+    DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
+    DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
+    DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
+    DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
+    DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
+}
+
+/*!
+    \brief      initialize the parameters of DMA struct with the default values
+    \param[in]  init_struct: the initialization data needed to initialize DMA channel
+    \param[out] none
+    \retval     none
+*/
+void dma_struct_para_init(dma_parameter_struct* init_struct)
+{
+    /* set the DMA struct with the default values */
+    init_struct->periph_addr  = 0U;
+    init_struct->periph_width = 0U; 
+    init_struct->periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
+    init_struct->memory_addr  = 0U;
+    init_struct->memory_width = 0U;
+    init_struct->memory_inc   = DMA_MEMORY_INCREASE_DISABLE;
+    init_struct->number       = 0U;
+    init_struct->direction    = DMA_PERIPHERAL_TO_MEMORY;
+    init_struct->priority     = DMA_PRIORITY_LOW;
+}
+
+/*!
+    \brief      initialize DMA channel
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel is initialized
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  init_struct: the data needed to initialize DMA channel
+                  periph_addr: peripheral base address
+                  periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
+                  periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE 
+                  memory_addr: memory base address
+                  memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT
+                  memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE
+                  direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
+                  number: the number of remaining data to be transferred by the DMA
+                  priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH
+    \param[out] none
+    \retval     none
+*/
+void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct)
+{
+    uint32_t ctl;
+    
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    /* configure peripheral base address */
+    DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
+    
+    /* configure memory base address */
+    DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
+    
+    /* configure the number of remaining data to be transferred */
+    DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
+    
+    /* configure peripheral transfer width,memory transfer width, */
+    ctl = DMA_CHCTL(dma_periph, channelx);
+    ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
+    ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
+    DMA_CHCTL(dma_periph, channelx) = ctl;
+
+    /* configure peripheral increasing mode */
+    if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
+        DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
+    }else{
+        DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
+    }
+
+    /* configure memory increasing mode */
+    if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
+        DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
+    }else{
+        DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
+    }
+    
+    /* configure the direction of  data transfer */
+    if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
+        DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
+    }else{
+        DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
+    } 
+}
+
+/*!
+    \brief      enable DMA circulation mode  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none 
+*/
+void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+
+    DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
+}
+
+/*!
+    \brief      disable DMA circulation mode  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel 
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none 
+*/
+void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
+}
+
+/*!
+    \brief      enable memory to memory mode
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel 
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
+}
+
+/*!
+    \brief      disable memory to memory mode
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
+}
+
+/*!
+    \brief      enable DMA channel 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none 
+*/
+void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
+}
+
+/*!
+    \brief      disable DMA channel 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none 
+*/
+void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
+}
+
+/*!
+    \brief      set DMA peripheral base address  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to set peripheral base address
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  address: peripheral base address
+    \param[out] none
+    \retval     none 
+*/
+void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHPADDR(dma_periph, channelx) = address;
+}
+
+/*!
+    \brief      set DMA memory base address  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to set memory base address
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  address: memory base address
+    \param[out] none
+    \retval     none 
+*/
+void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHMADDR(dma_periph, channelx) = address;
+}
+
+/*!
+    \brief      set the number of remaining data to be transferred by the DMA 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to set number
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  number: the number of remaining data to be transferred by the DMA
+      \arg        0x0000-0xFFFF
+    \param[out] none
+    \retval     none 
+*/
+void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
+}
+
+/*!
+    \brief      get the number of remaining data to be transferred by the DMA  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to set number 
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     uint32_t: the number of remaining data to be transferred by the DMA 
+*/
+uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    return (uint32_t)DMA_CHCNT(dma_periph, channelx);
+}
+
+/*!
+    \brief      configure priority level of DMA channel 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  priority: priority Level of this channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_PRIORITY_LOW: low priority
+      \arg        DMA_PRIORITY_MEDIUM: medium priority
+      \arg        DMA_PRIORITY_HIGH: high priority
+      \arg        DMA_PRIORITY_ULTRA_HIGH: ultra high priority
+    \param[out] none
+    \retval     none 
+*/
+void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
+{
+    uint32_t ctl;
+    
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    /* acquire DMA_CHxCTL register */
+    ctl = DMA_CHCTL(dma_periph, channelx);
+    /* assign regiser */
+    ctl &= ~DMA_CHXCTL_PRIO;
+    ctl |= priority;
+    DMA_CHCTL(dma_periph, channelx) = ctl;
+}
+
+/*!
+    \brief      configure transfer data size of memory 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  mwidth: transfer data width of memory
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
+      \arg        DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
+      \arg        DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit
+    \param[out] none
+    \retval     none
+*/
+void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
+{
+    uint32_t ctl;
+    
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    /* acquire DMA_CHxCTL register */
+    ctl = DMA_CHCTL(dma_periph, channelx);
+    /* assign regiser */
+    ctl &= ~DMA_CHXCTL_MWIDTH;
+    ctl |= mwidth;
+    DMA_CHCTL(dma_periph, channelx) = ctl;
+}
+
+/*!
+    \brief      configure transfer data size of peripheral 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  pwidth: transfer data width of peripheral
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
+      \arg        DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
+      \arg        DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit
+    \param[out] none
+    \retval     none
+*/
+void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
+{
+    uint32_t ctl;
+    
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    /* acquire DMA_CHxCTL register */
+    ctl = DMA_CHCTL(dma_periph, channelx);
+    /* assign regiser */
+    ctl &= ~DMA_CHXCTL_PWIDTH;
+    ctl |= pwidth;
+    DMA_CHCTL(dma_periph, channelx) = ctl;
+}
+
+/*!
+    \brief      enable next address increasement algorithm of memory  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
+}
+
+/*!
+    \brief      disable next address increasement algorithm of memory  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
+}
+
+/*!
+    \brief      enable next address increasement algorithm of peripheral
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
+}
+
+/*!
+    \brief      disable next address increasement algorithm of peripheral 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[out] none
+    \retval     none
+*/
+void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
+}
+
+/*!
+    \brief      configure the direction of data transfer on the channel  
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  direction: specify the direction of data transfer
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
+      \arg        DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
+    \param[out] none
+    \retval     none
+*/
+void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    if(DMA_PERIPHERAL_TO_MEMORY == direction){
+        DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
+    } else {
+        DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
+    }
+}
+
+/*!
+    \brief      check DMA flag is set or not 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to get flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  flag: specify get which flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_FLAG_G: global interrupt flag of channel
+      \arg        DMA_FLAG_FTF: full transfer finish flag of channel
+      \arg        DMA_FLAG_HTF: half transfer finish flag of channel
+      \arg        DMA_FLAG_ERR: error flag of channel
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
+{
+    FlagStatus reval;
+
+    /* check whether the flag is set or not */
+    if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
+        reval = SET;
+    }else{
+        reval = RESET;
+    }
+    
+    return reval;
+}
+
+/*!
+    \brief      clear the flag of a DMA channel
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to clear flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  flag: specify get which flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_FLAG_G: global interrupt flag of channel
+      \arg        DMA_FLAG_FTF: full transfer finish flag of channel
+      \arg        DMA_FLAG_HTF: half transfer finish flag of channel
+      \arg        DMA_FLAG_ERR: error flag of channel
+    \param[out] none
+    \retval     none
+*/
+void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
+{
+    DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
+}
+
+/*!
+    \brief      check DMA flag and interrupt enable bit is set or not 
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to get flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  flag: specify get which flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
+      \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
+      \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
+{
+    uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
+    
+    switch(flag){
+        case DMA_INT_FLAG_FTF:
+            /* check whether the full transfer finish interrupt flag is set and enabled */
+            interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
+            interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
+            break;
+        case DMA_INT_FLAG_HTF:
+            /* check whether the half transfer finish interrupt flag is set and enabled */
+            interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
+            interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
+            break;
+        case DMA_INT_FLAG_ERR:
+            /* check whether the error interrupt flag is set and enabled */
+            interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
+            interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
+            break;
+        default:
+            DMA_WRONG_HANDLE
+        }
+    
+    /* when the interrupt flag is set and enabled, return SET */    
+    if(interrupt_flag && interrupt_enable){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear DMA a channel flag
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel to clear flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  flag: specify get which flag
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_INT_FLAG_G: global interrupt flag of channel
+      \arg        DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
+      \arg        DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
+      \arg        DMA_INT_FLAG_ERR: error interrupt flag of channel
+    \param[out] none
+    \retval     none
+*/
+void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
+{
+    DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
+}
+
+/*!
+    \brief      enable DMA interrupt
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel 
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  source: specify which interrupt to enbale
+                one or more parameters can be selected which are shown as below
+      \arg        DMA_INT_FTF: channel full transfer finish interrupt
+      \arg        DMA_INT_HTF: channel half transfer finish interrupt
+      \arg        DMA_INT_ERR: channel error interrupt
+    \param[out] none
+    \retval     none
+*/
+void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) |= source;
+}
+
+/*!
+    \brief      disable DMA interrupt
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
+    \param[in]  source: specify which interrupt to disbale
+                one or more parameters can be selected which are shown as below
+      \arg        DMA_INT_FTF: channel full transfer finish interrupt
+      \arg        DMA_INT_HTF: channel half transfer finish interrupt
+      \arg        DMA_INT_ERR: channel error interrupt
+    \param[out] none
+    \retval     none
+*/
+void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
+{
+    if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
+        DMA_WRONG_HANDLE
+    }
+    
+    DMA_CHCTL(dma_periph, channelx) &= ~source;
+}
+
+/*!
+    \brief      check whether peripheral and channels match
+    \param[in]  dma_periph: DMAx(x=0,1)
+      \arg        DMAx(x=0,1)
+    \param[in]  channelx: specify which DMA channel
+                only one parameter can be selected which is shown as below:
+      \arg        DMA_CHx(x=0..6)
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
+{
+    ErrStatus val = SUCCESS;
+    
+    if(DMA1 == dma_periph){
+        /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
+        if(channelx > DMA_CH4){
+            val = ERROR;
+        }
+    }
+    
+    return val;
+}

+ 3084 - 0
Library/Source/gd32f10x_enet.c

@@ -0,0 +1,3084 @@
+/*!
+    \file    gd32f10x_enet.c
+    \brief   ENET driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_enet.h"
+
+#ifdef GD32F10X_CL
+
+#if defined   (__CC_ARM)                                    /*!< ARM compiler */
+__align(4) 
+enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM];        /*!< ENET RxDMA descriptor */
+__align(4) 
+enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM];        /*!< ENET TxDMA descriptor */
+__align(4) 
+uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET receive buffer */
+__align(4) 
+uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET transmit buffer */
+
+#elif defined ( __ICCARM__ )                                /*!< IAR compiler */
+#pragma data_alignment=4
+enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM];        /*!< ENET RxDMA descriptor */
+#pragma data_alignment=4
+enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM];        /*!< ENET TxDMA descriptor */
+#pragma data_alignment=4
+uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET receive buffer */
+#pragma data_alignment=4
+uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET transmit buffer */
+
+#elif defined (__GNUC__)        /* GNU Compiler */
+enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4)));        /*!< ENET RxDMA descriptor */ 
+enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4)));        /*!< ENET TxDMA descriptor */
+uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4)));           /*!< ENET receive buffer */
+uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4)));           /*!< ENET transmit buffer */
+
+#endif /* __CC_ARM */
+
+/* global transmit and receive descriptors pointers */
+enet_descriptors_struct  *dma_current_txdesc;
+enet_descriptors_struct  *dma_current_rxdesc;
+
+/* structure pointer of ptp descriptor for normal mode */
+enet_descriptors_struct  *dma_current_ptp_txdesc = NULL;
+enet_descriptors_struct  *dma_current_ptp_rxdesc = NULL;
+
+/* init structure parameters for ENET initialization */
+static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static uint32_t enet_unknow_err = 0U;
+
+/* array of register offset for debug information get */
+static const uint16_t enet_reg_tab[] = {
+0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, 
+0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 
+  
+0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, 
+ 
+0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 
+  
+0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, 
+0x1050, 0x1054};
+
+
+/*!
+    \brief      deinitialize the ENET, and reset structure parameters for ENET initialization
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_deinit(void)
+{
+    rcu_periph_reset_enable(RCU_ENETRST);
+    rcu_periph_reset_disable(RCU_ENETRST);
+    enet_initpara_reset();
+}
+
+/*!
+    \brief      configure the parameters which are usually less cared for initialization
+                note -- this function must be called before enet_init(), otherwise 
+                configuration will be no effect
+    \param[in]  option: different function option, which is related to several parameters, 
+                only one parameter can be selected which is shown as below, refer to enet_option_enum
+      \arg        FORWARD_OPTION: choose to configure the frame forward related parameters
+      \arg        DMABUS_OPTION: choose to configure the DMA bus mode related parameters
+      \arg        DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters
+      \arg        DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters
+      \arg        STORE_OPTION: choose to configure the store forward mode related parameters
+      \arg        DMA_OPTION: choose to configure the DMA descriptor related parameters 
+      \arg        VLAN_OPTION: choose to configure vlan related parameters
+      \arg        FLOWCTL_OPTION: choose to configure flow control related parameters
+      \arg        HASHH_OPTION: choose to configure hash high
+      \arg        HASHL_OPTION: choose to configure hash low
+      \arg        FILTER_OPTION: choose to configure frame filter related parameters
+      \arg        HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters
+      \arg        TIMER_OPTION: choose to configure time counter related parameters
+      \arg        INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters
+    \param[in]  para: the related parameters according to the option 
+                      all the related parameters should be configured which are shown as below
+                      FORWARD_OPTION related parameters:
+                      -  ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ;
+                      -  ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ;
+                      -  ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE .
+                      DMABUS_OPTION related parameters:
+                      -  ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ;
+                      -  ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ;
+                      DMA_MAXBURST_OPTION related parameters:
+                      -  ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/
+                         ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/
+                         ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/
+                         ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/
+                         ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ;
+                      -  ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/
+                         ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/
+                         ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/
+                         ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/
+                         ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ;
+                      -  ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ;
+                      DMA_ARBITRATION_OPTION related parameters:
+                      -  ENET_ARBITRATION_RXPRIORTX / ENET_ARBITRATION_RXTX_1_1
+                         / ENET_ARBITRATION_RXTX_2_1/ ENET_ARBITRATION_RXTX_3_1
+                         / ENET_ARBITRATION_RXTX_4_1.
+                      STORE_OPTION related parameters:
+                      -  ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ;
+                      -  ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ;
+                      -  ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/
+                         ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ;
+                      -  ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/
+                         ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/
+                         ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/
+                         ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES .
+                      DMA_OPTION related parameters:
+                      -  ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ;
+                      -  ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE .
+                      VLAN_OPTION related parameters:
+                      -  ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ;
+                      -  MAC_VLT_VLTI(regval) .
+                      FLOWCTL_OPTION related parameters:
+                      -  MAC_FCTL_PTM(regval) ;
+                      -  ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ;
+                      -  ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ 
+                         ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ;
+                      -  ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ;
+                      -  ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ;
+                      -  ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE ;
+                      -  ENET_ACTIVE_THRESHOLD_256BYTES/ ENET_ACTIVE_THRESHOLD_512BYTES ;
+                      -  ENET_ACTIVE_THRESHOLD_768BYTES/ ENET_ACTIVE_THRESHOLD_1024BYTES ;
+                      -  ENET_ACTIVE_THRESHOLD_1280BYTES/ ENET_ACTIVE_THRESHOLD_1536BYTES ;
+                      -  ENET_ACTIVE_THRESHOLD_1792BYTES ;
+                      -  ENET_DEACTIVE_THRESHOLD_256BYTES/ ENET_DEACTIVE_THRESHOLD_512BYTES ;
+                      -  ENET_DEACTIVE_THRESHOLD_768BYTES/ ENET_DEACTIVE_THRESHOLD_1024BYTES ;
+                      -  ENET_DEACTIVE_THRESHOLD_1280BYTES/ ENET_DEACTIVE_THRESHOLD_1536BYTES ;
+                      -  ENET_DEACTIVE_THRESHOLD_1792BYTES .
+                      HASHH_OPTION related parameters:
+                      -  0x0~0xFFFF FFFFU
+                      HASHL_OPTION related parameters:
+                      -  0x0~0xFFFF FFFFU
+                      FILTER_OPTION related parameters:
+                      -  ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/
+                         ENET_SRC_FILTER_DISABLE ;
+                      -  ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ;
+                      -  ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/
+                         ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ;
+                      -  ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/
+                         ENET_UNICAST_FILTER_PERFECT ;
+                      -  ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/
+                         ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED .
+                      HALFDUPLEX_OPTION related parameters:
+                      -  ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ;
+                      -  ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ;
+                      -  ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ;
+                      -  ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/
+                         ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ;
+                      -  ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE .
+                      TIMER_OPTION related parameters:
+                      -  ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ;
+                      -  ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ;
+                      INTERFRAMEGAP_OPTION related parameters:
+                      -  ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/
+                         ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/
+                         ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/
+                         ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT .
+    \param[out] none    
+    \retval     none
+*/
+void enet_initpara_config(enet_option_enum option, uint32_t para)
+{
+    switch(option){
+    case FORWARD_OPTION:
+        /* choose to configure forward_frame, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION;
+        enet_initpara.forward_frame = para;
+        break;
+    case DMABUS_OPTION:
+        /* choose to configure dmabus_mode, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION;
+        enet_initpara.dmabus_mode = para;
+        break;
+    case DMA_MAXBURST_OPTION:
+        /* choose to configure dma_maxburst, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION;
+        enet_initpara.dma_maxburst = para;
+        break;
+    case DMA_ARBITRATION_OPTION:
+        /* choose to configure dma_arbitration, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION;
+        enet_initpara.dma_arbitration = para;
+        break;
+    case STORE_OPTION:
+        /* choose to configure store_forward_mode, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)STORE_OPTION;
+        enet_initpara.store_forward_mode = para;
+        break;
+    case DMA_OPTION:
+        /* choose to configure dma_function, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)DMA_OPTION;
+        enet_initpara.dma_function = para;
+        break;
+    case VLAN_OPTION:
+        /* choose to configure vlan_config, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)VLAN_OPTION;
+        enet_initpara.vlan_config = para;
+        break;
+    case FLOWCTL_OPTION:
+        /* choose to configure flow_control, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION;
+        enet_initpara.flow_control = para;
+        break;
+    case HASHH_OPTION:
+        /* choose to configure hashtable_high, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)HASHH_OPTION;
+        enet_initpara.hashtable_high = para;
+        break;
+    case HASHL_OPTION:
+        /* choose to configure hashtable_low, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)HASHL_OPTION;
+        enet_initpara.hashtable_low = para;
+        break;
+    case FILTER_OPTION:
+        /* choose to configure framesfilter_mode, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)FILTER_OPTION;
+        enet_initpara.framesfilter_mode = para;
+        break;
+    case HALFDUPLEX_OPTION:
+        /* choose to configure halfduplex_param, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION;
+        enet_initpara.halfduplex_param = para;
+        break;
+    case TIMER_OPTION:
+        /* choose to configure timer_config, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)TIMER_OPTION;
+        enet_initpara.timer_config = para; 
+        break;
+    case INTERFRAMEGAP_OPTION:
+        /* choose to configure interframegap, and save the configuration parameters */
+        enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION;
+        enet_initpara.interframegap = para;
+        break;
+    default:
+        break;    
+    }      
+} 
+
+/*!
+    \brief      initialize ENET peripheral with generally concerned parameters and the less cared 
+                parameters
+    \param[in]  mediamode: PHY mode and mac loopback configurations, only one parameter can be selected
+                           which is shown as below, refer to enet_mediamode_enum 
+      \arg        ENET_AUTO_NEGOTIATION: PHY auto negotiation
+      \arg        ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex
+      \arg        ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex
+      \arg        ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex
+      \arg        ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex
+      \arg        ENET_LOOPBACKMODE: MAC in loopback mode at the MII
+    \param[in]  checksum: IP frame checksum offload function, only one parameter can be selected
+                          which is shown as below, refer to enet_mediamode_enum 
+      \arg        ENET_NO_AUTOCHECKSUM: disable IP frame checksum function
+      \arg        ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function
+      \arg        ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame
+                                                       with only payload error but no other errors will not be dropped
+    \param[in]  recept: frame filter function, only one parameter can be selected
+                          which is shown as below, refer to enet_frmrecept_enum 
+      \arg        ENET_PROMISCUOUS_MODE: promiscuous mode enabled
+      \arg        ENET_RECEIVEALL: all received frame are forwarded to application
+      \arg        ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames
+      \arg        ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames
+    \param[out] none    
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept)
+{
+    uint32_t reg_value=0U, reg_temp = 0U, temp = 0U;
+    uint32_t media_temp = 0U;
+    uint32_t timeout = 0U;
+    uint16_t phy_value = 0U;  
+    ErrStatus phy_state= ERROR, enet_state = ERROR;
+  
+    /* PHY interface configuration, configure SMI clock and reset PHY chip */
+    if(ERROR == enet_phy_config()){
+        _ENET_DELAY_(PHY_RESETDELAY);
+        if(ERROR == enet_phy_config()){
+            return enet_state;
+        }  
+    }
+    /* initialize ENET peripheral with generally concerned parameters */
+    enet_default_init();
+  
+    /* 1st, configure mediamode */
+    media_temp = (uint32_t)mediamode;
+    /* if is PHY auto negotiation */
+    if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){
+        /* wait for PHY_LINKED_STATUS bit be set */
+        do{
+            enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
+            phy_value &= PHY_LINKED_STATUS;  
+            timeout++;
+        }while((RESET == phy_value) && (timeout < PHY_READ_TO));
+        /* return ERROR due to timeout */
+        if(PHY_READ_TO == timeout){
+            return enet_state;
+        }
+        /* reset timeout counter */
+        timeout = 0U;
+        
+        /* enable auto-negotiation */
+        phy_value = PHY_AUTONEGOTIATION;
+        phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
+        if(!phy_state){
+            /* return ERROR due to write timeout */
+            return enet_state;
+        }
+    
+        /* wait for the PHY_AUTONEGO_COMPLETE bit be set */
+        do{
+            enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
+            phy_value &= PHY_AUTONEGO_COMPLETE;
+            timeout++;
+        }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO));  
+        /* return ERROR due to timeout */
+        if(PHY_READ_TO == timeout){
+            return enet_state;
+        }
+        /* reset timeout counter */
+        timeout = 0U;
+    
+        /* read the result of the auto-negotiation */
+        enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value);  
+        /* configure the duplex mode of MAC following the auto-negotiation result */
+        if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){
+            media_temp = ENET_MODE_FULLDUPLEX;
+        }else{
+            media_temp = ENET_MODE_HALFDUPLEX;
+        }
+        /* configure the communication speed of MAC following the auto-negotiation result */
+        if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){
+            media_temp |= ENET_SPEEDMODE_10M;
+        }else{
+            media_temp |= ENET_SPEEDMODE_100M;
+        }    
+    }else{
+        phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3);
+        phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1);
+        phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
+        if(!phy_state){
+            /* return ERROR due to write timeout */
+            return enet_state;
+        }
+        /* PHY configuration need some time */
+        _ENET_DELAY_(PHY_CONFIGDELAY);      
+    }
+    /* after configuring the PHY, use mediamode to configure registers */
+    reg_value = ENET_MAC_CFG;
+    /* configure ENET_MAC_CFG register */
+    reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM));
+    reg_value |= media_temp;
+    ENET_MAC_CFG = reg_value;
+    
+    
+    /* 2st, configure checksum */
+    if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){
+        ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE;
+      
+        reg_value = ENET_DMA_CTL;
+        /* configure ENET_DMA_CTL register */
+        reg_value &= ~ENET_DMA_CTL_DTCERFD;
+        reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD);
+        ENET_DMA_CTL = reg_value;
+    }
+    
+    /* 3rd, configure recept */
+    ENET_MAC_FRMF |= (uint32_t)recept;
+    
+    /* 4th, configure different function options */
+    /* configure forward_frame related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){
+        reg_temp = enet_initpara.forward_frame;
+              
+        reg_value = ENET_MAC_CFG;
+        temp = reg_temp;
+        /* configure ENET_MAC_CFG register */
+        reg_value &= (~ENET_MAC_CFG_APCD);
+        temp &= ENET_MAC_CFG_APCD;
+        reg_value |= temp;
+        ENET_MAC_CFG = reg_value;
+      
+        reg_value = ENET_DMA_CTL;
+        temp = reg_temp;
+        /* configure ENET_DMA_CTL register */
+        reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF));
+        temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF) << 2);
+        reg_value |= (temp >> 2);
+        ENET_DMA_CTL = reg_value;
+    }
+
+    /* configure dmabus_mode related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){
+        temp = enet_initpara.dmabus_mode;
+      
+        reg_value = ENET_DMA_BCTL;
+        /* configure ENET_DMA_BCTL register */
+        reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \
+                      |ENET_DMA_BCTL_FPBL);
+        reg_value |= temp;
+        ENET_DMA_BCTL = reg_value;
+    }
+
+    /* configure dma_maxburst related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){   
+        temp = enet_initpara.dma_maxburst;
+      
+        reg_value = ENET_DMA_BCTL;
+        /* configure ENET_DMA_BCTL register */
+        reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP);    
+        reg_value |= temp;
+        ENET_DMA_BCTL = reg_value;
+    }
+
+    /* configure dma_arbitration related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){   
+        temp = enet_initpara.dma_arbitration;
+      
+        reg_value = ENET_DMA_BCTL;
+        /* configure ENET_DMA_BCTL register */
+        reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB);
+        reg_value |= temp;
+        ENET_DMA_BCTL = reg_value;
+    }
+    
+    /* configure store_forward_mode related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){   
+        temp = enet_initpara.store_forward_mode;
+      
+        reg_value = ENET_DMA_CTL;
+        /* configure ENET_DMA_CTL register */
+        reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC);
+        reg_value |= temp;
+        ENET_DMA_CTL = reg_value;
+    }
+
+    /* configure dma_function related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){   
+        reg_temp = enet_initpara.dma_function;
+              
+        reg_value = ENET_DMA_CTL;
+        /* configure ENET_DMA_CTL register */
+        reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF));
+        reg_value |= reg_temp;
+        ENET_DMA_CTL = reg_value;
+    }
+
+    /* configure vlan_config related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){   
+        reg_temp = enet_initpara.vlan_config;
+              
+        reg_value = ENET_MAC_VLT;
+        /* configure ENET_MAC_VLT register */
+        reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC);
+        reg_value |= reg_temp;
+        ENET_MAC_VLT = reg_value;
+    }
+
+    /* configure flow_control related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){   
+        reg_temp = enet_initpara.flow_control;
+              
+        reg_value = ENET_MAC_FCTL;
+        temp = reg_temp;
+        /* configure ENET_MAC_FCTL register */
+        reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \
+                      | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN);
+        temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \
+                 | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN);
+        reg_value |= temp;
+        ENET_MAC_FCTL = reg_value;
+      
+        reg_value = ENET_MAC_FCTH;
+        temp = reg_temp;
+        /* configure ENET_MAC_FCTH register */
+        reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD);
+        temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8);
+        reg_value |= (temp >> 8);
+        ENET_MAC_FCTH = reg_value;
+    }    
+    
+    /* configure hashtable_high related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){   
+        ENET_MAC_HLH = enet_initpara.hashtable_high;
+    } 
+
+    /* configure hashtable_low related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){   
+        ENET_MAC_HLL = enet_initpara.hashtable_low;
+    }    
+
+    /* configure framesfilter_mode related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){   
+        reg_temp = enet_initpara.framesfilter_mode;
+              
+        reg_value = ENET_MAC_FRMF;
+        /* configure ENET_MAC_FRMF register */
+        reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \
+                      | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \
+                      | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM);
+        reg_value |= reg_temp;
+        ENET_MAC_FRMF = reg_value;
+    }  
+
+    /* configure halfduplex_param related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){   
+        reg_temp = enet_initpara.halfduplex_param;
+              
+        reg_value = ENET_MAC_CFG;
+        /* configure ENET_MAC_CFG register */
+        reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \
+                      | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC);
+        reg_value |= reg_temp;
+        ENET_MAC_CFG = reg_value;
+    } 
+
+    /* configure timer_config related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){   
+        reg_temp = enet_initpara.timer_config;
+              
+        reg_value = ENET_MAC_CFG;
+        /* configure ENET_MAC_CFG register */
+        reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD);
+        reg_value |= reg_temp;
+        ENET_MAC_CFG = reg_value;
+    } 
+    
+    /* configure interframegap related registers */
+    if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){   
+        reg_temp = enet_initpara.interframegap;
+              
+        reg_value = ENET_MAC_CFG;
+        /* configure ENET_MAC_CFG register */
+        reg_value &= ~ENET_MAC_CFG_IGBS;
+        reg_value |= reg_temp;
+        ENET_MAC_CFG = reg_value;
+    }    
+
+    enet_state = SUCCESS;
+    return enet_state;
+}
+
+/*!
+    \brief      reset all core internal registers located in CLK_TX and CLK_RX
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_software_reset(void)
+{
+    uint32_t timeout = 0U;
+    ErrStatus enet_state = ERROR;
+    uint32_t dma_flag;
+    
+    /* reset all core internal registers located in CLK_TX and CLK_RX */
+    ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR;
+    
+    /* wait for reset operation complete */
+    do{
+        dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR);
+        timeout++;
+    }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout));
+
+    /* reset operation complete */    
+    if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){
+        enet_state = SUCCESS;
+    }
+    
+    return enet_state;
+}
+
+/*!
+    \brief      check receive frame valid and return frame size
+    \param[in]  none
+    \param[out] none
+    \retval     size of received frame: 0x0 - 0x3FFF
+*/
+uint32_t enet_rxframe_size_get(void)
+{
+    uint32_t size = 0U;
+    uint32_t status;
+    
+    /* get rdes0 information of current RxDMA descriptor */
+    status = dma_current_rxdesc->status;
+    
+    /* if the desciptor is owned by DMA */
+    if((uint32_t)RESET != (status & ENET_RDES0_DAV)){
+        return 0U;
+    }
+    
+    /* if has any error, or the frame uses two or more descriptors */
+    if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) ||
+       (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) ||
+       (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){
+        /* drop current receive frame */
+        enet_rxframe_drop();
+
+        return 1U;
+    }
+
+    /* if is an ethernet-type frame, and IP frame payload error occurred */
+    if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) &&
+       (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){
+         /* drop current receive frame */
+         enet_rxframe_drop();
+
+        return 1U;
+    }  
+
+    /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */
+    if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) &&
+       (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) &&
+       (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) &&
+       (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){
+        /* get the size of the received data including CRC */
+        size = GET_RDES0_FRML(status);
+        /* substract the CRC size */ 
+        size = size - 4U;
+    }else{
+        enet_unknow_err++;
+        enet_rxframe_drop();
+
+        return 1U;
+    }
+ 
+    /* return packet size */ 
+    return size;
+}
+
+/*!
+    \brief      initialize the DMA Tx/Rx descriptors's parameters in chain mode
+    \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: DMA Tx descriptors
+      \arg        ENET_DMA_RX: DMA Rx descriptors
+    \param[out] none
+    \retval     none
+*/
+void enet_descriptors_chain_init(enet_dmadirection_enum direction)
+{
+    uint32_t num = 0U, count = 0U, maxsize = 0U;
+    uint32_t desc_status = 0U, desc_bufsize = 0U;
+    enet_descriptors_struct *desc, *desc_tab;
+    uint8_t *buf;  
+
+    /* if want to initialize DMA Tx descriptors */
+    if (ENET_DMA_TX == direction){
+        /* save a copy of the DMA Tx descriptors */
+        desc_tab = txdesc_tab;
+        buf = &tx_buff[0][0];
+        count = ENET_TXBUF_NUM;
+        maxsize = ENET_TXBUF_SIZE;
+      
+        /* select chain mode */
+        desc_status = ENET_TDES0_TCHM;
+      
+        /* configure DMA Tx descriptor table address register */
+        ENET_DMA_TDTADDR = (uint32_t)desc_tab;
+        dma_current_txdesc = desc_tab;
+    }else{ 
+        /* if want to initialize DMA Rx descriptors */
+        /* save a copy of the DMA Rx descriptors */
+        desc_tab = rxdesc_tab;
+        buf = &rx_buff[0][0];
+        count = ENET_RXBUF_NUM;
+        maxsize = ENET_RXBUF_SIZE;
+      
+        /* enable receiving */
+        desc_status = ENET_RDES0_DAV;
+        /* select receive chained mode and set buffer1 size */
+        desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE;
+      
+        /* configure DMA Rx descriptor table address register */
+        ENET_DMA_RDTADDR = (uint32_t)desc_tab;
+        dma_current_rxdesc = desc_tab; 
+    }
+    dma_current_ptp_rxdesc = NULL;
+    dma_current_ptp_txdesc = NULL;
+    
+    /* configure each descriptor */   
+    for(num=0U; num < count; num++){
+        /* get the pointer to the next descriptor of the descriptor table */
+        desc = desc_tab + num;
+
+        /* configure descriptors */
+        desc->status = desc_status;         
+        desc->control_buffer_size = desc_bufsize;
+        desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
+    
+        /* if is not the last descriptor */
+        if(num < (count - 1U)){
+            /* configure the next descriptor address */
+            desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U);
+        }else{
+            /* when it is the last descriptor, the next descriptor address 
+            equals to first descriptor address in descriptor table */ 
+            desc->buffer2_next_desc_addr = (uint32_t) desc_tab;  
+        }
+    }  
+}
+
+/*!
+    \brief      initialize the DMA Tx/Rx descriptors's parameters in ring mode
+    \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: DMA Tx descriptors
+      \arg        ENET_DMA_RX: DMA Rx descriptors
+    \param[out] none
+    \retval     none
+*/
+void enet_descriptors_ring_init(enet_dmadirection_enum direction)
+{
+    uint32_t num = 0U, count = 0U, maxsize = 0U;
+    uint32_t desc_status = 0U, desc_bufsize = 0U;
+    enet_descriptors_struct *desc;
+    enet_descriptors_struct *desc_tab;
+    uint8_t *buf; 
+  
+    /* configure descriptor skip length */
+    ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL;
+    ENET_DMA_BCTL |= DMA_BCTL_DPSL(0);
+  
+    /* if want to initialize DMA Tx descriptors */
+    if (ENET_DMA_TX == direction){
+        /* save a copy of the DMA Tx descriptors */
+        desc_tab = txdesc_tab;
+        buf = &tx_buff[0][0];
+        count = ENET_TXBUF_NUM;
+        maxsize = ENET_TXBUF_SIZE;      
+      
+        /* configure DMA Tx descriptor table address register */
+        ENET_DMA_TDTADDR = (uint32_t)desc_tab;
+        dma_current_txdesc = desc_tab;
+    }else{
+        /* if want to initialize DMA Rx descriptors */
+        /* save a copy of the DMA Rx descriptors */
+        desc_tab = rxdesc_tab;
+        buf = &rx_buff[0][0];
+        count = ENET_RXBUF_NUM;
+        maxsize = ENET_RXBUF_SIZE;      
+      
+        /* enable receiving */
+        desc_status = ENET_RDES0_DAV;
+        /* set buffer1 size */
+        desc_bufsize = ENET_RXBUF_SIZE;
+      
+         /* configure DMA Rx descriptor table address register */
+        ENET_DMA_RDTADDR = (uint32_t)desc_tab;
+        dma_current_rxdesc = desc_tab; 
+    }
+    dma_current_ptp_rxdesc = NULL;
+    dma_current_ptp_txdesc = NULL;
+    
+    /* configure each descriptor */   
+    for(num=0U; num < count; num++){
+        /* get the pointer to the next descriptor of the descriptor table */
+        desc = desc_tab + num;
+
+        /* configure descriptors */
+        desc->status = desc_status; 
+        desc->control_buffer_size = desc_bufsize;      
+        desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);    
+    
+        /* when it is the last descriptor */
+        if(num == (count - 1U)){
+            if (ENET_DMA_TX == direction){
+                /* configure transmit end of ring mode */  
+                desc->status |= ENET_TDES0_TERM;
+            }else{
+                /* configure receive end of ring mode */
+                desc->control_buffer_size |= ENET_RDES1_RERM;
+            }
+        }
+    }   
+}
+
+/*!
+    \brief      handle current received frame data to application buffer
+    \param[in]  bufsize: the size of buffer which is the parameter in function
+    \param[out] buffer: pointer to the received frame data
+                note -- if the input is NULL, user should copy data in application by himself
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize)
+{
+    uint32_t offset = 0U, size = 0U;
+    
+    /* the descriptor is busy due to own by the DMA */
+    if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){
+        return ERROR; 
+    }
+    
+
+    /* if buffer pointer is null, indicates that users has copied data in application */
+    if(NULL != buffer){
+        /* if no error occurs, and the frame uses only one descriptor */
+        if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && 
+           (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) &&  
+           (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){      
+            /* get the frame length except CRC */
+            size = GET_RDES0_FRML(dma_current_rxdesc->status);
+            size = size - 4U;
+            
+            /* to avoid situation that the frame size exceeds the buffer length */
+            if(size > bufsize){
+                return ERROR;
+            }
+            
+            /* copy data from Rx buffer to application buffer */
+            for(offset = 0U; offset<size; offset++){
+                (*(buffer + offset)) = (*(__IO uint8_t *) (uint32_t)((dma_current_rxdesc->buffer1_addr) + offset));
+            }
+            
+        }else{
+            /* return ERROR */
+            return ERROR;
+        }
+    }
+    /* enable reception, descriptor is owned by DMA */
+    dma_current_rxdesc->status = ENET_RDES0_DAV; 
+ 
+    /* check Rx buffer unavailable flag status */
+    if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){
+        /* clear RBU flag */
+        ENET_DMA_STAT = ENET_DMA_STAT_RBU;
+        /* resume DMA reception by writing to the RPEN register*/
+        ENET_DMA_RPEN = 0U;
+    }
+  
+    /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */      
+    /* chained mode */
+    if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){      
+        dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr);    
+    }else{    
+        /* ring mode */
+        if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){
+            /* if is the last descriptor in table, the next descriptor is the table header */
+            dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR);      
+        }else{ 
+            /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
+            dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)));      
+        }
+    }
+  
+    return SUCCESS;
+}
+
+/*!
+    \brief      handle application buffer data to transmit it
+    \param[in]  buffer: pointer to the frame data to be transmitted,
+                note -- if the input is NULL, user should handle the data in application by himself
+    \param[in]  length: the length of frame data to be transmitted
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length)
+{
+    uint32_t offset = 0U;
+    uint32_t dma_tbu_flag, dma_tu_flag;
+    
+    /* the descriptor is busy due to own by the DMA */
+    if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){
+        return ERROR;
+    }
+    
+    /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */
+    if(length > ENET_MAX_FRAME_SIZE){
+        return ERROR;
+    } 
+    
+    /* if buffer pointer is null, indicates that users has handled data in application */
+    if(NULL != buffer){    
+        /* copy frame data from application buffer to Tx buffer */
+        for(offset = 0U; offset < length; offset++){
+            (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset));
+        }
+    }
+    
+    /* set the frame length */
+    dma_current_txdesc->control_buffer_size = length;
+    /* set the segment of frame, frame is transmitted in one descriptor */    
+    dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG;
+    /* enable the DMA transmission */
+    dma_current_txdesc->status |= ENET_TDES0_DAV;
+    
+    /* check Tx buffer unavailable flag status */
+    dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); 
+    dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU);
+    
+    if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){
+        /* clear TBU and TU flag */
+        ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag);
+        /* resume DMA transmission by writing to the TPEN register*/
+        ENET_DMA_TPEN = 0U;
+    }
+  
+    /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/  
+    /* chained mode */
+    if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){     
+        dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr);    
+    }else{   
+        /* ring mode */
+        if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){
+            /* if is the last descriptor in table, the next descriptor is the table header */
+            dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR);      
+        }else{
+            /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
+            dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)));
+        }
+    }
+
+    return SUCCESS;
+}
+
+/*!
+    \brief      configure the transmit IP frame checksum offload calculation and insertion
+    \param[in]  desc: the descriptor pointer which users want to configure
+    \param[in]  checksum: IP frame checksum configuration
+                only one parameter can be selected which is shown as below
+      \arg        ENET_CHECKSUM_DISABLE: checksum insertion disabled
+      \arg        ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled
+      \arg        ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header
+      \arg        ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated
+    \param[out] none
+    \retval     none
+*/
+void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum)
+{
+    desc->status &= ~ENET_TDES0_CM;
+    desc->status |= checksum;
+}
+
+/*!
+    \brief      ENET Tx and Rx function enable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_enable(void)
+{
+    enet_tx_enable();
+    enet_rx_enable();
+}
+
+/*!
+    \brief      ENET Tx and Rx function disable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_disable(void)
+{
+    enet_tx_disable();
+    enet_rx_disable();
+}
+
+/*!
+    \brief      configure MAC address 
+    \param[in]  mac_addr: select which MAC address will be set, 
+                only one parameter can be selected which is shown as below  
+      \arg        ENET_MAC_ADDRESS0: set MAC address 0 filter
+      \arg        ENET_MAC_ADDRESS1: set MAC address 1 filter
+      \arg        ENET_MAC_ADDRESS2: set MAC address 2 filter
+      \arg        ENET_MAC_ADDRESS3: set MAC address 3 filter
+    \param[in]  paddr: the buffer pointer which stores the MAC address
+                  (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) 
+    \param[out] none
+    \retval     none
+*/ 
+void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[])
+{
+    REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr);
+    REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr);
+}
+
+/*!
+    \brief      get MAC address 
+    \param[in]  mac_addr: select which MAC address will be get,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_ADDRESS0: get MAC address 0 filter
+      \arg        ENET_MAC_ADDRESS1: get MAC address 1 filter
+      \arg        ENET_MAC_ADDRESS2: get MAC address 2 filter
+      \arg        ENET_MAC_ADDRESS3: get MAC address 3 filter
+    \param[out] paddr: the buffer pointer which is stored the MAC address
+                  (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) 
+    \retval     none
+*/                                   
+void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[])
+{
+    paddr[0] = ENET_GET_MACADDR(mac_addr, 0U);
+    paddr[1] = ENET_GET_MACADDR(mac_addr, 1U);
+    paddr[2] = ENET_GET_MACADDR(mac_addr, 2U);
+    paddr[3] = ENET_GET_MACADDR(mac_addr, 3U);
+    paddr[4] = ENET_GET_MACADDR(mac_addr, 4U);
+    paddr[5] = ENET_GET_MACADDR(mac_addr, 5U);
+}
+
+/*!
+    \brief      get the ENET MAC/MSC/PTP/DMA status flag 
+    \param[in]  enet_flag: ENET status flag, refer to enet_flag_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_FLAG_MPKR: magic packet received flag 
+      \arg        ENET_MAC_FLAG_WUFR: wakeup frame received flag
+      \arg        ENET_MAC_FLAG_FLOWCONTROL: flow control status flag 
+      \arg        ENET_MAC_FLAG_WUM: WUM status flag
+      \arg        ENET_MAC_FLAG_MSC: MSC status flag
+      \arg        ENET_MAC_FLAG_MSCR: MSC receive status flag
+      \arg        ENET_MAC_FLAG_MSCT: MSC transmit status flag
+      \arg        ENET_MAC_FLAG_TMST: time stamp trigger status flag
+      \arg        ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag
+      \arg        ENET_PTP_FLAG_TTM: target time match flag
+      \arg        ENET_MSC_FLAG_RFCE: received frames CRC error flag
+      \arg        ENET_MSC_FLAG_RFAE: received frames alignment error flag
+      \arg        ENET_MSC_FLAG_RGUF: received good unicast frames flag
+      \arg        ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag
+      \arg        ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag
+      \arg        ENET_MSC_FLAG_TGF: transmitted good frames flag
+      \arg        ENET_DMA_FLAG_TS: transmit status flag
+      \arg        ENET_DMA_FLAG_TPS: transmit process stopped status flag
+      \arg        ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag
+      \arg        ENET_DMA_FLAG_TJT: transmit jabber timeout status flag
+      \arg        ENET_DMA_FLAG_RO: receive overflow status flag
+      \arg        ENET_DMA_FLAG_TU: transmit underflow status flag
+      \arg        ENET_DMA_FLAG_RS: receive status flag
+      \arg        ENET_DMA_FLAG_RBU: receive buffer unavailable status flag
+      \arg        ENET_DMA_FLAG_RPS: receive process stopped status flag
+      \arg        ENET_DMA_FLAG_RWT: receive watchdog timeout status flag
+      \arg        ENET_DMA_FLAG_ET: early transmit status flag
+      \arg        ENET_DMA_FLAG_FBE: fatal bus error status flag
+      \arg        ENET_DMA_FLAG_ER: early receive status flag
+      \arg        ENET_DMA_FLAG_AI: abnormal interrupt summary flag
+      \arg        ENET_DMA_FLAG_NI: normal interrupt summary flag
+      \arg        ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag
+      \arg        ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag
+      \arg        ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag
+      \arg        ENET_DMA_FLAG_MSC: MSC status flag
+      \arg        ENET_DMA_FLAG_WUM: WUM status flag
+      \arg        ENET_DMA_FLAG_TST: timestamp trigger status flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus enet_flag_get(enet_flag_enum enet_flag)
+{
+    if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear the ENET DMA status flag 
+    \param[in]  enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_FLAG_TS_CLR: transmit status flag clear
+      \arg        ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear
+      \arg        ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear
+      \arg        ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear
+      \arg        ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear
+      \arg        ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear
+      \arg        ENET_DMA_FLAG_RS_CLR: receive status flag clear
+      \arg        ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear
+      \arg        ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear
+      \arg        ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear
+      \arg        ENET_DMA_FLAG_ET_CLR: early transmit status flag clear
+      \arg        ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear
+      \arg        ENET_DMA_FLAG_ER_CLR: early receive status flag clear
+      \arg        ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear
+      \arg        ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear
+    \param[out] none
+    \retval     none
+*/
+void enet_flag_clear(enet_flag_clear_enum enet_flag)
+{
+    /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */
+    ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag));
+}
+
+/*!
+    \brief      enable ENET MAC/MSC/DMA interrupt 
+    \param[in]  enet_int: ENET interrupt,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_INT_WUMIM: WUM interrupt mask
+      \arg        ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask
+      \arg        ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask
+      \arg        ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask
+      \arg        ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask
+      \arg        ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask
+      \arg        ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask
+      \arg        ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask
+      \arg        ENET_DMA_INT_TIE: transmit interrupt enable
+      \arg        ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable
+      \arg        ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable
+      \arg        ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable
+      \arg        ENET_DMA_INT_ROIE: receive overflow interrupt enable
+      \arg        ENET_DMA_INT_TUIE: transmit underflow interrupt enable
+      \arg        ENET_DMA_INT_RIE: receive interrupt enable
+      \arg        ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable
+      \arg        ENET_DMA_INT_RPSIE: receive process stopped interrupt enable
+      \arg        ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable
+      \arg        ENET_DMA_INT_ETIE: early transmit interrupt enable
+      \arg        ENET_DMA_INT_FBEIE: fatal bus error interrupt enable
+      \arg        ENET_DMA_INT_ERIE: early receive interrupt enable
+      \arg        ENET_DMA_INT_AIE: abnormal interrupt summary enable
+      \arg        ENET_DMA_INT_NIE: normal interrupt summary enable
+    \param[out] none
+    \retval     none
+*/
+void enet_interrupt_enable(enet_int_enum enet_int)
+{
+    if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){
+        /* ENET_DMA_INTEN register interrupt */
+        ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int));
+    }else{
+        /* other INTMSK register interrupt */
+        ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int));
+    }
+}
+
+/*!
+    \brief      disable ENET MAC/MSC/DMA interrupt 
+    \param[in]  enet_int: ENET interrupt,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_INT_WUMIM: WUM interrupt mask
+      \arg        ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask
+      \arg        ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask
+      \arg        ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask
+      \arg        ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask
+      \arg        ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask
+      \arg        ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask
+      \arg        ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask
+      \arg        ENET_DMA_INT_TIE: transmit interrupt enable
+      \arg        ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable
+      \arg        ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable
+      \arg        ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable
+      \arg        ENET_DMA_INT_ROIE: receive overflow interrupt enable
+      \arg        ENET_DMA_INT_TUIE: transmit underflow interrupt enable
+      \arg        ENET_DMA_INT_RIE: receive interrupt enable
+      \arg        ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable
+      \arg        ENET_DMA_INT_RPSIE: receive process stopped interrupt enable
+      \arg        ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable
+      \arg        ENET_DMA_INT_ETIE: early transmit interrupt enable
+      \arg        ENET_DMA_INT_FBEIE: fatal bus error interrupt enable
+      \arg        ENET_DMA_INT_ERIE: early receive interrupt enable
+      \arg        ENET_DMA_INT_AIE: abnormal interrupt summary enable
+      \arg        ENET_DMA_INT_NIE: normal interrupt summary enable
+    \param[out] none
+    \retval     none
+*/
+void enet_interrupt_disable(enet_int_enum enet_int)
+{
+    if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){
+        /* ENET_DMA_INTEN register interrupt */
+        ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int));
+    }else{
+        /* other INTMSK register interrupt */
+        ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int));
+    }
+}
+
+/*!
+    \brief      get ENET MAC/MSC/DMA interrupt flag 
+    \param[in]  int_flag: ENET interrupt flag,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_INT_FLAG_WUM: WUM status flag
+      \arg        ENET_MAC_INT_FLAG_MSC: MSC status flag
+      \arg        ENET_MAC_INT_FLAG_MSCR: MSC receive status flag
+      \arg        ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag
+      \arg        ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag
+      \arg        ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag
+      \arg        ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag
+      \arg        ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag
+      \arg        ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag
+      \arg        ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag
+      \arg        ENET_MSC_INT_FLAG_TGF: transmitted good frames flag
+      \arg        ENET_DMA_INT_FLAG_TS: transmit status flag
+      \arg        ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag
+      \arg        ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag
+      \arg        ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag
+      \arg        ENET_DMA_INT_FLAG_RO: receive overflow status flag
+      \arg        ENET_DMA_INT_FLAG_TU: transmit underflow status flag
+      \arg        ENET_DMA_INT_FLAG_RS: receive status flag
+      \arg        ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag
+      \arg        ENET_DMA_INT_FLAG_RPS: receive process stopped status flag
+      \arg        ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag
+      \arg        ENET_DMA_INT_FLAG_ET: early transmit status flag
+      \arg        ENET_DMA_INT_FLAG_FBE: fatal bus error status flag
+      \arg        ENET_DMA_INT_FLAG_ER: early receive status flag
+      \arg        ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag
+      \arg        ENET_DMA_INT_FLAG_NI: normal interrupt summary flag
+      \arg        ENET_DMA_INT_FLAG_MSC: MSC status flag
+      \arg        ENET_DMA_INT_FLAG_WUM: WUM status flag
+      \arg        ENET_DMA_INT_FLAG_TST: timestamp trigger status flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag)
+{
+    if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear ENET DMA interrupt flag 
+    \param[in]  int_flag_clear: clear ENET interrupt flag,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_INT_FLAG_TS_CLR: transmit status flag
+      \arg        ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag
+      \arg        ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag
+      \arg        ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag
+      \arg        ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag
+      \arg        ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag
+      \arg        ENET_DMA_INT_FLAG_RS_CLR: receive status flag
+      \arg        ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag
+      \arg        ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag
+      \arg        ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag
+      \arg        ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag
+      \arg        ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag
+      \arg        ENET_DMA_INT_FLAG_ER_CLR: early receive status flag
+      \arg        ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag
+      \arg        ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag
+    \param[out] none
+    \retval     none
+*/
+void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear)
+{
+    /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */
+    ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear));
+}
+
+/*!
+    \brief      ENET Tx function enable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_tx_enable(void)
+{
+    ENET_MAC_CFG |= ENET_MAC_CFG_TEN;
+    enet_txfifo_flush();
+    ENET_DMA_CTL |= ENET_DMA_CTL_STE;
+}
+
+/*!
+    \brief      ENET Tx function disable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_tx_disable(void)
+{    
+    ENET_DMA_CTL &= ~ENET_DMA_CTL_STE;
+    enet_txfifo_flush();
+    ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN;
+}
+
+/*!
+    \brief      ENET Rx function enable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_rx_enable(void)
+{
+    ENET_MAC_CFG |= ENET_MAC_CFG_REN;
+    ENET_DMA_CTL |= ENET_DMA_CTL_SRE;
+}
+
+/*!
+    \brief      ENET Rx function disable (include MAC and DMA module)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_rx_disable(void)
+{
+    ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE;
+    ENET_MAC_CFG &= ~ENET_MAC_CFG_REN;
+}
+
+/*!
+    \brief      put registers value into the application buffer 
+    \param[in]  type: register type which will be get, refer to enet_registers_type_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH 
+      \arg        ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT
+      \arg        ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL
+      \arg        ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR
+    \param[in]  num: the number of registers that the user want to get
+    \param[out] preg: the application buffer pointer for storing the register value
+    \retval     none
+*/
+void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num)
+{
+    uint32_t offset = 0U, max = 0U, limit = 0U;
+    
+    offset = (uint32_t)type;
+    max = (uint32_t)type + num;
+    limit = sizeof(enet_reg_tab)/sizeof(uint16_t);
+    
+    /* prevent element in this array is out of range */
+    if(max > limit){ 
+        max = limit;
+    }
+    
+    for(; offset < max; offset++){
+        /* get value of the corresponding register */
+        *preg = REG32((ENET) + enet_reg_tab[offset]); 
+        preg++;
+    }
+} 
+
+/*!
+    \brief      enable the MAC address filter 
+    \param[in]  mac_addr: select which MAC address will be enable  
+      \arg        ENET_MAC_ADDRESS1: enable MAC address 1 filter
+      \arg        ENET_MAC_ADDRESS2: enable MAC address 2 filter
+      \arg        ENET_MAC_ADDRESS3: enable MAC address 3 filter
+    \param[out] none
+    \retval     none
+*/
+void enet_address_filter_enable(enet_macaddress_enum mac_addr)
+{
+    REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE;
+}
+
+/*!
+    \brief      disable the MAC address filter 
+    \param[in]  mac_addr: select which MAC address will be disable,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_ADDRESS1: disable MAC address 1 filter
+      \arg        ENET_MAC_ADDRESS2: disable MAC address 2 filter
+      \arg        ENET_MAC_ADDRESS3: disable MAC address 3 filter
+    \param[out] none
+    \retval     none
+*/
+void enet_address_filter_disable(enet_macaddress_enum mac_addr)
+{
+    REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE;
+}
+
+/*!
+    \brief      configure the MAC address filter 
+    \param[in]  mac_addr: select which MAC address will be configured,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC_ADDRESS1: configure MAC address 1 filter
+      \arg        ENET_MAC_ADDRESS2: configure MAC address 2 filter
+      \arg        ENET_MAC_ADDRESS3: configure MAC address 3 filter
+    \param[in]  addr_mask: select which MAC address bytes will be mask,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits
+      \arg        ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits 
+      \arg        ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits
+      \arg        ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits
+      \arg        ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits
+      \arg        ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits
+    \param[in]  filter_type: select which MAC address filter type will be selected,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame
+      \arg        ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame
+    \param[out] none
+    \retval     none
+*/
+void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type)
+{
+    uint32_t reg;
+    
+    /* get the address filter register value which is to be configured */
+    reg = REG32(ENET_ADDRH_BASE + mac_addr);
+
+    /* clear and configure the address filter register */
+    reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF);
+    reg |= (addr_mask | filter_type);
+    REG32(ENET_ADDRH_BASE + mac_addr) = reg;
+}
+
+/*!
+    \brief      PHY interface configuration (configure SMI clock and reset PHY chip)
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/ 
+ErrStatus enet_phy_config(void)
+{
+    uint32_t ahbclk;
+    uint32_t reg;
+    uint16_t phy_value;
+    ErrStatus enet_state = ERROR;
+  
+    /* clear the previous MDC clock */
+    reg = ENET_MAC_PHY_CTL;
+    reg &= ~ENET_MAC_PHY_CTL_CLR;
+
+    /* get the HCLK frequency */
+    ahbclk = rcu_clock_freq_get(CK_AHB);
+  
+    /* configure MDC clock according to HCLK frequency range */
+    if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){
+        reg |= ENET_MDC_HCLK_DIV16;
+    }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){
+        reg |= ENET_MDC_HCLK_DIV26;
+    }else if(ENET_RANGE(ahbclk, 60000000U, 90000000U)){
+        reg |= ENET_MDC_HCLK_DIV42;
+    }else if((ENET_RANGE(ahbclk, 90000000U, 108000000U))||(108000000U == ahbclk)){
+        reg |= ENET_MDC_HCLK_DIV62;    
+    }else{
+        return enet_state;
+    }
+    ENET_MAC_PHY_CTL = reg;
+
+    /* reset PHY */
+    phy_value = PHY_RESET;
+    if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){
+        return enet_state;
+    }
+    /* PHY reset need some time */    
+    _ENET_DELAY_(ENET_DELAY_TO);
+    
+    /* check whether PHY reset is complete */
+    if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){
+        return enet_state;
+    }
+
+    /* PHY reset complete */
+    if(RESET == (phy_value & PHY_RESET)){
+        enet_state = SUCCESS;
+    }
+    
+    return enet_state;
+}
+
+/*!
+    \brief      write to / read from a PHY register
+    \param[in]  direction: only one parameter can be selected which is shown as below
+      \arg        ENET_PHY_WRITE: write data to phy register
+      \arg        ENET_PHY_READ:  read data from phy register
+    \param[in]  phy_address: 0x0 - 0x1F
+    \param[in]  phy_reg: 0x0 - 0x1F
+    \param[in]  pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction 
+    \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue)
+{
+    uint32_t reg, phy_flag;
+    uint32_t timeout = 0U;
+    ErrStatus enet_state = ERROR;
+
+    /* configure ENET_MAC_PHY_CTL with write/read operation */  
+    reg = ENET_MAC_PHY_CTL;
+    reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA);
+    reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); 
+
+    /* if do the write operation, write value to the register */
+    if(ENET_PHY_WRITE == direction){
+        ENET_MAC_PHY_DATA = *pvalue;        
+    }
+    
+    /* do PHY write/read operation, and wait the operation complete  */
+    ENET_MAC_PHY_CTL = reg;
+    do{
+        phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB);
+        timeout++;
+    }
+    while((RESET != phy_flag) && (ENET_DELAY_TO != timeout));
+
+    /* write/read operation complete */    
+    if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){
+        enet_state = SUCCESS;
+    }
+
+    /* if do the read operation, get value from the register */    
+    if(ENET_PHY_READ == direction){
+        *pvalue = (uint16_t)ENET_MAC_PHY_DATA;        
+    }
+    
+    return enet_state;
+}
+
+/*!
+    \brief      enable the loopback function of PHY chip
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus enet_phyloopback_enable(void)
+{
+    uint16_t temp_phy = 0U;
+    ErrStatus phy_state = ERROR;
+
+    /* get the PHY configuration to update it */
+    enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); 
+
+    /* enable the PHY loopback mode */
+    temp_phy |= PHY_LOOPBACK;
+
+    /* update the PHY control register with the new configuration */
+    phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
+
+    return phy_state;
+}
+
+/*!
+    \brief      disable the loopback function of PHY chip
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus enet_phyloopback_disable(void)
+{
+    uint16_t temp_phy = 0U;
+    ErrStatus phy_state = ERROR;
+
+    /* get the PHY configuration to update it */
+    enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); 
+
+    /* disable the PHY loopback mode */
+    temp_phy &= (uint16_t)~PHY_LOOPBACK;
+
+    /* update the PHY control register with the new configuration */
+    phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
+
+    return phy_state;
+}
+
+/*!
+    \brief      enable ENET forward feature
+    \param[in]  feature: the feature of ENET forward mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames
+      \arg        ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory
+      \arg        ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames
+    \param[out] none
+    \retval     none
+*/
+void enet_forward_feature_enable(uint32_t feature)
+{
+    uint32_t mask;
+    
+    mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES)));
+    ENET_MAC_CFG |= mask;
+    
+    mask = (feature & (~(ENET_AUTO_PADCRC_DROP)));
+    ENET_DMA_CTL |= (mask >> 2);
+}
+
+/*!
+    \brief      disable ENET forward feature
+    \param[in]  feature: the feature of ENET forward mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames
+      \arg        ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory
+      \arg        ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames
+    \param[out] none
+    \retval     none
+*/
+void enet_forward_feature_disable(uint32_t feature)
+{
+    uint32_t mask;
+    
+    mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES)));
+    ENET_MAC_CFG &= ~mask;
+    
+    mask = (feature & (~(ENET_AUTO_PADCRC_DROP)));
+    ENET_DMA_CTL &= ~(mask >> 2);
+}
+                            
+/*!                    
+    \brief      enable ENET filter feature
+    \param[in]  feature: the feature of ENET filter mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_SRC_FILTER: filter source address function
+      \arg        ENET_SRC_FILTER_INVERSE: inverse source address filtering result function
+      \arg        ENET_DEST_FILTER_INVERSE: inverse DA filtering result function
+      \arg        ENET_MULTICAST_FILTER_PASS: pass all multicast frames function
+      \arg        ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function
+      \arg        ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function
+      \arg        ENET_FILTER_MODE_EITHER: HASH or perfect filter function
+    \param[out] none
+    \retval     none
+*/
+void enet_filter_feature_enable(uint32_t feature)
+{
+    ENET_MAC_FRMF |= feature;
+}
+
+/*!
+    \brief      disable ENET filter feature
+    \param[in]  feature: the feature of ENET filter mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_SRC_FILTER: filter source address function
+      \arg        ENET_SRC_FILTER_INVERSE: inverse source address filtering result function
+      \arg        ENET_DEST_FILTER_INVERSE: inverse DA filtering result function
+      \arg        ENET_MULTICAST_FILTER_PASS: pass all multicast frames function
+      \arg        ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function
+      \arg        ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function
+      \arg        ENET_FILTER_MODE_EITHER: HASH or perfect filter function
+    \param[out] none
+    \retval     none
+*/
+void enet_filter_feature_disable(uint32_t feature)
+{
+    ENET_MAC_FRMF &= ~feature;
+}
+
+/*!
+    \brief      generate the pause frame, ENET will send pause frame after enable transmit flow control
+                this function only use in full-dulex mode
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus enet_pauseframe_generate(void)  
+{ 
+    ErrStatus enet_state =ERROR;
+    uint32_t temp = 0U;
+
+    /* in full-duplex mode, must make sure this bit is 0 before writing register */
+    temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA;
+    if(RESET == temp){
+        ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA;
+        enet_state = SUCCESS;
+    }
+    return enet_state;    
+}
+
+/*!
+    \brief      configure the pause frame detect type
+    \param[in]  detect: pause frame detect type,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also
+                                                            use the MAC0 address to detecting pause frame
+      \arg        ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified 
+                                           in IEEE802.3 can be detected
+    \param[out] none
+    \retval     none
+*/
+void enet_pauseframe_detect_config(uint32_t detect)
+{
+    ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT;
+    ENET_MAC_FCTL |= detect;
+}
+
+/*!
+    \brief      configure the pause frame parameters
+    \param[in]  pausetime: pause time in transmit pause control frame
+    \param[in]  pause_threshold: the threshold of the pause timer for retransmitting frames automatically,
+                this value must make sure to be less than configured pause time, only one parameter can be
+                selected which is shown as below
+      \arg        ENET_PAUSETIME_MINUS4: pause time minus 4 slot times
+      \arg        ENET_PAUSETIME_MINUS28: pause time minus 28 slot times
+      \arg        ENET_PAUSETIME_MINUS144: pause time minus 144 slot times
+      \arg        ENET_PAUSETIME_MINUS256: pause time minus 256 slot times
+    \param[out] none
+    \retval     none
+*/
+void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold)
+{
+    ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS);
+    ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold);
+}
+
+/*!
+    \brief      configure the threshold of the flow control(deactive and active threshold)
+    \param[in]  deactive: the threshold of the deactive flow control, this value
+                should always be less than active flow control value, only one 
+                parameter can be selected which is shown as below
+      \arg        ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes
+      \arg        ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes
+    \param[in]  active: the threshold of the active flow control, only one parameter
+                can be selected which is shown as below
+      \arg        ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes
+      \arg        ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes
+    \param[out] none
+    \retval     none
+*/
+void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active)
+{
+    ENET_MAC_FCTH = ((deactive | active) >> 8); 
+}
+
+/*!
+    \brief      enable ENET flow control feature
+    \param[in]  feature: the feature of ENET flow control mode
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function
+      \arg        ENET_TX_FLOWCONTROL: the flow control operation in the MAC
+      \arg        ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it
+      \arg        ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode)
+    \param[out] none
+    \retval     none
+*/
+void enet_flowcontrol_feature_enable(uint32_t feature)
+{
+    if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){
+        ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE;
+    }
+    feature &= ~ENET_ZERO_QUANTA_PAUSE;
+    ENET_MAC_FCTL |= feature;
+}
+
+/*!
+    \brief      disable ENET flow control feature
+    \param[in]  feature: the feature of ENET flow control mode
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function
+      \arg        ENET_TX_FLOWCONTROL: the flow control operation in the MAC
+      \arg        ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it
+      \arg        ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode)
+    \param[out] none
+    \retval     none
+*/
+void enet_flowcontrol_feature_disable(uint32_t feature)
+{
+    if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){
+        ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE;
+    }
+    feature &= ~ENET_ZERO_QUANTA_PAUSE;
+    ENET_MAC_FCTL &= ~feature;
+}
+
+/*!
+    \brief      get the dma transmit/receive process state
+    \param[in]  direction: choose the direction of dma process which users want to check, 
+                refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: dma transmit process
+      \arg        ENET_DMA_RX: dma receive process
+    \param[out] none
+    \retval     state of dma process, the value range shows below:
+                  ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING,
+                  ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING,
+                  ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING,
+                  ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING
+*/
+uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction)
+{
+    uint32_t reval;
+    reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction);
+    return reval;
+}
+
+/*!
+    \brief      poll the DMA transmission/reception enable by writing any value to the 
+                ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception
+    \param[in]  direction: choose the direction of DMA process which users want to resume, 
+                refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: DMA transmit process
+      \arg        ENET_DMA_RX: DMA receive process
+    \param[out] none
+    \retval     none
+*/
+void enet_dmaprocess_resume(enet_dmadirection_enum direction)
+{
+    if(ENET_DMA_TX == direction){
+        ENET_DMA_TPEN = 0U;
+    }else{
+        ENET_DMA_RPEN = 0U;
+    }
+}
+
+/*!
+    \brief      check and recover the Rx process 
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_rxprocess_check_recovery(void)
+{
+    uint32_t status;
+
+    /* get DAV information of current RxDMA descriptor */  
+    status = dma_current_rxdesc->status;
+    status &= ENET_RDES0_DAV;
+    
+    /* if current descriptor is owned by DMA, but the descriptor address mismatches with 
+    receive descriptor address pointer updated by RxDMA controller */
+    if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) &&
+       (ENET_RDES0_DAV == status)){
+        dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR;
+    }
+}
+
+/*!
+    \brief      flush the ENET transmit FIFO, and wait until the flush operation completes
+    \param[in]  none
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus enet_txfifo_flush(void)
+{
+    uint32_t flush_state;
+    uint32_t timeout = 0U;
+    ErrStatus enet_state = ERROR;
+ 
+    /* set the FTF bit for flushing transmit FIFO */
+    ENET_DMA_CTL |= ENET_DMA_CTL_FTF;   
+    /* wait until the flush operation completes */
+    do{
+        flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; 
+        timeout++;
+    }while((RESET != flush_state) && (timeout < ENET_DELAY_TO));
+    /* return ERROR due to timeout */
+    if(RESET == flush_state){
+        enet_state = SUCCESS;
+    }
+    
+    return  enet_state;
+}
+
+/*!
+    \brief      get the transmit/receive address of current descriptor, or current buffer, or descriptor table
+    \param[in]  addr_get: choose the address which users want to get, refer to enet_desc_reg_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_RX_DESC_TABLE: the start address of the receive descriptor table
+      \arg        ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by
+                                        the RxDMA controller
+      \arg        ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller
+      \arg        ENET_TX_DESC_TABLE: the start address of the transmit descriptor table
+      \arg        ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by
+                                        the TxDMA controller
+      \arg        ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller
+    \param[out] none    
+    \retval     address value
+*/
+uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get)
+{
+    uint32_t reval = 0U;
+
+    reval = REG32((ENET) +(uint32_t)addr_get);
+    return reval;
+}
+
+/*!
+    \brief      get the Tx or Rx descriptor information
+    \param[in]  desc: the descriptor pointer which users want to get information
+    \param[in]  info_get: the descriptor information type which is selected,
+                only one parameter can be selected which is shown as below
+      \arg        RXDESC_BUFFER_1_SIZE: receive buffer 1 size
+      \arg        RXDESC_BUFFER_2_SIZE: receive buffer 2 size
+      \arg        RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer
+      \arg        TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted
+      \arg        RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame
+      \arg        TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame
+    \param[out] none
+    \retval     descriptor information, if value is 0xFFFFFFFFU, means the false input parameter
+*/
+uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get)
+{
+    uint32_t reval = 0xFFFFFFFFU;
+
+    switch(info_get){
+    case RXDESC_BUFFER_1_SIZE:
+        reval = GET_RDES1_RB1S(desc->control_buffer_size);
+        break;
+    case RXDESC_BUFFER_2_SIZE:
+        reval = GET_RDES1_RB2S(desc->control_buffer_size);
+        break; 
+    case RXDESC_FRAME_LENGTH:    
+        reval = GET_RDES0_FRML(desc->status);
+        if(reval > 4U){
+            reval = reval - 4U;
+        }else{
+            reval = 0U;
+        }
+        break;
+    case RXDESC_BUFFER_1_ADDR:    
+        reval = desc->buffer1_addr;    
+        break;
+    case TXDESC_BUFFER_1_ADDR:    
+        reval = desc->buffer1_addr;  
+        break;
+    case TXDESC_COLLISION_COUNT:    
+        reval = GET_TDES0_COCNT(desc->status);
+        break;    
+    default:
+        break;
+    }
+    return reval;
+}
+
+/*!
+    \brief      get the number of missed frames during receiving
+    \param[in]  none
+    \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO
+    \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller
+    \retval     none
+*/
+void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop)
+{
+    uint32_t temp_counter = 0U;
+  
+    temp_counter = ENET_DMA_MFBOCNT;
+    *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter);
+    *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter);
+}
+
+/*!
+    \brief      get the bit flag of ENET DMA descriptor
+    \param[in]  desc: the descriptor pointer which users want to get flag
+    \param[in]  desc_flag: the bit flag of ENET DMA descriptor,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_TDES0_DB: deferred 
+      \arg        ENET_TDES0_UFE: underflow error
+      \arg        ENET_TDES0_EXD: excessive deferral
+      \arg        ENET_TDES0_VFRM: VLAN frame
+      \arg        ENET_TDES0_ECO: excessive collision
+      \arg        ENET_TDES0_LCO: late collision
+      \arg        ENET_TDES0_NCA: no carrier
+      \arg        ENET_TDES0_LCA: loss of carrier
+      \arg        ENET_TDES0_IPPE: IP payload error
+      \arg        ENET_TDES0_FRMF: frame flushed
+      \arg        ENET_TDES0_JT: jabber timeout
+      \arg        ENET_TDES0_ES: error summary
+      \arg        ENET_TDES0_IPHE: IP header error
+      \arg        ENET_TDES0_TTMSS: transmit timestamp status 
+      \arg        ENET_TDES0_TCHM: the second address chained mode
+      \arg        ENET_TDES0_TERM: transmit end of ring mode
+      \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
+      \arg        ENET_TDES0_DPAD: disable adding pad      
+      \arg        ENET_TDES0_DCRC: disable CRC
+      \arg        ENET_TDES0_FSG: first segment
+      \arg        ENET_TDES0_LSG: last segment
+      \arg        ENET_TDES0_INTC: interrupt on completion
+      \arg        ENET_TDES0_DAV: DAV bit
+      
+      \arg        ENET_RDES0_PCERR: payload checksum error 
+      \arg        ENET_RDES0_CERR: CRC error
+      \arg        ENET_RDES0_DBERR: dribble bit error
+      \arg        ENET_RDES0_RERR: receive error
+      \arg        ENET_RDES0_RWDT: receive watchdog timeout
+      \arg        ENET_RDES0_FRMT: frame type
+      \arg        ENET_RDES0_LCO: late collision
+      \arg        ENET_RDES0_IPHERR: IP frame header error
+      \arg        ENET_RDES0_LDES: last descriptor
+      \arg        ENET_RDES0_FDES: first descriptor
+      \arg        ENET_RDES0_VTAG: VLAN tag
+      \arg        ENET_RDES0_OERR: overflow error 
+      \arg        ENET_RDES0_LERR: length error
+      \arg        ENET_RDES0_SAFF: SA filter fail
+      \arg        ENET_RDES0_DERR: descriptor error
+      \arg        ENET_RDES0_ERRS: error summary      
+      \arg        ENET_RDES0_DAFF: destination address filter fail
+      \arg        ENET_RDES0_DAV: descriptor available
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag)
+{
+    FlagStatus enet_flag = RESET;
+  
+    if ((uint32_t)RESET != (desc->status & desc_flag)){
+        enet_flag = SET;
+    }
+
+    return enet_flag;
+}
+
+/*!
+    \brief      set the bit flag of ENET DMA descriptor
+    \param[in]  desc: the descriptor pointer which users want to set flag
+    \param[in]  desc_flag: the bit flag of ENET DMA descriptor,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_TDES0_VFRM: VLAN frame
+      \arg        ENET_TDES0_FRMF: frame flushed
+      \arg        ENET_TDES0_TCHM: the second address chained mode
+      \arg        ENET_TDES0_TERM: transmit end of ring mode
+      \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
+      \arg        ENET_TDES0_DPAD: disable adding pad      
+      \arg        ENET_TDES0_DCRC: disable CRC
+      \arg        ENET_TDES0_FSG: first segment
+      \arg        ENET_TDES0_LSG: last segment
+      \arg        ENET_TDES0_INTC: interrupt on completion
+      \arg        ENET_TDES0_DAV: DAV bit
+      \arg        ENET_RDES0_DAV: descriptor available 
+    \param[out] none
+    \retval     none
+*/
+void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag)
+{
+    desc->status |= desc_flag;
+}
+
+/*!
+    \brief      clear the bit flag of ENET DMA descriptor
+    \param[in]  desc: the descriptor pointer which users want to clear flag
+    \param[in]  desc_flag: the bit flag of ENET DMA descriptor,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_TDES0_VFRM: VLAN frame
+      \arg        ENET_TDES0_FRMF: frame flushed
+      \arg        ENET_TDES0_TCHM: the second address chained mode
+      \arg        ENET_TDES0_TERM: transmit end of ring mode
+      \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
+      \arg        ENET_TDES0_DPAD: disable adding pad      
+      \arg        ENET_TDES0_DCRC: disable CRC
+      \arg        ENET_TDES0_FSG: first segment
+      \arg        ENET_TDES0_LSG: last segment
+      \arg        ENET_TDES0_INTC: interrupt on completion
+      \arg        ENET_TDES0_DAV: DAV bit
+      \arg        ENET_RDES0_DAV: descriptor available 
+    \param[out] none
+    \retval     none
+*/
+void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag)
+{
+    desc->status &= ~desc_flag;
+}
+
+/*!
+    \brief      when receiving completed, set RS bit in ENET_DMA_STAT register will set 
+    \param[in]  desc: the descriptor pointer which users want to configure
+    \param[out] none
+    \retval     none
+*/
+void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc)
+{
+    desc->control_buffer_size &= ~ENET_RDES1_DINTC;
+}
+
+/*!
+    \brief      when receiving completed, set RS bit in ENET_DMA_STAT register will not set 
+    \param[in]  desc: the descriptor pointer which users want to configure
+    \param[out] none
+    \retval     none
+*/
+void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc)
+{
+    desc->control_buffer_size |= ENET_RDES1_DINTC;
+}
+
+/*!
+    \brief      drop current receive frame
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_rxframe_drop(void)
+{
+    /* enable reception, descriptor is owned by DMA */
+    dma_current_rxdesc->status = ENET_RDES0_DAV;  
+    
+    /* chained mode */
+    if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){     
+        if(NULL != dma_current_ptp_rxdesc){
+            dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr);
+            /* if it is the last ptp descriptor */
+            if(0U != dma_current_ptp_rxdesc->status){
+                /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
+                dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status);
+            }else{
+                /* ponter to the next ptp descriptor */
+                dma_current_ptp_rxdesc++;
+            }
+        }else{
+            dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr);
+        }
+            
+    }else{
+        /* ring mode */    
+        if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){
+            /* if is the last descriptor in table, the next descriptor is the table header */
+            dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR);
+            if(NULL != dma_current_ptp_rxdesc){
+                dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status);
+            }
+        }else{
+            /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
+            dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
+            if(NULL != dma_current_ptp_rxdesc){
+                dma_current_ptp_rxdesc++;
+            }
+        }
+    }
+}
+
+/*!
+    \brief      enable DMA feature
+    \param[in]  feature: the feature of DMA mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function
+      \arg        ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function
+    \param[out] none
+    \retval     none
+*/
+void enet_dma_feature_enable(uint32_t feature)
+{
+    ENET_DMA_CTL |= feature;   
+}
+
+/*!
+    \brief      disable DMA feature
+    \param[in]  feature: the feature of DMA mode,
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function
+      \arg        ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function
+    \param[out] none
+    \retval     none
+*/
+void enet_dma_feature_disable(uint32_t feature)
+{
+    ENET_DMA_CTL &= ~feature;
+}
+
+/*!
+    \brief      initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function
+    \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: DMA Tx descriptors
+      \arg        ENET_DMA_RX: DMA Rx descriptors
+    \param[in]  desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab)
+{
+    uint32_t num = 0U, count = 0U, maxsize = 0U;
+    uint32_t desc_status = 0U, desc_bufsize = 0U;
+    enet_descriptors_struct *desc, *desc_tab;
+    uint8_t *buf;
+  
+    /* if want to initialize DMA Tx descriptors */
+    if (ENET_DMA_TX == direction){
+        /* save a copy of the DMA Tx descriptors */
+        desc_tab = txdesc_tab;
+        buf = &tx_buff[0][0];
+        count = ENET_TXBUF_NUM;
+        maxsize = ENET_TXBUF_SIZE;        
+      
+        /* select chain mode, and enable transmit timestamp function */
+        desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN;
+      
+        /* configure DMA Tx descriptor table address register */
+        ENET_DMA_TDTADDR = (uint32_t)desc_tab;
+        dma_current_txdesc = desc_tab;
+        dma_current_ptp_txdesc = desc_ptptab;
+    }else{
+        /* if want to initialize DMA Rx descriptors */
+        /* save a copy of the DMA Rx descriptors */
+        desc_tab = rxdesc_tab;
+        buf = &rx_buff[0][0];
+        count = ENET_RXBUF_NUM;
+        maxsize = ENET_RXBUF_SIZE;       
+  
+        /* enable receiving */
+        desc_status = ENET_RDES0_DAV;
+        /* select receive chained mode and set buffer1 size */
+        desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE;
+      
+        /* configure DMA Rx descriptor table address register */
+        ENET_DMA_RDTADDR = (uint32_t)desc_tab;
+        dma_current_rxdesc = desc_tab;
+        dma_current_ptp_rxdesc = desc_ptptab;      
+    }
+      
+    /* configure each descriptor */   
+    for(num = 0U; num < count; num++){
+        /* get the pointer to the next descriptor of the descriptor table */
+        desc = desc_tab + num;
+
+        /* configure descriptors */
+        desc->status = desc_status;         
+        desc->control_buffer_size = desc_bufsize;
+        desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
+    
+        /* if is not the last descriptor */
+        if(num < (count - 1U)){
+            /* configure the next descriptor address */
+            desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U);
+        }else{
+            /* when it is the last descriptor, the next descriptor address 
+            equals to first descriptor address in descriptor table */ 
+            desc->buffer2_next_desc_addr = (uint32_t)desc_tab;  
+        }
+        /* set desc_ptptab equal to desc_tab */
+        (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr;
+        (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr;
+    } 
+    /* when it is the last ptp descriptor, preserve the first descriptor 
+    address of desc_ptptab in ptp descriptor status */
+    (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab;
+}
+
+/*!
+    \brief      initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function
+    \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_DMA_TX: DMA Tx descriptors
+      \arg        ENET_DMA_RX: DMA Rx descriptors
+    \param[in]  desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab)
+{
+    uint32_t num = 0U, count = 0U, maxsize = 0U;
+    uint32_t desc_status = 0U, desc_bufsize = 0U;
+    enet_descriptors_struct *desc, *desc_tab;
+    uint8_t *buf;
+
+    /* configure descriptor skip length */
+    ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL;
+    ENET_DMA_BCTL |= DMA_BCTL_DPSL(0);
+    
+    /* if want to initialize DMA Tx descriptors */
+    if (ENET_DMA_TX == direction){
+        /* save a copy of the DMA Tx descriptors */
+        desc_tab = txdesc_tab;
+        buf = &tx_buff[0][0];
+        count = ENET_TXBUF_NUM;
+        maxsize = ENET_TXBUF_SIZE;        
+      
+        /* select ring mode, and enable transmit timestamp function */
+        desc_status = ENET_TDES0_TTSEN;
+      
+        /* configure DMA Tx descriptor table address register */
+        ENET_DMA_TDTADDR = (uint32_t)desc_tab;
+        dma_current_txdesc = desc_tab;
+        dma_current_ptp_txdesc = desc_ptptab;
+    }else{
+        /* if want to initialize DMA Rx descriptors */
+        /* save a copy of the DMA Rx descriptors */
+        desc_tab = rxdesc_tab;
+        buf = &rx_buff[0][0];
+        count = ENET_RXBUF_NUM;
+        maxsize = ENET_RXBUF_SIZE;       
+  
+        /* enable receiving */
+        desc_status = ENET_RDES0_DAV;
+        /* select receive ring mode and set buffer1 size */
+        desc_bufsize = (uint32_t)ENET_RXBUF_SIZE;
+      
+        /* configure DMA Rx descriptor table address register */
+        ENET_DMA_RDTADDR = (uint32_t)desc_tab;
+        dma_current_rxdesc = desc_tab;
+        dma_current_ptp_rxdesc = desc_ptptab;      
+    }
+      
+    /* configure each descriptor */   
+    for(num = 0U; num < count; num++){
+        /* get the pointer to the next descriptor of the descriptor table */
+        desc = desc_tab + num;
+
+        /* configure descriptors */
+        desc->status = desc_status;         
+        desc->control_buffer_size = desc_bufsize;
+        desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
+    
+        /* when it is the last descriptor */
+        if(num == (count - 1U)){
+            if (ENET_DMA_TX == direction){
+                /* configure transmit end of ring mode */  
+                desc->status |= ENET_TDES0_TERM;
+            }else{
+                /* configure receive end of ring mode */
+                desc->control_buffer_size |= ENET_RDES1_RERM;
+            }
+        }
+        /* set desc_ptptab equal to desc_tab */
+        (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr;
+        (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr;
+    } 
+    /* when it is the last ptp descriptor, preserve the first descriptor 
+    address of desc_ptptab in ptp descriptor status */
+    (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab;
+}
+
+/*!
+    \brief      receive a packet data with timestamp values to application buffer, when the DMA is in normal mode   
+    \param[in]  bufsize: the size of buffer which is the parameter in function
+    \param[out] timestamp: pointer to the table which stores the timestamp high and low
+    \param[out] buffer: pointer to the application buffer
+                note -- if the input is NULL, user should copy data in application by himself
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[])
+{
+    uint32_t offset = 0U, size = 0U;
+    
+    /* the descriptor is busy due to own by the DMA */
+    if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){
+        return ERROR;
+    }
+    
+    /* if buffer pointer is null, indicates that users has copied data in application */
+    if(NULL != buffer){
+        /* if no error occurs, and the frame uses only one descriptor */
+        if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) &&
+           ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) &&
+           ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){
+            
+            /* get the frame length except CRC */
+            size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U;
+            
+            /* to avoid situation that the frame size exceeds the buffer length */
+            if(size > bufsize){
+                return ERROR;
+            }
+
+            /* copy data from Rx buffer to application buffer */
+            for(offset = 0U; offset < size; offset++){
+                (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset));
+            }
+            
+        }else{
+            return ERROR;
+        }
+    }
+    /* copy timestamp value from Rx descriptor to application array */
+    timestamp[0] = dma_current_rxdesc->buffer1_addr;
+    timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr;
+
+    dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ;
+    dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr;
+    
+    /* enable reception, descriptor is owned by DMA */
+    dma_current_rxdesc->status = ENET_RDES0_DAV;
+    
+    /* check Rx buffer unavailable flag status */
+    if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){
+        /* clear RBU flag */
+        ENET_DMA_STAT = ENET_DMA_STAT_RBU;
+        /* resume DMA reception by writing to the RPEN register*/
+        ENET_DMA_RPEN = 0U;
+    }
+    
+
+    /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */      
+    /* chained mode */
+    if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){
+        dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr);
+        /* if it is the last ptp descriptor */
+        if(0U != dma_current_ptp_rxdesc->status){
+            /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
+            dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status);
+        }else{
+            /* ponter to the next ptp descriptor */
+            dma_current_ptp_rxdesc++;
+        }
+    }else{
+        /* ring mode */   
+        if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){
+            /* if is the last descriptor in table, the next descriptor is the table header */
+            dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR);
+            /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table,
+            use the same table with RxDMA descriptor */
+            dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status);          
+        }else{
+            /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
+            dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));      
+            dma_current_ptp_rxdesc ++;
+        }
+    }
+
+    return SUCCESS;
+}
+
+/*!
+    \brief      send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode 
+    \param[in]  buffer: pointer on the application buffer
+                note -- if the input is NULL, user should copy data in application by himself
+    \param[in]  length: the length of frame data to be transmitted
+    \param[out] timestamp: pointer to the table which stores the timestamp high and low
+                note -- if the input is NULL, timestamp is ignored
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[])
+{
+    uint32_t offset = 0U, timeout = 0U;
+    uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; 
+    
+    /* the descriptor is busy due to own by the DMA */
+    if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){
+        return ERROR;
+    }
+
+    /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */
+    if(length > ENET_MAX_FRAME_SIZE){
+        return ERROR;
+    }
+    
+    /* if buffer pointer is null, indicates that users has handled data in application */
+    if(NULL != buffer){
+        /* copy frame data from application buffer to Tx buffer */
+        for(offset = 0U; offset < length; offset++){
+            (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset));
+        }
+    }
+    /* set the frame length */
+    dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF);
+    /* set the segment of frame, frame is transmitted in one descriptor */
+    dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG;
+    /* enable the DMA transmission */
+    dma_current_txdesc->status |= ENET_TDES0_DAV;
+    
+    /* check Tx buffer unavailable flag status */
+    dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); 
+    dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU);
+    
+    if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){
+        /* clear TBU and TU flag */
+        ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag);
+        /* resume DMA transmission by writing to the TPEN register*/
+        ENET_DMA_TPEN = 0U;
+    }
+    
+    /* if timestamp pointer is null, indicates that users don't care timestamp in application */
+    if(NULL != timestamp){
+        /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */
+        do{   
+            tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS);
+            timeout++;
+        }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO));
+       
+        /* return ERROR due to timeout */
+        if(ENET_DELAY_TO == timeout){
+            return ERROR;
+        } 
+    
+        /* clear the ENET_TDES0_TTMSS flag */
+        dma_current_txdesc->status &= ~ENET_TDES0_TTMSS;
+        /* get the timestamp value of the transmit frame */
+        timestamp[0] = dma_current_txdesc->buffer1_addr;
+        timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr;
+    }
+    dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ;
+    dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr;
+
+    /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */   
+    /* chained mode */
+    if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){   
+        dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr);
+        /* if it is the last ptp descriptor */
+        if(0U != dma_current_ptp_txdesc->status){ 
+            /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
+            dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status);
+        }else{
+            /* ponter to the next ptp descriptor */
+            dma_current_ptp_txdesc++;
+        }
+    }else{
+        /* ring mode */   
+        if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){
+            /* if is the last descriptor in table, the next descriptor is the table header */
+            dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); 
+            /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table,
+            use the same table with TxDMA descriptor */
+            dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status);
+        }else{
+            /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
+            dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));      
+            dma_current_ptp_txdesc ++;      
+        }
+    }
+    return SUCCESS;
+}
+
+/*!
+    \brief      wakeup frame filter register pointer reset 
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_wum_filter_register_pointer_reset(void)
+{
+    ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR;
+}
+
+/*!
+    \brief      set the remote wakeup frame registers 
+    \param[in]  pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total)
+    \param[out] none
+    \retval     none
+*/
+void enet_wum_filter_config(uint32_t pdata[])
+{
+    uint32_t num = 0U;
+  
+    /* configure ENET_MAC_RWFF register */
+    for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){
+        ENET_MAC_RWFF = pdata[num];
+    }
+}
+
+/*!
+    \brief      enable wakeup management features  
+    \param[in]  feature: one or more parameters can be selected which are shown as below
+      \arg        ENET_WUM_POWER_DOWN: power down mode
+      \arg        ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception
+      \arg        ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception
+      \arg        ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame
+    \param[out] none
+    \retval     none
+*/
+void enet_wum_feature_enable(uint32_t feature)
+{
+    ENET_MAC_WUM |= feature;
+}
+
+/*!
+    \brief      disable wakeup management features  
+    \param[in]  feature: one or more parameters can be selected which are shown as below
+      \arg        ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception
+      \arg        ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception
+      \arg        ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame
+    \param[out] none
+    \retval     none
+*/
+void enet_wum_feature_disable(uint32_t feature)
+{
+    ENET_MAC_WUM &= (~feature);
+}
+
+/*!
+    \brief      reset the MAC statistics counters  
+    \param[in]  none 
+    \param[out] none
+    \retval     none
+*/
+void enet_msc_counters_reset(void)
+{
+    /* reset all counters */
+    ENET_MSC_CTL |= ENET_MSC_CTL_CTR;
+}
+
+/*!
+    \brief      enable the MAC statistics counter features
+    \param[in]  feature: one or more parameters can be selected which are shown as below
+      \arg        ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover
+      \arg        ENET_MSC_RESET_ON_READ: reset on read
+      \arg        ENET_MSC_COUNTERS_FREEZE: MSC counter freeze
+    \param[out] none
+    \retval     none
+*/
+void enet_msc_feature_enable(uint32_t feature)
+{
+    ENET_MSC_CTL |= feature;
+}
+
+/*!
+    \brief      disable the MAC statistics counter features
+    \param[in]  feature: one or more parameters can be selected which are shown as below 
+      \arg        ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover
+      \arg        ENET_MSC_RESET_ON_READ: reset on read
+      \arg        ENET_MSC_COUNTERS_FREEZE: MSC counter freeze
+    \param[out] none
+    \retval     none
+*/
+void enet_msc_feature_disable(uint32_t feature)
+{
+     ENET_MSC_CTL &= (~feature);
+}
+
+/*!
+    \brief      get MAC statistics counter  
+    \param[in]  counter: MSC counters which is selected, refer to enet_msc_counter_enum,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter
+      \arg        ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter
+      \arg        ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter
+      \arg        ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter
+      \arg        ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter
+      \arg        ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter
+    \param[out] none
+    \retval     the MSC counter value
+*/
+uint32_t enet_msc_counters_get(enet_msc_counter_enum counter)
+{
+    uint32_t reval;
+    
+    reval = REG32((ENET + (uint32_t)counter));
+    
+    return reval;
+}
+
+/*!
+    \brief      change subsecond to nanosecond  
+    \param[in]  subsecond: subsecond value
+    \param[out] none
+    \retval     the nanosecond value
+*/
+uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond)
+{
+    uint64_t val = subsecond * 1000000000Ull;
+    val >>= 31;
+    return (uint32_t)val;
+}
+
+/*!
+    \brief      change nanosecond to subsecond  
+    \param[in]  nanosecond: nanosecond value
+    \param[out] none
+    \retval     the subsecond value
+*/
+uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond)
+{
+    uint64_t val = nanosecond * 0x80000000Ull;
+    val /= 1000000000U;
+    return (uint32_t)val;
+}
+
+/*!
+    \brief      enable the PTP features
+    \param[in]  feature: the feature of ENET PTP mode
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames
+      \arg        ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_feature_enable(uint32_t feature)
+{
+    ENET_PTP_TSCTL |= feature;
+}
+
+/*!
+    \brief      disable the PTP features
+    \param[in]  feature: the feature of ENET PTP mode
+                one or more parameters can be selected which are shown as below
+      \arg        ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames
+      \arg        ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_feature_disable(uint32_t feature)
+{
+    ENET_PTP_TSCTL &= ~feature;
+}
+
+/*!
+    \brief      configure the PTP timestamp function
+    \param[in]  func: only one parameter can be selected which is shown as below
+      \arg        ENET_PTP_ADDEND_UPDATE: addend register update
+      \arg        ENET_PTP_SYSTIME_UPDATE: timestamp update
+      \arg        ENET_PTP_SYSTIME_INIT: timestamp initialize
+      \arg        ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating
+      \arg        ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+
+ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func)
+{
+    uint32_t temp_config = 0U, temp_state = 0U;
+    uint32_t timeout = 0U;
+    ErrStatus enet_state = SUCCESS;
+
+    switch(func){
+    case ENET_PTP_ADDEND_UPDATE: 
+        /* this bit must be read as zero before application set it */
+        do{
+            temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; 
+            timeout++;
+        }while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
+        /* return ERROR due to timeout */
+        if(ENET_DELAY_TO == timeout){
+            enet_state = ERROR;
+        }else{
+            ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU;
+        }    
+        break;
+    case ENET_PTP_SYSTIME_UPDATE:
+        /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */
+        do{
+            temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); 
+            timeout++;
+        }while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
+        /* return ERROR due to timeout */
+        if(ENET_DELAY_TO == timeout){
+            enet_state = ERROR;
+        }else{
+            ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU;
+        }    
+        break; 
+    case ENET_PTP_SYSTIME_INIT:
+        /* this bit must be read as zero before application set it */
+        do{
+            temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; 
+            timeout++;
+        }while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
+        /* return ERROR due to timeout */
+        if(ENET_DELAY_TO == timeout){
+            enet_state = ERROR;
+        }else{
+            ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI;
+        }    
+        break;        
+    default:
+        temp_config = (uint32_t)func & (~BIT(31)); 
+        if(RESET != ((uint32_t)func & BIT(31))){
+            ENET_PTP_TSCTL |= temp_config;    
+        }else{
+            ENET_PTP_TSCTL &= ~temp_config;     
+        }
+        break; 
+    }
+
+    return enet_state;
+}
+
+/*!
+    \brief      configure system time subsecond increment value
+    \param[in]  subsecond: the value will be added to the subsecond value of system time, 
+                this value must be between 0 and 0xFF
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_subsecond_increment_config(uint32_t subsecond)
+{
+    ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond);
+}
+
+/*!
+    \brief      adjusting the clock frequency only in fine update mode
+    \param[in]  add: the value will be added to the accumulator register to achieve time synchronization
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_timestamp_addend_config(uint32_t add)
+{
+    ENET_PTP_TSADDEND = add;
+}
+
+/*!
+    \brief      initialize or add/subtract to second of the system time
+    \param[in]  sign: timestamp update positive or negative sign,
+                only one parameter can be selected which is shown as below
+      \arg        ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time
+      \arg        ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time
+    \param[in]  second: initializing or adding/subtracting to second of the system time
+    \param[in]  subsecond: the current subsecond of the system time 
+                with 0.46 ns accuracy if required accuracy is 20 ns
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond)
+{
+    ENET_PTP_TSUH = second;
+    ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); 
+}
+
+/*!
+    \brief      configure the expected target time
+    \param[in]  second: the expected target second time
+    \param[in]  nanosecond: the expected target nanosecond time (signed)
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond)
+{
+    ENET_PTP_ETH = second;
+    ENET_PTP_ETL = nanosecond;
+}
+
+/*!
+    \brief      get the current system time
+    \param[in]  none
+    \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains 
+                parameters of PTP system time
+                members of the structure and the member values are shown as below:
+                  second: 0x0 - 0xFFFF FFFF
+                  nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31
+                  sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE
+    \retval     none
+*/
+void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct)
+{
+    uint32_t temp_sec = 0U, temp_subs = 0U;
+
+    /* get the value of sysytem time registers */
+    temp_sec = (uint32_t)ENET_PTP_TSH;   
+    temp_subs = (uint32_t)ENET_PTP_TSL;
+   
+    /* get sysytem time and construct the enet_ptp_systime_struct structure */
+    systime_struct->second = temp_sec;
+    systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs);
+    systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond);
+    systime_struct->sign = GET_PTP_TSL_STS(temp_subs);
+}
+
+/*!
+    \brief      configure and start PTP timestamp counter
+    \param[in]  updatemethod: method for updating
+      \arg        ENET_PTP_FINEMODE: fine correction method
+      \arg        ENET_PTP_COARSEMODE: coarse correction method
+    \param[in]  init_sec: second value for initializing system time
+    \param[in]  init_subsec: subsecond value for initializing system time
+    \param[in]  carry_cfg: the value to be added to the accumulator register (in fine method is used)
+    \param[in]  accuracy_cfg: the value to be added to the subsecond value of system time
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg)
+{
+    /* mask the timestamp trigger interrupt */
+    enet_interrupt_disable(ENET_MAC_INT_TMSTIM);
+
+    /* enable timestamp */
+    enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP);
+
+    /* configure system time subsecond increment based on the PTP clock frequency */
+    enet_ptp_subsecond_increment_config(accuracy_cfg);
+
+    if(ENET_PTP_FINEMODE == updatemethod){    
+        /* fine correction method: configure the timestamp addend, then update */
+        enet_ptp_timestamp_addend_config(carry_cfg);
+        enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE);
+        /* wait until update is completed */
+        while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){
+        }
+    }
+
+    /* choose the fine correction method */
+    enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod);
+
+    /* initialize the system time */
+    enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec);
+    enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT);
+}
+
+/*!
+    \brief      adjust frequency in fine method by configure addend register
+    \param[in]  carry_cfg: the value to be added to the accumulator register
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg)
+{
+    /* re-configure the timestamp addend, then update */
+    enet_ptp_timestamp_addend_config((uint32_t)carry_cfg);
+    enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE);
+}
+
+/*!
+    \brief      update system time in coarse method
+    \param[in]  systime_struct: pointer to a enet_ptp_systime_struct structure which contains 
+                parameters of PTP system time
+                members of the structure and the member values are shown as below:
+                  second: 0x0 - 0xFFFF FFFF
+                  nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31
+                  sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct)
+{
+    uint32_t subsecond_val;
+    uint32_t carry_cfg;
+
+    subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond);
+    
+    /* save the carry_cfg value */
+    carry_cfg = ENET_PTP_TSADDEND_TMSA;
+
+    /* update the system time */
+    enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val);
+    enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE);
+
+    /* wait until the update is completed */
+    while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){
+    }
+      
+    /* write back the carry_cfg value, then update */
+    enet_ptp_timestamp_addend_config(carry_cfg);
+    enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE);
+}
+
+/*!
+    \brief      set system time in fine method
+    \param[in]  systime_struct: pointer to a enet_ptp_systime_struct structure which contains 
+                parameters of PTP system time
+                members of the structure and the member values are shown as below:
+                  second: 0x0 - 0xFFFF FFFF
+                  nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31
+                  sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE
+    \param[out] none
+    \retval     none
+*/
+void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct)
+{
+    uint32_t subsecond_val;
+
+    subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond);
+
+    /* initialize the system time */
+    enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val);
+    enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT);
+    
+    /* wait until the system time initialzation finished */
+    while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){
+    }
+}
+
+/*!
+    \brief      get the ptp flag status
+    \param[in]  flag: ptp flag status to be checked  
+      \arg        ENET_PTP_ADDEND_UPDATE: addend register update
+      \arg        ENET_PTP_SYSTIME_UPDATE: timestamp update
+      \arg        ENET_PTP_SYSTIME_INIT: timestamp initialize
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus enet_ptp_flag_get(uint32_t flag)
+{
+    FlagStatus bitstatus = RESET;
+
+    if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){
+        bitstatus = SET;
+    }
+    
+    return bitstatus;
+}
+
+/*!
+    \brief      reset the ENET initpara struct, call it before using enet_initpara_config()
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_initpara_reset(void)
+{
+    enet_initpara.option_enable = 0U;
+    enet_initpara.forward_frame = 0U;
+    enet_initpara.dmabus_mode = 0U;
+    enet_initpara.dma_maxburst = 0U;
+    enet_initpara.dma_arbitration = 0U;
+    enet_initpara.store_forward_mode = 0U;
+    enet_initpara.dma_function = 0U; 
+    enet_initpara.vlan_config = 0U;
+    enet_initpara.flow_control = 0U;
+    enet_initpara.hashtable_high = 0U;
+    enet_initpara.hashtable_low = 0U;
+    enet_initpara.framesfilter_mode = 0U;
+    enet_initpara.halfduplex_param = 0U;
+    enet_initpara.timer_config = 0U;
+    enet_initpara.interframegap = 0U;
+} 
+
+/*!
+    \brief      initialize ENET peripheral with generally concerned parameters, call it by enet_init() 
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void enet_default_init(void)
+{
+    uint32_t reg_value = 0U;
+
+    /* MAC */
+    /* configure ENET_MAC_CFG register */
+    reg_value = ENET_MAC_CFG;
+    reg_value &= MAC_CFG_MASK;
+    reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \
+                | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \
+                | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \
+                | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \
+                | ENET_DEFERRALCHECK_DISABLE \
+                | ENET_AUTO_PADCRC_DROP_DISABLE \
+                | ENET_CHECKSUMOFFLOAD_DISABLE;
+    ENET_MAC_CFG = reg_value;
+  
+    /* configure ENET_MAC_FRMF register */
+    ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \
+                   |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \
+                   |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \
+                   |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE;
+
+    /* configure ENET_MAC_HLH, ENET_MAC_HLL register */
+    ENET_MAC_HLH = 0x0U;
+    
+    ENET_MAC_HLL = 0x0U;
+
+    /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */
+    reg_value = ENET_MAC_FCTL;
+    reg_value &= MAC_FCTL_MASK;
+    reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \
+                |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \
+                |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE;
+    ENET_MAC_FCTL = reg_value;
+
+    /* configure ENET_MAC_VLT register */
+    ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0);
+
+    /* DMA */
+    /* configure ENET_DMA_CTL register */
+    reg_value = ENET_DMA_CTL;
+    reg_value &= DMA_CTL_MASK;
+    reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \
+                |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \
+                |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \
+                |ENET_SECONDFRAME_OPT_DISABLE; 
+    ENET_DMA_CTL = reg_value;
+
+    /* configure ENET_DMA_BCTL register */
+    reg_value = ENET_DMA_BCTL;
+    reg_value &= DMA_BCTL_MASK;
+    reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \
+               |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \
+               |ENET_FIXED_BURST_ENABLE;
+    ENET_DMA_BCTL = reg_value;
+}
+
+#ifndef USE_DELAY
+/*!
+    \brief      insert a delay time
+    \param[in]  ncount: specifies the delay time length
+    \param[out] none
+    \param[out] none
+*/
+static void enet_delay(uint32_t ncount)
+{
+    __IO uint32_t delay_time = 0U; 
+    
+    for(delay_time = ncount; delay_time != 0U; delay_time--){
+    }
+}
+#endif /* USE_DELAY */
+
+#endif /* GD32F10X_CL */

+ 645 - 0
Library/Source/gd32f10x_exmc.c

@@ -0,0 +1,645 @@
+/*!
+    \file    gd32f10x_exmc.c
+    \brief   EXMC driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_exmc.h"
+
+/* EXMC bank0 register reset value */
+#define BANK0_SNCTL0_REGION_RESET         ((uint32_t)0x000030DBU)
+#define BANK0_SNCTL1_2_3_REGION_RESET     ((uint32_t)0x000030D2U)
+#define BANK0_SNTCFG_RESET                ((uint32_t)0x0FFFFFFFU)
+#define BANK0_SNWTCFG_RESET               ((uint32_t)0x0FFFFFFFU)
+
+/* EXMC bank1/2 register reset mask*/
+#define BANK1_2_NPCTL_RESET               ((uint32_t)0x00000018U)
+#define BANK1_2_NPINTEN_RESET             ((uint32_t)0x00000040U)
+#define BANK1_2_NPCTCFG_RESET             ((uint32_t)0xFCFCFCFCU)
+#define BANK1_2_NPATCFG_RESET             ((uint32_t)0xFCFCFCFCU)
+
+/* EXMC bank3 register reset mask*/
+#define BANK3_NPCTL_RESET                 ((uint32_t)0x00000018U)
+#define BANK3_NPINTEN_RESET               ((uint32_t)0x00000040U)
+#define BANK3_NPCTCFG_RESET               ((uint32_t)0xFCFCFCFCU)
+#define BANK3_NPATCFG_RESET               ((uint32_t)0xFCFCFCFCU)
+#define BANK3_PIOTCFG3_RESET              ((uint32_t)0xFCFCFCFCU)
+
+/* EXMC register bit offset */
+#define SNCTL_NRMUX_OFFSET                ((uint32_t)1U)
+#define SNCTL_SBRSTEN_OFFSET              ((uint32_t)8U)
+#define SNCTL_WRAPEN_OFFSET               ((uint32_t)10U)
+#define SNCTL_WREN_OFFSET                 ((uint32_t)12U)
+#define SNCTL_NRWTEN_OFFSET               ((uint32_t)13U)
+#define SNCTL_EXMODEN_OFFSET              ((uint32_t)14U)
+#define SNCTL_ASYNCWAIT_OFFSET            ((uint32_t)15U)
+
+#define SNTCFG_AHLD_OFFSET                ((uint32_t)4U)
+#define SNTCFG_DSET_OFFSET                ((uint32_t)8U)
+#define SNTCFG_BUSLAT_OFFSET              ((uint32_t)16U)
+
+#define SNWTCFG_WAHLD_OFFSET              ((uint32_t)4U)
+#define SNWTCFG_WDSET_OFFSET              ((uint32_t)8U)
+#define SNWTCFG_WBUSLAT_OFFSET            ((uint32_t)16U)
+
+#define NPCTL_NDWTEN_OFFSET               ((uint32_t)1U)
+#define NPCTL_ECCEN_OFFSET                ((uint32_t)6U)
+
+#define NPCTCFG_COMWAIT_OFFSET            ((uint32_t)8U)
+#define NPCTCFG_COMHLD_OFFSET             ((uint32_t)16U)
+#define NPCTCFG_COMHIZ_OFFSET             ((uint32_t)24U)
+
+#define NPATCFG_ATTWAIT_OFFSET            ((uint32_t)8U)
+#define NPATCFG_ATTHLD_OFFSET             ((uint32_t)16U)
+#define NPATCFG_ATTHIZ_OFFSET             ((uint32_t)24U)
+
+#define PIOTCFG_IOWAIT_OFFSET             ((uint32_t)8U)
+#define PIOTCFG_IOHLD_OFFSET              ((uint32_t)16U)
+#define PIOTCFG_IOHIZ_OFFSET              ((uint32_t)24U)
+
+#define INTEN_INTS_OFFSET                 ((uint32_t)3U)
+
+/*!
+    \brief      deinitialize EXMC NOR/SRAM region
+    \param[in]  norsram_region: select the region of bank0
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_deinit(uint32_t norsram_region)
+{
+    /* reset the registers */
+    if(EXMC_BANK0_NORSRAM_REGION0 == norsram_region){
+        EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET;
+    }else{
+        EXMC_SNCTL(norsram_region) = BANK0_SNCTL1_2_3_REGION_RESET;
+    }
+
+    EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET;
+    EXMC_SNWTCFG(norsram_region) = BANK0_SNWTCFG_RESET;
+}
+
+/*!
+    \brief      initialize EXMC NOR/SRAM region
+    \param[in]  exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
+                  norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3
+                  write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE
+                  extended_mode: ENABLE or DISABLE 
+                  asyn_wait: ENABLE or DISABLE
+                  nwait_signal: ENABLE or DISABLE
+                  memory_write: ENABLE or DISABLE
+                  nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING
+                  wrap_burst_mode: ENABLE or DISABLE
+                  nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
+                  burst_mode: ENABLE or DISABLE
+                  databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
+                  memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
+                  address_data_mux: ENABLE or DISABLE
+                  read_write_timing: struct exmc_norsram_timing_parameter_struct set the time
+                  write_timing: struct exmc_norsram_timing_parameter_struct set the time
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
+{
+    uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U;
+
+    /* get the register value */
+    snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
+
+    /* clear relative bits */
+    snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | 
+                          EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | 
+                          EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | 
+                          EXMC_SNCTL_NRMUX ));
+
+    snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
+                        exmc_norsram_init_struct->memory_type |
+                        exmc_norsram_init_struct->databus_width |
+                       (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
+                        exmc_norsram_init_struct->nwait_polarity |
+                       (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
+                        exmc_norsram_init_struct->nwait_config |
+                       (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
+                       (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
+                       (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
+                       (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
+                        exmc_norsram_init_struct->write_mode;
+
+    sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
+                       (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
+                       (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
+                       (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
+                       exmc_norsram_init_struct->read_write_timing->syn_clk_division |
+                       exmc_norsram_init_struct->read_write_timing->syn_data_latency |
+                       exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
+
+    /* nor flash access enable */
+    if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
+        snctl |= (uint32_t)EXMC_SNCTL_NREN;
+    }
+
+    /* extended mode configure */
+    if(ENABLE == exmc_norsram_init_struct->extended_mode){
+        snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) |
+                             (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)|
+                             (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) |
+                              exmc_norsram_init_struct->write_timing->asyn_access_mode);
+    }else{
+        snwtcfg = BANK0_SNWTCFG_RESET;
+    }
+
+    /* configure the registers */
+    EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
+    EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
+    EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg;
+}
+
+/*!
+    \brief      initialize the struct exmc_norsram_parameter_struct
+    \param[in]  none
+    \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer
+    \retval     none
+*/
+void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
+{
+    /* configure the structure with default value */
+    exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0;
+    exmc_norsram_init_struct->address_data_mux = ENABLE;
+    exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM;
+    exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B;
+    exmc_norsram_init_struct->burst_mode = DISABLE;
+    exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
+    exmc_norsram_init_struct->wrap_burst_mode = DISABLE;
+    exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
+    exmc_norsram_init_struct->memory_write = ENABLE;
+    exmc_norsram_init_struct->nwait_signal = ENABLE;
+    exmc_norsram_init_struct->extended_mode = DISABLE;
+    exmc_norsram_init_struct->asyn_wait = DISABLE;
+    exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE;
+
+    /* read/write timing configure */
+    exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
+    exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
+    exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
+    exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
+    exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
+    exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK;
+    exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
+
+    /* write timing configure, when extended mode is used */
+    exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU;
+    exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU;
+    exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU;
+    exmc_norsram_init_struct->write_timing->bus_latency = 0xFU;
+    exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
+}
+
+/*!
+    \brief      enable EXMC NOR/PSRAM bank region
+    \param[in]  norsram_region: specifie the region of NOR/PSRAM bank
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_enable(uint32_t norsram_region)
+{
+    EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
+}
+
+/*!
+    \brief      disable EXMC NOR/PSRAM bank region
+    \param[in]  norsram_region: specifie the region of NOR/PSRAM Bank
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_disable(uint32_t norsram_region)
+{
+    EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
+}
+
+/*!
+    \brief      deinitialize EXMC NAND bank
+    \param[in]  nand_bank: select the bank of NAND
+      \arg        EXMC_BANKx_NAND(x=1..2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_deinit(uint32_t nand_bank)
+{
+    /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */
+    EXMC_NPCTL(nand_bank) = BANK1_2_NPCTL_RESET;
+    EXMC_NPINTEN(nand_bank) = BANK1_2_NPINTEN_RESET;
+    EXMC_NPCTCFG(nand_bank) = BANK1_2_NPCTCFG_RESET;
+    EXMC_NPATCFG(nand_bank) = BANK1_2_NPATCFG_RESET;
+}
+
+/*!
+    \brief      initialize EXMC NAND bank
+    \param[in]  exmc_nand_parameter_struct: configure the EXMC NAND parameter
+                  nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND
+                  ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096
+                  atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
+                  ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
+                  ecc_logic: ENABLE or DISABLE
+                  databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B
+                  wait_feature: ENABLE or DISABLE
+                  common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
+                  attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
+{
+    uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U;
+    
+    npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)|
+                       EXMC_NPCTL_NDTP |
+                       exmc_nand_init_struct->databus_width |
+                      (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)|
+                       exmc_nand_init_struct->ecc_size |
+                       exmc_nand_init_struct->ctr_latency |
+                       exmc_nand_init_struct->atr_latency;
+
+    npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) |
+                        (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
+                        ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
+                        (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
+
+    npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
+                        (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
+                        ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) |
+                        (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
+
+    /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */
+    EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl;
+    EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg;
+    EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg;
+}
+
+/*!
+    \brief      initialize the struct exmc_nand_init_struct
+    \param[in]  none
+    \param[out] the initialized struct exmc_nand_init_struct pointer
+    \retval     none
+*/
+void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
+{
+    /* configure the structure with default value */
+    exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND;
+    exmc_nand_init_struct->wait_feature = DISABLE;
+    exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B;
+    exmc_nand_init_struct->ecc_logic = DISABLE;
+    exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES;
+    exmc_nand_init_struct->ctr_latency = 0x0U;
+    exmc_nand_init_struct->atr_latency = 0x0U;
+    exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU;
+    exmc_nand_init_struct->common_space_timing->waittime = 0xFCU;
+    exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU;
+    exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU;
+    exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU;
+    exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU;
+    exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU;
+    exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
+}
+
+/*!
+    \brief      enable NAND bank
+    \param[in]  nand_bank: specifie the NAND bank
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_enable(uint32_t nand_bank)
+{
+    EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_NDBKEN;
+}
+
+/*!
+    \brief      disable NAND bank
+    \param[in]  nand_bank: specifie the NAND bank
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_disable(uint32_t nand_bank)
+{
+    EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_NDBKEN;
+}
+
+/*!
+    \brief      enable or disable the EXMC NAND ECC function
+    \param[in]  nand_bank: specifie the NAND bank
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[in]  newvalue: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue)
+{
+    if (ENABLE == newvalue){
+        /* enable the selected NAND bank ECC function */
+        EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_ECCEN;
+    }else{
+        /* disable the selected NAND bank ECC function */
+        EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_ECCEN;
+    }
+}
+
+/*!
+    \brief      get the EXMC ECC value
+    \param[in]  nand_bank: specifie the NAND bank
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     the error correction code(ECC) value
+*/
+uint32_t exmc_ecc_get(uint32_t nand_bank)
+{
+    return (EXMC_NECC(nand_bank));
+}
+
+/*!
+    \brief      deinitialize EXMC PC card bank
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void exmc_pccard_deinit(void)
+{
+    /* EXMC_BANK3_PCCARD */
+    EXMC_NPCTL3 = BANK3_NPCTL_RESET;
+    EXMC_NPINTEN3 = BANK3_NPINTEN_RESET;
+    EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET;
+    EXMC_NPATCFG3 = BANK3_NPATCFG_RESET;
+    EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET;
+}
+
+/*!
+    \brief      initialize EXMC PC card bank
+    \param[in]  exmc_pccard_parameter_struct: configure the EXMC NAND parameter
+                  atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
+                  ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
+                  wait_feature: ENABLE or DISABLE
+                  common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
+                  attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
+                  io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time
+    \param[out] none
+    \retval     none
+*/
+void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
+{
+    /* configure the EXMC bank3 PC card control register */
+    EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) |
+                             EXMC_NAND_DATABUS_WIDTH_16B |  
+                             exmc_pccard_init_struct->ctr_latency |
+                             exmc_pccard_init_struct->atr_latency ;
+
+    /* configure the EXMC bank3 PC card common space timing configuration register */
+    EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) |
+                              (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
+                              ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
+                              (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
+
+    /* configure the EXMC bank3 PC card attribute space timing configuration register */
+    EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
+                              (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
+                              ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )|
+                              (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
+
+    /* configure the EXMC bank3 PC card io space timing configuration register */
+    EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) |
+                              (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) |
+                              ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )|
+                              ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ );
+}
+
+/*!
+    \brief      initialize the struct exmc_pccard_parameter_struct
+    \param[in]  none
+    \param[out] the initialized struct exmc_pccard_parameter_struct pointer
+    \retval     none
+*/
+void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
+{
+    /* configure the structure with default value */
+    exmc_pccard_init_struct->wait_feature = DISABLE;
+    exmc_pccard_init_struct->ctr_latency = 0x0U;
+    exmc_pccard_init_struct->atr_latency = 0x0U;
+    exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU;
+    exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU;
+    exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU;
+    exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU;
+    exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU;
+    exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU;
+    exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU;
+    exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
+    exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU;
+    exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU;
+    exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU;
+    exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU;
+}
+
+/*!
+    \brief      enable PC Card Bank
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void exmc_pccard_enable(void)
+{
+    EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN;
+}
+
+/*!
+    \brief      disable PC Card Bank
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void exmc_pccard_disable(void)
+{
+   EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN;
+}
+
+/*!
+    \brief      enable EXMC interrupt
+    \param[in]  bank: specifies the NAND bank, PC card bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC card bank
+    \param[in]  interrupt_source: specify get which interrupt flag
+                one or more parameters can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge
+      \arg        EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level
+      \arg        EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source)
+{
+    /* NAND bank1, bank2 or PC card bank3 */
+    EXMC_NPINTEN(bank) |= interrupt_source;
+}
+
+/*!
+    \brief      disable EXMC interrupt
+    \param[in]  bank: specifies the NAND bank, PC card bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC card bank
+    \param[in]  interrupt_source: specify get which interrupt flag
+                one or more parameters can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge
+      \arg        EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level
+      \arg        EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(bank) &= ~interrupt_source;
+}
+
+/*!
+    \brief      check EXMC flag is set or not
+    \param[in]  bank: specifies the NAND bank, PC card bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC Card bank
+    \param[in]  flag: specify get which flag
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
+      \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
+      \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
+      \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag)
+{
+    uint32_t status = 0x00000000U;
+
+    /* NAND bank1,bank2 or PC card bank3 */
+    status = EXMC_NPINTEN(bank);
+    
+    if ((status & flag) != (uint32_t)flag ){
+        /* flag is reset */
+        return RESET;
+    }else{
+        /* flag is set */
+        return SET;
+    }
+}
+
+/*!
+    \brief      clear EXMC flag
+    \param[in]  bank: specifie the NAND bank, PCCARD bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC card bank
+    \param[in]  flag: specify get which flag
+                one or more parameters can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
+      \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
+      \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
+      \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
+    \param[out] none
+    \retval     none
+*/
+void exmc_flag_clear(uint32_t bank, uint32_t flag)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(bank) &= ~flag;
+}
+
+/*!
+    \brief      check EXMC interrupt flag is set or not
+    \param[in]  bank: specifies the NAND bank, PC card bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC card bank
+    \param[in]  interrupt_source: specify get which interrupt flag
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge
+      \arg        EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level
+      \arg        EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source)
+{
+    uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U;
+
+    /* NAND bank1,bank2 or PC card bank3 */
+    status = EXMC_NPINTEN(bank);
+    interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET));
+
+    interrupt_enable = (status & interrupt_source);
+
+    if ((interrupt_enable) && (interrupt_state)){
+        /* interrupt flag is set */
+        return SET;
+    }else{
+        /* interrupt flag is reset */
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear EXMC interrupt flag
+    \param[in]  bank: specifies the NAND bank, PC card bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK1_NAND: the NAND bank1
+      \arg        EXMC_BANK2_NAND: the NAND bank2
+      \arg        EXMC_BANK3_PCCARD: the PC card bank
+    \param[in]  interrupt_source: specify get which interrupt flag
+                one or more parameters can be selected which is shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge
+      \arg        EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level
+      \arg        EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source)
+{
+    /* NAND bank1, bank2 or PC card bank3 */
+    EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET);
+}

+ 251 - 0
Library/Source/gd32f10x_exti.c

@@ -0,0 +1,251 @@
+/*!
+    \file    gd32f10x_exti.c
+    \brief   EXTI driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+#include "gd32f10x_exti.h"
+
+#define EXTI_REG_RESET_VALUE            ((uint32_t)0x00000000U)
+
+/*!
+    \brief      deinitialize the EXTI
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void exti_deinit(void)
+{
+    /* reset the value of all the EXTI registers */
+    EXTI_INTEN = EXTI_REG_RESET_VALUE;
+    EXTI_EVEN  = EXTI_REG_RESET_VALUE;
+    EXTI_RTEN  = EXTI_REG_RESET_VALUE;
+    EXTI_FTEN  = EXTI_REG_RESET_VALUE;
+    EXTI_SWIEV = EXTI_REG_RESET_VALUE;
+}
+
+/*!
+    \brief      initialize the EXTI
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[in]  mode: interrupt or event mode, refer to exti_mode_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_INTERRUPT: interrupt mode
+      \arg        EXTI_EVENT: event mode
+    \param[in]  trig_type: interrupt trigger type, refer to exti_trig_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_TRIG_RISING: rising edge trigger
+      \arg        EXTI_TRIG_FALLING: falling trigger
+      \arg        EXTI_TRIG_BOTH: rising and falling trigger
+      \arg        EXTI_TRIG_NONE: without rising edge or falling edge trigger
+    \param[out] none
+    \retval     none
+*/
+void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
+{
+    /* reset the EXTI line x */
+    EXTI_INTEN &= ~(uint32_t)linex;
+    EXTI_EVEN &= ~(uint32_t)linex;
+    EXTI_RTEN &= ~(uint32_t)linex;
+    EXTI_FTEN &= ~(uint32_t)linex;
+    
+    /* set the EXTI mode and enable the interrupts or events from EXTI line x */
+    switch(mode){
+    case EXTI_INTERRUPT:
+        EXTI_INTEN |= (uint32_t)linex;
+        break;
+    case EXTI_EVENT:
+        EXTI_EVEN |= (uint32_t)linex;
+        break;
+    default:
+        break;
+    }
+    
+    /* set the EXTI trigger type */
+    switch(trig_type){
+    case EXTI_TRIG_RISING:
+        EXTI_RTEN |= (uint32_t)linex;
+        EXTI_FTEN &= ~(uint32_t)linex;
+        break;
+    case EXTI_TRIG_FALLING:
+        EXTI_RTEN &= ~(uint32_t)linex;
+        EXTI_FTEN |= (uint32_t)linex;
+        break;
+    case EXTI_TRIG_BOTH:
+        EXTI_RTEN |= (uint32_t)linex;
+        EXTI_FTEN |= (uint32_t)linex;
+        break;
+    case EXTI_TRIG_NONE:
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      enable the interrupts from EXTI line x
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_interrupt_enable(exti_line_enum linex)
+{
+    EXTI_INTEN |= (uint32_t)linex;
+}
+
+/*!
+    \brief      enable the events from EXTI line x
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_event_enable(exti_line_enum linex)
+{
+    EXTI_EVEN |= (uint32_t)linex;
+}
+
+/*!
+    \brief      disable the interrupt from EXTI line x
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_interrupt_disable(exti_line_enum linex)
+{
+    EXTI_INTEN &= ~(uint32_t)linex;
+}
+
+/*!
+    \brief      disable the events from EXTI line x
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_event_disable(exti_line_enum linex)
+{
+    EXTI_EVEN &= ~(uint32_t)linex;
+}
+
+/*!
+    \brief      get EXTI lines flag
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     FlagStatus: status of flag (RESET or SET)
+*/
+FlagStatus exti_flag_get(exti_line_enum linex)
+{
+    if(RESET != (EXTI_PD & (uint32_t)linex)){
+        return SET;
+    }else{
+        return RESET;
+    } 
+}
+
+/*!
+    \brief      clear EXTI lines pending flag
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_flag_clear(exti_line_enum linex)
+{
+    EXTI_PD = (uint32_t)linex;
+}
+
+/*!
+    \brief      get EXTI lines flag when the interrupt flag is set
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     FlagStatus: status of flag (RESET or SET)
+*/
+FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
+{
+    if(RESET != (EXTI_PD & (uint32_t)linex)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear EXTI lines pending flag
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_interrupt_flag_clear(exti_line_enum linex)
+{
+    EXTI_PD = (uint32_t)linex;
+}
+
+/*!
+    \brief      enable EXTI software interrupt event
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_software_interrupt_enable(exti_line_enum linex)
+{
+    EXTI_SWIEV |= (uint32_t)linex;
+}
+
+/*!
+    \brief      disable EXTI software interrupt event
+    \param[in]  linex: EXTI line number, refer to exti_line_enum
+                only one parameter can be selected which is shown as below:
+      \arg        EXTI_x (x=0..19): EXTI line x
+    \param[out] none
+    \retval     none
+*/
+void exti_software_interrupt_disable(exti_line_enum linex)
+{
+    EXTI_SWIEV &= ~(uint32_t)linex;
+}

+ 964 - 0
Library/Source/gd32f10x_fmc.c

@@ -0,0 +1,964 @@
+/*!
+    \file    gd32f10x_fmc.c
+    \brief   FMC driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_fmc.h"
+
+/*!
+    \brief      set the wait state counter value
+    \param[in]  wscnt£ºwait state counter value
+      \arg        WS_WSCNT_0: FMC 0 wait state
+      \arg        WS_WSCNT_1: FMC 1 wait state
+      \arg        WS_WSCNT_2: FMC 2 wait state
+    \param[out] none
+    \retval     none
+*/
+void fmc_wscnt_set(uint32_t wscnt)
+{
+    uint32_t reg;
+    
+    reg = FMC_WS;
+    /* set the wait state counter value */
+    reg &= ~FMC_WS_WSCNT;
+    FMC_WS = (reg | wscnt);
+}
+
+/*!
+    \brief      unlock the main FMC operation
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_unlock(void)
+{
+    if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){
+        /* write the FMC unlock key */
+        FMC_KEY0 = UNLOCK_KEY0;
+        FMC_KEY0 = UNLOCK_KEY1;
+    }
+
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        /* write the FMC unlock key */
+        if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){
+            FMC_KEY1 = UNLOCK_KEY0;
+            FMC_KEY1 = UNLOCK_KEY1;
+        }
+    }
+}
+
+/*!
+    \brief      unlock the FMC bank0 operation 
+                this function can be used for all GD32F10x devices.
+                for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0.
+                for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function.
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_bank0_unlock(void)
+{
+    if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){
+        /* write the FMC unlock key */
+        FMC_KEY0 = UNLOCK_KEY0;
+        FMC_KEY0 = UNLOCK_KEY1;
+    }
+}
+
+/*!
+    \brief      unlock the FMC bank1 operation 
+                this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB.
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_bank1_unlock(void)
+{
+    if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){
+        /* write the FMC unlock key */
+        FMC_KEY1 = UNLOCK_KEY0;
+        FMC_KEY1 = UNLOCK_KEY1;
+    }
+}
+
+/*!
+    \brief      lock the main FMC operation
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_lock(void)
+{
+    /* set the LK bit */
+    FMC_CTL0 |= FMC_CTL0_LK;
+    
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        /* set the LK bit */
+        FMC_CTL1 |= FMC_CTL1_LK;
+    }
+}
+
+/*!
+    \brief      lock the FMC bank0 operation
+                this function can be used for all GD32F10X devices.
+                for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0.
+                for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function.
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_bank0_lock(void)
+{
+    /* set the LK bit*/
+    FMC_CTL0 |= FMC_CTL0_LK;
+}
+
+/*!
+    \brief      lock the FMC bank1 operation
+                this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB.
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fmc_bank1_lock(void)
+{
+    /* set the LK bit*/
+    FMC_CTL1 |= FMC_CTL1_LK;
+}
+
+/*!
+    \brief      erase page
+    \param[in]  page_address: the page address to be erased.
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_page_erase(uint32_t page_address)
+{
+    fmc_state_enum fmc_state;
+    
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        if(FMC_BANK0_END_ADDRESS > page_address){
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* if the last operation is completed, start page erase */
+            if(FMC_READY == fmc_state){
+                FMC_CTL0 |= FMC_CTL0_PER;
+                FMC_ADDR0 = page_address;
+                FMC_CTL0 |= FMC_CTL0_START;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PER bit */
+                FMC_CTL0 &= ~FMC_CTL0_PER;
+            }
+        }else{
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+            /* if the last operation is completed, start page erase */
+            if(FMC_READY == fmc_state){
+                FMC_CTL1 |= FMC_CTL1_PER;
+                FMC_ADDR1 = page_address;
+                if(FMC_OBSTAT & FMC_OBSTAT_SPC){
+                    FMC_ADDR0 = page_address;
+                }
+                FMC_CTL1 |= FMC_CTL1_START;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PER bit */
+                FMC_CTL1 &= ~FMC_CTL1_PER;
+            }
+        }
+    }else{
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        /* if the last operation is completed, start page erase */
+        if(FMC_READY == fmc_state){
+            FMC_CTL0 |= FMC_CTL0_PER;
+            FMC_ADDR0 = page_address;
+            FMC_CTL0 |= FMC_CTL0_START;
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the PER bit */
+            FMC_CTL0 &= ~FMC_CTL0_PER;
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      erase whole chip
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_mass_erase(void)
+{
+    fmc_state_enum fmc_state;
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        if(FMC_READY == fmc_state){
+            /* start whole chip erase */
+            FMC_CTL0 |= FMC_CTL0_MER;
+            FMC_CTL0 |= FMC_CTL0_START;
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the MER bit */
+            FMC_CTL0 &= ~FMC_CTL0_MER;
+        }
+        fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+        if(FMC_READY == fmc_state){
+            /* start whole chip erase */
+            FMC_CTL1 |= FMC_CTL1_MER;
+            FMC_CTL1 |= FMC_CTL1_START;
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the MER bit */
+            FMC_CTL1 &= ~FMC_CTL1_MER;
+        }
+    }else{
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+  
+        if(FMC_READY == fmc_state){
+            /* start whole chip erase */
+            FMC_CTL0 |= FMC_CTL0_MER;
+            FMC_CTL0 |= FMC_CTL0_START;    
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the MER bit */
+            FMC_CTL0 &= ~FMC_CTL0_MER;
+        }
+    }
+    /* return the FMC state  */
+    return fmc_state;
+}
+
+/*!
+    \brief      erase bank0
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank0_erase(void)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+    /* wait for the FMC ready */
+    fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+    if(FMC_READY == fmc_state){
+        /* start FMC bank0 erase */
+        FMC_CTL0 |= FMC_CTL0_MER;
+        FMC_CTL0 |= FMC_CTL0_START;
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        /* reset the MER bit */
+        FMC_CTL0 &= ~FMC_CTL0_MER;
+    }
+    /* return the fmc state */
+    return fmc_state;
+}
+
+/*!
+    \brief      erase bank1
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank1_erase(void)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+    /* wait for the FMC ready */
+    fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+  
+   if(FMC_READY == fmc_state){
+        /* start FMC bank1 erase */
+        FMC_CTL1 |= FMC_CTL1_MER;
+        FMC_CTL1 |= FMC_CTL1_START;
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+        /* reset the MER bit */
+        FMC_CTL1 &= ~FMC_CTL1_MER;
+    }
+    /* return the fmc state */
+    return fmc_state;
+}
+
+/*!
+    \brief      program a word at the corresponding address
+    \param[in]  address: address to program
+    \param[in]  data: word to program
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        if(FMC_BANK0_END_ADDRESS > address){
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); 
+  
+            if(FMC_READY == fmc_state){
+                /* set the PG bit to start program */
+                FMC_CTL0 |= FMC_CTL0_PG;
+                REG32(address) = data;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PG bit */
+                FMC_CTL0 &= ~FMC_CTL0_PG;
+            }
+        }else{
+            fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); 
+  
+            if(FMC_READY == fmc_state){
+                /* set the PG bit to start program */
+                FMC_CTL1 |= FMC_CTL1_PG;
+                REG32(address) = data;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PG bit */
+                FMC_CTL1 &= ~FMC_CTL1_PG;
+            }
+        }
+    }else{
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+  
+        if(FMC_READY == fmc_state){
+            /* set the PG bit to start program */
+            FMC_CTL0 |= FMC_CTL0_PG;
+            REG32(address) = data;
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the PG bit */
+            FMC_CTL0 &= ~FMC_CTL0_PG;
+        } 
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      program a half word at the corresponding address
+    \param[in]  address: address to program
+    \param[in]  data: halfword to program
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+    if(FMC_BANK0_SIZE < FMC_SIZE){
+        if(FMC_BANK0_END_ADDRESS > address){
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); 
+  
+            if(FMC_READY == fmc_state){
+                /* set the PG bit to start program */
+                FMC_CTL0 |= FMC_CTL0_PG;
+                REG16(address) = data;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PG bit */
+                FMC_CTL0 &= ~FMC_CTL0_PG;
+            }
+        }else{
+            fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); 
+  
+            if(FMC_READY == fmc_state){
+                /* set the PG bit to start program */
+                FMC_CTL1 |= FMC_CTL1_PG;
+                REG16(address) = data;
+                /* wait for the FMC ready */
+                fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
+                /* reset the PG bit */
+                FMC_CTL1 &= ~FMC_CTL1_PG;
+            }
+        }
+    }else{
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+  
+        if(FMC_READY == fmc_state){
+            /* set the PG bit to start program */
+            FMC_CTL0 |= FMC_CTL0_PG;
+            REG16(address) = data;
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+            /* reset the PG bit */
+            FMC_CTL0 &= ~FMC_CTL0_PG;
+        } 
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      unlock the option byte operation
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ob_unlock(void)
+{
+    if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){
+        /* write the FMC key */
+        FMC_OBKEY = UNLOCK_KEY0;
+        FMC_OBKEY = UNLOCK_KEY1;
+    }
+
+    /* wait until OBWEN bit is set by hardware */
+    while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){
+    }
+}
+
+/*!
+    \brief      lock the option byte operation
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ob_lock(void)
+{
+    /* reset the OBWEN bit */
+    FMC_CTL0 &= ~FMC_CTL0_OBWEN;
+}
+
+/*!
+    \brief      erase the FMC option byte
+                unlock the FMC_CTL0 and option byte before calling this function
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum ob_erase(void)
+{
+    uint16_t temp_spc = FMC_NSPC;
+
+    fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+    /* check the option byte security protection value */
+    if(RESET != ob_spc_get()){
+        temp_spc = FMC_USPC;  
+    }
+
+    if(FMC_READY == fmc_state){
+
+        /* start erase the option byte */
+        FMC_CTL0 |= FMC_CTL0_OBER;
+        FMC_CTL0 |= FMC_CTL0_START;
+
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+    
+        if(FMC_READY == fmc_state){
+            /* reset the OBER bit */
+            FMC_CTL0 &= ~FMC_CTL0_OBER;
+            /* set the OBPG bit */
+            FMC_CTL0 |= FMC_CTL0_OBPG;
+            /* no security protection */
+            OB_SPC = (uint16_t)temp_spc; 
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); 
+            if(FMC_TOERR != fmc_state){
+                /* reset the OBPG bit */
+                FMC_CTL0 &= ~FMC_CTL0_OBPG;
+            }
+        }else{
+            if(FMC_TOERR != fmc_state){
+                /* reset the OBPG bit */
+                FMC_CTL0 &= ~FMC_CTL0_OBPG;
+            }
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      enable write protection
+    \param[in]  ob_wp: specify sector to be write protected, set the bit to 1 if 
+                you want to protect the corresponding pages. meanwhile, sector 
+                macro could used to set specific sector write protected. 
+                one or more parameters can be selected which are shown as below:
+      \arg        OB_WPx(x = 0..31): write protect specify sector
+      \arg        OB_WP_ALL: write protect all sector
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
+{
+    uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3;
+
+    fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+    ob_wp = (uint32_t)(~ob_wp);
+    temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0);
+    temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U);
+    temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U);
+    temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U);
+
+    if(FMC_READY == fmc_state){
+    
+        /* set the OBPG bit*/
+        FMC_CTL0 |= FMC_CTL0_OBPG;
+
+        if(0xFFU != temp_wp0){
+            OB_WP0 = temp_wp0;
+      
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        }
+        if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){
+            OB_WP1 = temp_wp1;
+      
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        }
+        if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){
+            OB_WP2 = temp_wp2;
+      
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        }
+        if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){
+            OB_WP3 = temp_wp3;
+      
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+        }
+        if(FMC_TOERR != fmc_state){
+            /* reset the OBPG bit */
+            FMC_CTL0 &= ~FMC_CTL0_OBPG;
+        }
+    } 
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      configure security protection
+    \param[in]  ob_spc: specify security protection
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_NSPC: no security protection
+      \arg        FMC_USPC: under security protection
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
+{
+    fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+    if(FMC_READY == fmc_state){
+        FMC_CTL0 |= FMC_CTL0_OBER;
+        FMC_CTL0 |= FMC_CTL0_START;
+    
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+    
+        if(FMC_READY == fmc_state){
+            /* reset the OBER bit */
+            FMC_CTL0 &= ~FMC_CTL0_OBER;
+      
+            /* start the option byte program */
+            FMC_CTL0 |= FMC_CTL0_OBPG;
+       
+            OB_SPC = (uint16_t)ob_spc;
+
+            /* wait for the FMC ready */
+            fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); 
+    
+            if(FMC_TOERR != fmc_state){
+                /* reset the OBPG bit */
+                FMC_CTL0 &= ~FMC_CTL0_OBPG;
+            }
+        }else{
+            if(FMC_TOERR != fmc_state){
+                /* reset the OBER bit */
+                FMC_CTL0 &= ~FMC_CTL0_OBER;
+            }
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      program the FMC user option byte 
+    \param[in]  ob_fwdgt: option byte watchdog value
+      \arg        OB_FWDGT_SW: software free watchdog
+      \arg        OB_FWDGT_HW: hardware free watchdog
+    \param[in]  ob_deepsleep: option byte deepsleep reset value
+      \arg        OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
+      \arg        OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode 
+    \param[in]  ob_stdby:option byte standby reset value
+      \arg        OB_STDBY_NRST: no reset when entering standby mode
+      \arg        OB_STDBY_RST: generate a reset instead of entering standby mode
+    \param[in]  ob_boot: specifies the option byte boot bank value
+      \arg        OB_BOOT_B0: boot from bank0
+      \arg        OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+    uint8_t temp;
+
+    /* wait for the FMC ready */
+    fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+  
+    if(FMC_READY == fmc_state){
+        /* set the OBPG bit*/
+        FMC_CTL0 |= FMC_CTL0_OBPG; 
+
+        temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK);
+        OB_USER = (uint16_t)temp;
+    
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+        if(FMC_TOERR != fmc_state){
+            /* reset the OBPG bit */
+            FMC_CTL0 &= ~FMC_CTL0_OBPG;
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      program option bytes data
+    \param[in]  address: the option bytes address to be programmed
+    \param[in]  data: the byte to be programmed
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum ob_data_program(uint32_t address, uint8_t data)
+{
+    fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+
+    if(FMC_READY == fmc_state){
+        /* set the OBPG bit */
+        FMC_CTL0 |= FMC_CTL0_OBPG; 
+        REG16(address) = data;
+    
+        /* wait for the FMC ready */
+        fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
+    
+        if(FMC_TOERR != fmc_state){
+            /* reset the OBPG bit */
+            FMC_CTL0 &= ~FMC_CTL0_OBPG;
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      get the FMC user option byte
+    \param[in]  none
+    \param[out] none
+    \retval     the FMC user option byte values
+*/
+uint8_t ob_user_get(void)
+{
+    /* return the FMC user option byte value */
+    return (uint8_t)(FMC_OBSTAT >> 2U);
+}
+
+/*!
+    \brief      get OB_DATA in register FMC_OBSTAT
+    \param[in]  none
+    \param[out] none
+    \retval     ob_data
+*/
+uint16_t ob_data_get(void)
+{
+    return (uint16_t)(FMC_OBSTAT >> 10U);
+}
+
+/*!
+    \brief      get the FMC option byte write protection
+    \param[in]  none
+    \param[out] none
+    \retval     the FMC write protection option byte value
+*/
+uint32_t ob_write_protection_get(void)
+{
+    /* return the FMC write protection option byte value */
+    return FMC_WP;
+}
+
+/*!
+    \brief      get the FMC option byte security protection
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus ob_spc_get(void)
+{
+    FlagStatus spc_state = RESET;
+
+    if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){
+        spc_state = SET;
+    }else{
+        spc_state = RESET;
+    }
+    return spc_state;
+}
+
+/*!
+    \brief      enable FMC interrupt
+    \param[in]  interrupt: the FMC interrupt source
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_INT_BANK0_END: enable FMC end of program interrupt
+      \arg        FMC_INT_BANK0_ERR: enable FMC error interrupt
+      \arg        FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt
+      \arg        FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt
+    \param[out] none
+    \retval     none
+*/
+void fmc_interrupt_enable(uint32_t interrupt)
+{
+    FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt));
+}
+
+/*!
+    \brief      disable FMC interrupt
+    \param[in]  interrupt: the FMC interrupt source
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_INT_BANK0_END: enable FMC end of program interrupt
+      \arg        FMC_INT_BANK0_ERR: enable FMC error interrupt
+      \arg        FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt
+      \arg        FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt
+    \param[out] none
+    \retval     none
+*/
+void fmc_interrupt_disable(uint32_t interrupt)
+{
+    FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt));
+}
+
+/*!
+    \brief      check flag is set or not
+    \param[in]  flag: check FMC flag
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit
+      \arg        FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit
+      \arg        FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit
+      \arg        FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit
+      \arg        FMC_FLAG_OBERR: FMC option bytes read error flag bit
+      \arg        FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit
+      \arg        FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit
+      \arg        FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit
+      \arg        FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus fmc_flag_get(uint32_t flag)
+{
+    if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear the FMC flag
+    \param[in]  flag: clear FMC flag
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit
+      \arg        FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit
+      \arg        FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit
+      \arg        FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit
+      \arg        FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit
+      \arg        FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit
+    \param[out] none
+    \retval     none
+*/
+void fmc_flag_clear(uint32_t flag)
+{
+    FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag));
+}
+
+/*!
+    \brief      get FMC interrupt flag state
+    \param[in]  flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag)
+{
+    uint32_t ret1 = RESET;
+    uint32_t ret2 = RESET;
+    
+    if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){
+        /* get the staus of interrupt flag */
+        ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
+        /* get the staus of interrupt enale bit */
+        ret2 = (uint32_t)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag)));
+    }else{
+        /* get the staus of interrupt flag */
+        ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
+        /* get the staus of interrupt enale bit */
+        ret2 = (uint32_t)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag)));
+    }
+
+    if(ret1 && ret2){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear FMC interrupt flag state
+    \param[in]  flag: FMC interrupt flags, refer to can_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit
+      \arg        FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit
+    \param[out] none
+    \retval     none
+*/
+void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag)
+{
+    FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag));
+}
+
+/*!
+    \brief      get the FMC bank0 state
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank0_state_get(void)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+  
+    if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){
+        fmc_state = FMC_BUSY;
+    }else{
+        if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){
+            fmc_state = FMC_WPERR;
+        }else{
+            if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){
+                fmc_state = FMC_PGERR; 
+            }
+        }
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      get the FMC bank1 state
+    \param[in]  none
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank1_state_get(void)
+{
+    fmc_state_enum fmc_state = FMC_READY;
+
+    if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){
+        fmc_state = FMC_BUSY;
+    }else{
+        if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){
+            fmc_state = FMC_WPERR;
+        }else{
+            if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){
+                fmc_state = FMC_PGERR; 
+            }
+        }
+    }
+
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      check whether FMC bank0 is ready or not
+    \param[in]  timeout: count of loop
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout)
+{
+    fmc_state_enum fmc_state = FMC_BUSY;
+  
+    /* wait for FMC ready */
+    do{
+        /* get FMC state */
+        fmc_state = fmc_bank0_state_get();
+        timeout--;
+    }while((FMC_BUSY == fmc_state) && (0x00U != timeout));
+    
+    if(FMC_BUSY == fmc_state){
+        fmc_state = FMC_TOERR;
+    }
+    /* return the FMC state */
+    return fmc_state;
+}
+
+/*!
+    \brief      check whether FMC bank1 is ready or not
+    \param[in]  timeout: count of loop
+    \param[out] none
+    \retval     state of FMC, refer to fmc_state_enum
+*/
+fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout)
+{
+    fmc_state_enum fmc_state = FMC_BUSY;
+  
+    /* wait for FMC ready */
+    do{
+        /* get FMC state */
+        fmc_state = fmc_bank1_state_get();
+        timeout--;
+    }while((FMC_BUSY == fmc_state) && (0x00U != timeout));
+    
+    if(FMC_BUSY == fmc_state){
+        fmc_state = FMC_TOERR;
+    }
+    /* return the FMC state */
+    return fmc_state;
+}

+ 154 - 0
Library/Source/gd32f10x_fwdgt.c

@@ -0,0 +1,154 @@
+/*!
+    \file    gd32f10x_fwdgt.c
+    \brief   FWDGT driver
+       
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_fwdgt.h"
+
+/* write value to FWDGT_CTL_CMD bit field */
+#define CTL_CMD(regval)             (BITS(0,15) & ((uint32_t)(regval) << 0))
+/* write value to FWDGT_RLD_RLD bit field */
+#define RLD_RLD(regval)             (BITS(0,11) & ((uint32_t)(regval) << 0))
+
+/*!
+    \brief      enable write access to FWDGT_PSC and FWDGT_RLD
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fwdgt_write_enable(void)
+{
+    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
+}
+
+/*!
+    \brief      disable write access to FWDGT_PSC and FWDGT_RLD
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fwdgt_write_disable(void)
+{
+    FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
+}
+
+/*!
+    \brief      start the free watchdog timer counter
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fwdgt_enable(void)
+{
+    FWDGT_CTL = FWDGT_KEY_ENABLE;
+}
+
+/*!
+    \brief      reload the counter of FWDGT
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void fwdgt_counter_reload(void)
+{
+    FWDGT_CTL = FWDGT_KEY_RELOAD;
+}
+
+/*!
+    \brief      configure counter reload value, and prescaler divider value
+    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
+    \param[in]  prescaler_div: FWDGT prescaler value
+                only one parameter can be selected which is shown as below:
+      \arg        FWDGT_PSC_DIV4: FWDGT prescaler set to 4
+      \arg        FWDGT_PSC_DIV8: FWDGT prescaler set to 8
+      \arg        FWDGT_PSC_DIV16: FWDGT prescaler set to 16
+      \arg        FWDGT_PSC_DIV32: FWDGT prescaler set to 32
+      \arg        FWDGT_PSC_DIV64: FWDGT prescaler set to 64
+      \arg        FWDGT_PSC_DIV128: FWDGT prescaler set to 128
+      \arg        FWDGT_PSC_DIV256: FWDGT prescaler set to 256
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
+{
+    uint32_t timeout = FWDGT_PSC_TIMEOUT;
+    uint32_t flag_status = RESET;
+  
+    /* enable write access to FWDGT_PSC,and FWDGT_RLD */
+    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
+    /* wait until the PUD flag to be reset */
+    do{
+       flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
+    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
+    
+    if((uint32_t)RESET != flag_status){
+        return ERROR;
+    }
+    /* configure FWDGT */
+    FWDGT_PSC = (uint32_t)prescaler_div;
+
+    timeout = FWDGT_RLD_TIMEOUT;
+    /* wait until the RUD flag to be reset */
+    do{
+       flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
+    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
+   
+    if((uint32_t)RESET != flag_status){
+        return ERROR;
+    }
+    FWDGT_RLD = RLD_RLD(reload_value);
+    /* reload the counter */
+    FWDGT_CTL = FWDGT_KEY_RELOAD;
+
+    return SUCCESS;
+}
+
+/*!
+    \brief      get flag state of FWDGT
+    \param[in]  flag: flag to get 
+                only one parameter can be selected which is shown as below:
+      \arg        FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going
+      \arg        FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus fwdgt_flag_get(uint16_t flag)
+{
+    if(FWDGT_STAT & flag){
+        return SET;
+    }
+    
+    return RESET;
+}

+ 538 - 0
Library/Source/gd32f10x_gpio.c

@@ -0,0 +1,538 @@
+/*!
+    \file    gd32f10x_gpio.c
+    \brief   GPIO driver
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_gpio.h"
+
+#define AFIO_EXTI_SOURCE_MASK              ((uint8_t)0x03U)         /*!< AFIO exti source selection mask*/  
+#define AFIO_EXTI_SOURCE_FIELDS            ((uint8_t)0x04U)         /*!< select AFIO exti source registers */
+#define LSB_16BIT_MASK                     ((uint16_t)0xFFFFU)      /*!< LSB 16-bit mask */
+#define PCF_POSITION_MASK                  ((uint32_t)0x000F0000U)  /*!< AFIO_PCF register position mask */
+#define PCF_SWJCFG_MASK                    ((uint32_t)0xF0FFFFFFU)  /*!< AFIO_PCF register SWJCFG mask */
+#define PCF_LOCATION1_MASK                 ((uint32_t)0x00200000U)  /*!< AFIO_PCF register location1 mask */
+#define PCF_LOCATION2_MASK                 ((uint32_t)0x00100000U)  /*!< AFIO_PCF register location2 mask */
+#define AFIO_PCF1_FIELDS                   ((uint32_t)0x80000000U)  /*!< select AFIO_PCF1 register */
+#define GPIO_OUTPUT_PORT_OFFSET            ((uint32_t)4U)           /*!< GPIO event output port offset*/
+
+/*!
+    \brief      reset GPIO port
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
+    \param[out] none
+    \retval     none
+*/
+void gpio_deinit(uint32_t gpio_periph)
+{
+    switch(gpio_periph){
+    case GPIOA:
+        /* reset GPIOA */
+        rcu_periph_reset_enable(RCU_GPIOARST);
+        rcu_periph_reset_disable(RCU_GPIOARST);
+        break;
+    case GPIOB:
+        /* reset GPIOB */
+        rcu_periph_reset_enable(RCU_GPIOBRST);
+        rcu_periph_reset_disable(RCU_GPIOBRST);
+        break;
+    case GPIOC:
+        /* reset GPIOC */
+        rcu_periph_reset_enable(RCU_GPIOCRST);
+        rcu_periph_reset_disable(RCU_GPIOCRST);
+        break;
+    case GPIOD:
+        /* reset GPIOD */
+        rcu_periph_reset_enable(RCU_GPIODRST);
+        rcu_periph_reset_disable(RCU_GPIODRST);
+        break;
+    case GPIOE:
+        /* reset GPIOE */
+        rcu_periph_reset_enable(RCU_GPIOERST);
+        rcu_periph_reset_disable(RCU_GPIOERST);
+        break;
+    case GPIOF:
+        /* reset GPIOF */
+        rcu_periph_reset_enable(RCU_GPIOFRST);
+        rcu_periph_reset_disable(RCU_GPIOFRST);
+        break;
+    case GPIOG:
+        /* reset GPIOG */
+        rcu_periph_reset_enable(RCU_GPIOGRST);
+        rcu_periph_reset_disable(RCU_GPIOGRST);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      reset alternate function I/O(AFIO)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void gpio_afio_deinit(void)
+{
+    rcu_periph_reset_enable(RCU_AFRST);
+    rcu_periph_reset_disable(RCU_AFRST);
+}
+
+/*!
+    \brief      GPIO parameter initialization
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  mode: gpio pin mode
+                only one parameter can be selected which is shown as below:
+      \arg        GPIO_MODE_AIN: analog input mode
+      \arg        GPIO_MODE_IN_FLOATING: floating input mode
+      \arg        GPIO_MODE_IPD: pull-down input mode
+      \arg        GPIO_MODE_IPU: pull-up input mode
+      \arg        GPIO_MODE_OUT_OD: GPIO output with open-drain
+      \arg        GPIO_MODE_OUT_PP: GPIO output with push-pull
+      \arg        GPIO_MODE_AF_OD: AFIO output with open-drain
+      \arg        GPIO_MODE_AF_PP: AFIO output with push-pull
+    \param[in]  speed: gpio output max speed value
+                only one parameter can be selected which is shown as below:
+      \arg        GPIO_OSPEED_10MHZ: output max speed 10MHz
+      \arg        GPIO_OSPEED_2MHZ: output max speed 2MHz
+      \arg        GPIO_OSPEED_50MHZ: output max speed 50MHz
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+
+    \param[out] none
+    \retval     none
+*/
+void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
+{
+    uint16_t i;
+    uint32_t temp_mode = 0U;
+    uint32_t reg = 0U;
+
+    /* GPIO mode configuration */
+    temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
+    
+    /* GPIO speed configuration */
+    if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
+            /* output mode max speed:10MHz,2MHz,50MHz */
+            temp_mode |= (uint32_t)speed;
+    }
+
+    /* configure the eight low port pins with GPIO_CTL0 */
+    for(i = 0U;i < 8U;i++){
+        if((1U << i) & pin){
+            reg = GPIO_CTL0(gpio_periph);
+            
+            /* clear the specified pin mode bits */
+            reg &= ~GPIO_MODE_MASK(i);
+            /* set the specified pin mode bits */
+            reg |= GPIO_MODE_SET(i, temp_mode);
+            
+            /* set IPD or IPU */
+            if(GPIO_MODE_IPD == mode){
+                /* reset the corresponding OCTL bit */
+                GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
+            }else{
+                /* set the corresponding OCTL bit */
+                if(GPIO_MODE_IPU == mode){
+                    GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
+                }
+            }
+            /* set GPIO_CTL0 register */
+            GPIO_CTL0(gpio_periph) = reg;
+        }
+    }
+    /* configure the eight high port pins with GPIO_CTL1 */
+    for(i = 8U;i < 16U;i++){
+        if((1U << i) & pin){
+            reg = GPIO_CTL1(gpio_periph);
+            
+            /* clear the specified pin mode bits */
+            reg &= ~GPIO_MODE_MASK(i - 8U);
+            /* set the specified pin mode bits */
+            reg |= GPIO_MODE_SET(i - 8U, temp_mode);
+            
+            /* set IPD or IPU */
+            if(GPIO_MODE_IPD == mode){
+                /* reset the corresponding OCTL bit */
+                GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
+            }else{
+                /* set the corresponding OCTL bit */
+                if(GPIO_MODE_IPU == mode){
+                    GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
+                }
+            }
+            /* set GPIO_CTL1 register */
+            GPIO_CTL1(gpio_periph) = reg;
+        }
+    }
+}
+
+/*!
+    \brief      set GPIO pin
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[out] none
+    \retval     none
+*/
+void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
+{
+    GPIO_BOP(gpio_periph) = (uint32_t)pin;
+}
+
+/*!
+    \brief      reset GPIO pin
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[out] none
+    \retval     none
+*/
+void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
+{
+    GPIO_BC(gpio_periph) = (uint32_t)pin;
+}
+
+/*!
+    \brief      write data to the specified GPIO pin
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[in]  bit_value: SET or RESET
+      \arg        RESET: clear the port pin
+      \arg        SET: set the port pin
+    \param[out] none
+    \retval     none
+*/
+void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
+{
+    if(RESET != bit_value){
+        GPIO_BOP(gpio_periph) = (uint32_t)pin;
+    }else{
+        GPIO_BC(gpio_periph) = (uint32_t)pin;
+    }
+}
+
+/*!
+    \brief      write data to the specified GPIO port
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  data: specify the value to be written to the port output data register
+    \param[out] none
+    \retval     none
+*/
+void gpio_port_write(uint32_t gpio_periph,uint16_t data)
+{
+    GPIO_OCTL(gpio_periph) = (uint32_t)data;
+}
+
+/*!
+    \brief      get GPIO pin input status
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[out] none
+    \retval     input status of gpio pin: SET or RESET
+*/
+FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)
+{
+    if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
+        return SET; 
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      get GPIO port input status
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[out] none
+    \retval     input status of gpio all pins
+*/
+uint16_t gpio_input_port_get(uint32_t gpio_periph)
+{
+    return (uint16_t)(GPIO_ISTAT(gpio_periph));
+}
+
+/*!
+    \brief      get GPIO pin output status
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[out] none
+    \retval     output status of gpio pin: SET or RESET
+*/
+FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
+{
+    if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      get GPIO port output status
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[out] none
+    \retval     output status of gpio all pins
+*/
+uint16_t gpio_output_port_get(uint32_t gpio_periph)
+{
+    return ((uint16_t)GPIO_OCTL(gpio_periph));
+}
+
+/*!
+    \brief      configure GPIO pin remap
+    \param[in]  gpio_remap: select the pin to remap
+      \arg        GPIO_SPI0_REMAP: SPI0 remapping
+      \arg        GPIO_I2C0_REMAP: I2C0 remapping
+      \arg        GPIO_USART0_REMAP: USART0 remapping
+      \arg        GPIO_USART1_REMAP: USART1 remapping
+      \arg        GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
+      \arg        GPIO_USART2_FULL_REMAP: USART2 full remapping
+      \arg        GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping 
+      \arg        GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
+      \arg        GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
+      \arg        GPIO_TIMER1_PARTIAL_REMAP2: TIMER1 partial remapping
+      \arg        GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
+      \arg        GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
+      \arg        GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
+      \arg        GPIO_TIMER3_REMAP: TIMER3 remapping
+      \arg        GPIO_CAN_PARTIAL_REMAP: CAN partial remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F10X_CL devices)
+      \arg        GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F10X_CL devices)
+      \arg        GPIO_PD01_REMAP: PD01 remapping
+      \arg        GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices)
+      \arg        GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices)
+      \arg        GPIO_ENET_REMAP: ENET remapping(only for GD32F10X_CL devices) 
+      \arg        GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F10X_CL devices)
+      \arg        GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST
+      \arg        GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled
+      \arg        GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled
+      \arg        GPIO_SPI2_REMAP: SPI2 remapping(only for GD32F10X_CL, GD32F10X_HD and GD32F10X_XD devices) 
+      \arg        GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) 
+      \arg        GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F10X_CL devices) 
+      \arg        GPIO_TIMER8_REMAP: TIMER8 remapping
+      \arg        GPIO_TIMER9_REMAP: TIMER9 remapping
+      \arg        GPIO_TIMER10_REMAP: TIMER10 remapping
+      \arg        GPIO_TIMER12_REMAP: TIMER12 remapping
+      \arg        GPIO_TIMER13_REMAP: TIMER13 remapping
+      \arg        GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
+    \param[in]  newvalue: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
+{
+    uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
+
+    if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
+        /* get AFIO_PCF1 regiter value */
+        temp_reg = AFIO_PCF1;
+    }else{
+        /* get AFIO_PCF0 regiter value */
+        temp_reg = AFIO_PCF0;
+    }
+
+    temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
+    remap1 = remap & LSB_16BIT_MASK;
+
+    /* judge pin remap type */
+    if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){
+        temp_reg &= PCF_SWJCFG_MASK;
+        AFIO_PCF0 &= PCF_SWJCFG_MASK;
+    }else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){
+        remap2 = ((uint32_t)0x03U) << temp_mask;
+        temp_reg &= ~remap2;
+        temp_reg |= ~PCF_SWJCFG_MASK;
+    }else{
+        temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U));
+        temp_reg |= ~PCF_SWJCFG_MASK;
+    }
+    
+    /* set pin remap value */
+    if(DISABLE != newvalue){
+        temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U));
+    }
+    
+    if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
+        /* set AFIO_PCF1 regiter value */
+        AFIO_PCF1 = temp_reg;
+    }else{
+        /* set AFIO_PCF0 regiter value */
+        AFIO_PCF0 = temp_reg;
+    }
+}
+
+/*!
+    \brief      select GPIO pin exti sources
+    \param[in]  gpio_outputport: gpio event output port
+      \arg        GPIO_PORT_SOURCE_GPIOA: output port source A
+      \arg        GPIO_PORT_SOURCE_GPIOB: output port source B
+      \arg        GPIO_PORT_SOURCE_GPIOC: output port source C
+      \arg        GPIO_PORT_SOURCE_GPIOD: output port source D
+      \arg        GPIO_PORT_SOURCE_GPIOE: output port source E 
+      \arg        GPIO_PORT_SOURCE_GPIOF: output port source F
+      \arg        GPIO_PORT_SOURCE_GPIOG: output port source G
+    \param[in]  gpio_outputpin: GPIO_PIN_SOURCE_x(x=0..15)
+    \param[out] none
+    \retval     none
+*/
+void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
+{
+    uint32_t source = 0U;
+    source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
+
+    /* select EXTI sources */
+    if(GPIO_PIN_SOURCE_4 > output_pin){
+        /* select EXTI0/EXTI1/EXTI2/EXTI3 */
+        AFIO_EXTISS0 &= ~source;
+        AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
+    }else if(GPIO_PIN_SOURCE_8 > output_pin){
+        /* select EXTI4/EXTI5/EXTI6/EXTI7 */
+        AFIO_EXTISS1 &= ~source;
+        AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
+    }else if(GPIO_PIN_SOURCE_12 > output_pin){
+        /* select EXTI8/EXTI9/EXTI10/EXTI11 */
+        AFIO_EXTISS2 &= ~source;
+        AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
+    }else{
+        /* select EXTI12/EXTI13/EXTI14/EXTI15 */
+        AFIO_EXTISS3 &= ~source;
+        AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
+    }
+}
+
+/*!
+    \brief      configure GPIO pin event output
+    \param[in]  output_port: gpio event output port
+                only one parameter can be selected which are shown as below:
+      \arg        GPIO_EVENT_PORT_GPIOA: event output port A
+      \arg        GPIO_EVENT_PORT_GPIOB: event output port B
+      \arg        GPIO_EVENT_PORT_GPIOC: event output port C
+      \arg        GPIO_EVENT_PORT_GPIOD: event output port D
+      \arg        GPIO_EVENT_PORT_GPIOE: event output port E
+      \arg        GPIO_EVENT_PORT_GPIOE: event output port F
+      \arg        GPIO_EVENT_PORT_GPIOE: event output port G
+    \param[in]  output_pin:
+                only one parameter can be selected which are shown as below:
+      \arg        GPIO_EVENT_PIN_x(x=0..15)
+    \param[out] none
+    \retval     none
+*/
+void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
+{
+    uint32_t reg = 0U;
+    reg = AFIO_EC;
+    
+    /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
+    reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN));
+    
+    reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
+    reg |= (uint32_t)output_pin;
+    
+    AFIO_EC = reg;
+}
+
+/*!
+    \brief      enable GPIO pin event output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void gpio_event_output_enable(void)
+{
+    AFIO_EC |= AFIO_EC_EOE;
+}
+
+/*!
+    \brief      disable GPIO pin event output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void gpio_event_output_disable(void)
+{
+    AFIO_EC &= (uint32_t)(~AFIO_EC_EOE);
+}
+
+/*!
+    \brief      lock GPIO pin
+    \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F,G) 
+    \param[in]  pin: GPIO pin
+                one or more parameters can be selected which are shown as below:
+      \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
+    \param[out] none
+    \retval     none
+*/
+void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
+{
+    uint32_t lock = 0x00010000U;
+    lock |= pin;
+
+    /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
+    GPIO_LOCK(gpio_periph) = (uint32_t)lock;
+    GPIO_LOCK(gpio_periph) = (uint32_t)pin;
+    GPIO_LOCK(gpio_periph) = (uint32_t)lock;
+    lock = GPIO_LOCK(gpio_periph);
+    lock = GPIO_LOCK(gpio_periph);
+}
+
+#ifdef GD32F10X_CL
+/*!
+    \brief      select ethernet MII or RMII PHY
+    \param[in]  gpio_enetsel: ethernet MII or RMII PHY selection
+      \arg        GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY
+      \arg        GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY
+    \param[out] none
+    \retval     none
+*/
+void gpio_ethernet_phy_select(uint32_t gpio_enetsel)
+{
+    /* clear AFIO_PCF0_ENET_PHY_SEL bit */
+    AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL);
+
+    /* select MII or RMII PHY */
+    AFIO_PCF0 |= (uint32_t)gpio_enetsel;
+}
+#endif

+ 714 - 0
Library/Source/gd32f10x_i2c.c

@@ -0,0 +1,714 @@
+/*!
+    \file    gd32f10x_i2c.c
+    \brief   I2C driver
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-04-16, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_i2c.h"
+
+/* I2C register bit mask */
+#define I2CCLK_MAX                    ((uint32_t)0x00000036U)             /*!< i2cclk maximum value */
+#define I2CCLK_MIN                    ((uint32_t)0x00000002U)             /*!< i2cclk minimum value */
+#define I2C_FLAG_MASK                 ((uint32_t)0x0000FFFFU)             /*!< i2c flag mask */
+#define I2C_ADDRESS_MASK              ((uint32_t)0x000003FFU)             /*!< i2c address mask */
+#define I2C_ADDRESS2_MASK             ((uint32_t)0x000000FEU)             /*!< the second i2c address mask */
+
+/* I2C register bit offset */
+#define STAT1_PECV_OFFSET             ((uint32_t)8U)     /* bit offset of PECV in I2C_STAT1 */
+
+/*!
+    \brief      reset I2C
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void i2c_deinit(uint32_t i2c_periph)
+{
+    switch(i2c_periph){
+    case I2C0:
+        /* reset I2C0 */
+        rcu_periph_reset_enable(RCU_I2C0RST);
+        rcu_periph_reset_disable(RCU_I2C0RST);
+        break;
+    case I2C1:
+        /* reset I2C1 */
+        rcu_periph_reset_enable(RCU_I2C1RST);
+        rcu_periph_reset_disable(RCU_I2C1RST);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure I2C clock
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
+    \param[in]  dutycyc: duty cycle in fast mode
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_DTCY_2: T_low/T_high=2 
+      \arg        I2C_DTCY_16_9: T_low/T_high=16/9
+    \param[out] none
+    \retval     none
+*/
+void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
+{
+    uint32_t pclk1, clkc, freq, risetime;
+    uint32_t temp;
+    
+    pclk1 = rcu_clock_freq_get(CK_APB1);
+    /* I2C peripheral clock frequency */
+    freq = (uint32_t)(pclk1/1000000U);
+    if(freq >= I2CCLK_MAX){
+        freq = I2CCLK_MAX;
+    }
+    temp = I2C_CTL1(i2c_periph);
+    temp &= ~I2C_CTL1_I2CCLK;
+    temp |= freq;
+    
+    I2C_CTL1(i2c_periph) = temp;
+    
+    if(100000U >= clkspeed){
+        /* the maximum SCL rise time is 1000ns in standard mode */
+        risetime = (uint32_t)((pclk1/1000000U)+1U);
+        if(risetime >= I2CCLK_MAX){
+            I2C_RT(i2c_periph) = I2CCLK_MAX;
+        }else if(risetime <= I2CCLK_MIN){
+            I2C_RT(i2c_periph) = I2CCLK_MIN;
+        }else{
+            I2C_RT(i2c_periph) = risetime;
+        }
+        clkc = (uint32_t)(pclk1/(clkspeed*2U)); 
+        if(clkc < 0x04U){
+            /* the CLKC in standard mode minmum value is 4 */
+            clkc = 0x04U;
+        }
+        I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
+
+    }else if(400000U >= clkspeed){
+        /* the maximum SCL rise time is 300ns in fast mode */
+        I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U);
+        if(I2C_DTCY_2 == dutycyc){
+            /* I2C duty cycle is 2 */
+            clkc = (uint32_t)(pclk1/(clkspeed*3U));
+            I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
+        }else{
+            /* I2C duty cycle is 16/9 */
+            clkc = (uint32_t)(pclk1/(clkspeed*25U));
+            I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
+        }
+        if(0U == (clkc & I2C_CKCFG_CLKC)){
+            /* the CLKC in fast mode minmum value is 1 */
+            clkc |= 0x0001U;  
+        }
+        I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
+        I2C_CKCFG(i2c_periph) |= clkc;
+    }else{
+    }
+}
+
+/*!
+    \brief      configure I2C address 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  mode:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_I2CMODE_ENABLE: I2C mode
+      \arg        I2C_SMBUSMODE_ENABLE: SMBus mode
+    \param[in]  addformat: 7bits or 10bits
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_ADDFORMAT_7BITS: 7bits
+      \arg        I2C_ADDFORMAT_10BITS: 10bits
+    \param[in]  addr: I2C address
+    \param[out] none
+    \retval     none
+*/
+void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
+{
+    /* SMBus/I2C mode selected */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_SMBEN); 
+    ctl |= mode;
+    I2C_CTL0(i2c_periph) = ctl;
+    /* configure address */
+    addr = addr & I2C_ADDRESS_MASK;
+    I2C_SADDR0(i2c_periph) = (addformat | addr);
+}
+
+/*!
+    \brief      SMBus type selection
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  type:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_SMBUS_DEVICE: device
+      \arg        I2C_SMBUS_HOST: host
+    \param[out] none
+    \retval     none
+*/
+void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
+{
+    if(I2C_SMBUS_HOST == type){
+        I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
+    }else{
+        I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
+    }
+}
+
+/*!
+    \brief      whether or not to send an ACK
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  ack:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_ACK_ENABLE: ACK will be sent
+      \arg        I2C_ACK_DISABLE: ACK will not be sent
+    \param[out] none
+    \retval     none
+*/
+void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
+{
+    if(I2C_ACK_ENABLE == ack){
+        I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN;
+    }else{
+        I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN);
+    }
+}
+
+/*!
+    \brief      configure I2C POAP position
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  pos:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_ACKPOS_CURRENT: whether to send ACK or not for the current
+      \arg        I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte
+    \param[out] none
+    \retval     none
+*/
+void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
+{
+    /* configure I2C POAP position */
+    if(I2C_ACKPOS_NEXT == pos){
+        I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP;
+    }else{
+        I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP);
+    }
+}
+
+/*!
+    \brief      master sends slave address
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  addr: slave address  
+    \param[in]  trandirection: transmitter or receiver
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_TRANSMITTER: transmitter  
+      \arg        I2C_RECEIVER:    receiver  
+    \param[out] none
+    \retval     none
+*/
+void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection)
+{
+    /* master is a transmitter or a receiver */
+    if(I2C_TRANSMITTER == trandirection){
+        addr = addr & I2C_TRANSMITTER;
+    }else{
+        addr = addr | I2C_RECEIVER;
+    }
+    /* send slave address */
+    I2C_DATA(i2c_periph) = addr;
+}
+
+/*!
+    \brief      enable dual-address mode
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  addr: the second address in dual-address mode
+    \param[out] none
+    \retval     none
+*/
+void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
+{
+    /* configure address */
+    addr = addr & I2C_ADDRESS2_MASK;
+    I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
+}
+
+/*!
+    \brief      disable dual-address mode
+    \param[in]  i2c_periph: I2Cx(x=0,1) 
+    \param[out] none
+    \retval     none
+*/
+void i2c_dualaddr_disable(uint32_t i2c_periph)
+{
+    I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
+}
+
+/*!
+    \brief      enable I2C
+    \param[in]  i2c_periph: I2Cx(x=0,1) 
+    \param[out] none
+    \retval     none
+*/
+void i2c_enable(uint32_t i2c_periph)
+{
+    I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
+}
+
+/*!
+    \brief      disable I2C
+    \param[in]  i2c_periph: I2Cx(x=0,1) 
+    \param[out] none
+    \retval     none
+*/
+void i2c_disable(uint32_t i2c_periph)
+{
+    I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
+}
+
+/*!
+    \brief      generate a START condition on I2C bus
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void i2c_start_on_bus(uint32_t i2c_periph)
+{
+    I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
+}
+
+/*!
+    \brief      generate a STOP condition on I2C bus
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[out] none
+    \retval     none
+*/
+void i2c_stop_on_bus(uint32_t i2c_periph)
+{
+    I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
+}
+
+/*!
+    \brief      I2C transmit data function
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  data: data of transmission 
+    \param[out] none
+    \retval     none
+*/
+void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
+{
+    I2C_DATA(i2c_periph) = DATA_TRANS(data);
+}
+
+/*!
+    \brief      I2C receive data function
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[out] none
+    \retval     data of received
+*/
+uint8_t i2c_data_receive(uint32_t i2c_periph)
+{
+    return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph));
+}
+
+/*!
+    \brief      enable I2C DMA mode 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  dmastate:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_DMA_ON: DMA mode enable
+      \arg        I2C_DMA_OFF: DMA mode disable
+    \param[out] none
+    \retval     none
+*/
+void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate)
+{
+    /* configure I2C DMA function */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL1(i2c_periph);
+    ctl &= ~(I2C_CTL1_DMAON); 
+    ctl |= dmastate;
+    I2C_CTL1(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      configure whether next DMA EOT is DMA last transfer or not
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  dmalast:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_DMALST_ON: next DMA EOT is the last transfer
+      \arg        I2C_DMALST_OFF: next DMA EOT is not the last transfer
+    \param[out] none
+    \retval     none
+*/
+void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
+{
+    /* configure DMA last transfer */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL1(i2c_periph);
+    ctl &= ~(I2C_CTL1_DMALST); 
+    ctl |= dmalast;
+    I2C_CTL1(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      whether to stretch SCL low when data is not ready in slave mode 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  stretchpara:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled
+      \arg        I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled
+    \param[out] none
+    \retval     none
+*/
+void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
+{
+    /* configure I2C SCL strerching enable or disable */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_SS); 
+    ctl |= stretchpara;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      whether or not to response to a general call 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  gcallpara:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_GCEN_ENABLE: slave will response to a general call
+      \arg        I2C_GCEN_DISABLE: slave will not response to a general call
+    \param[out] none
+    \retval     none
+*/
+void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
+{
+    /* configure slave response to a general call enable or disable */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_GCEN); 
+    ctl |= gcallpara;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      software reset I2C 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  sreset:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_SRESET_SET: I2C is under reset
+      \arg        I2C_SRESET_RESET: I2C is not under reset
+    \param[out] none
+    \retval     none
+*/
+void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
+{
+    /* modify CTL0 and configure software reset I2C state */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_SRESET); 
+    ctl |= sreset;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      I2C PEC calculation on or off
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  pecstate:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_PEC_ENABLE: PEC calculation on 
+      \arg        I2C_PEC_DISABLE: PEC calculation off 
+    \param[out] none
+    \retval     none
+*/
+void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate)
+{
+    /* on/off PEC calculation */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_PECEN);
+    ctl |= pecstate;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      I2C whether to transfer PEC value
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  pecpara:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_PECTRANS_ENABLE: transfer PEC 
+      \arg        I2C_PECTRANS_DISABLE: not transfer PEC 
+    \param[out] none
+    \retval     none
+*/
+void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara)
+{
+    /* whether to transfer PEC */
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_PECTRANS);
+    ctl |= pecpara;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      get packet error checking value 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[out] none
+    \retval     PEC value
+*/
+uint8_t i2c_pec_value_get(uint32_t i2c_periph)
+{
+    return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET);
+}
+
+/*!
+    \brief      I2C issue alert through SMBA pin 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  smbuspara:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_SALTSEND_ENABLE: issue alert through SMBA pin 
+      \arg        I2C_SALTSEND_DISABLE: not issue alert through SMBA pin 
+    \param[out] none
+    \retval     none
+*/
+void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara)
+{
+    /* issue alert through SMBA pin configure*/
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_SALT);
+    ctl |= smbuspara;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      enable or disable I2C ARP protocol in SMBus switch
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  arpstate:
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_ARP_ENABLE: enable ARP
+      \arg        I2C_ARP_DISABLE: disable ARP
+    \param[out] none
+    \retval     none
+*/
+void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate)
+{
+    /* enable or disable I2C ARP protocol*/
+    uint32_t ctl = 0U;
+    
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_ARPEN);
+    ctl |= arpstate;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \brief      check I2C flag is set or not
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  flag: I2C flags, refer to i2c_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_FLAG_SBSEND: start condition send out 
+      \arg        I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
+      \arg        I2C_FLAG_BTC: byte transmission finishes
+      \arg        I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
+      \arg        I2C_FLAG_STPDET: stop condition detected in slave mode
+      \arg        I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving
+      \arg        I2C_FLAG_TBE: I2C_DATA is empty during transmitting
+      \arg        I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
+      \arg        I2C_FLAG_LOSTARB: arbitration lost in master mode
+      \arg        I2C_FLAG_AERR: acknowledge error
+      \arg        I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode
+      \arg        I2C_FLAG_PECERR: PEC error when receiving data
+      \arg        I2C_FLAG_SMBTO: timeout signal in SMBus mode
+      \arg        I2C_FLAG_SMBALT: SMBus alert status
+      \arg        I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
+      \arg        I2C_FLAG_I2CBSY: busy flag
+      \arg        I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver
+      \arg        I2C_FLAG_RXGC: general call address (00h) received
+      \arg        I2C_FLAG_DEFSMB: default address of SMBus device
+      \arg        I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
+      \arg        I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
+{
+    if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear I2C flag
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  flag: I2C flags, refer to i2c_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg       I2C_FLAG_SMBALT: SMBus Alert status
+      \arg       I2C_FLAG_SMBTO: timeout signal in SMBus mode
+      \arg       I2C_FLAG_PECERR: PEC error when receiving data
+      \arg       I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode    
+      \arg       I2C_FLAG_AERR: acknowledge error
+      \arg       I2C_FLAG_LOSTARB: arbitration lost in master mode   
+      \arg       I2C_FLAG_BERR: a bus error   
+      \arg       I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1
+    \param[out] none
+    \retval     none
+*/
+void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
+{
+    if(I2C_FLAG_ADDSEND == flag){
+        /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
+        I2C_STAT0(i2c_periph);
+        I2C_STAT1(i2c_periph);
+    }else{
+        I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
+    }
+}
+
+/*!
+    \brief      enable I2C interrupt
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  interrupt: I2C interrupts, refer to i2c_interrupt_enum
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_INT_ERR: error interrupt enable 
+      \arg        I2C_INT_EV: event interrupt enable 
+      \arg        I2C_INT_BUF: buffer interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
+{
+    I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
+}
+
+/*!
+    \brief      disable I2C interrupt
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  interrupt: I2C interrupts, refer to i2c_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_INT_ERR: error interrupt enable 
+      \arg        I2C_INT_EV: event interrupt enable 
+      \arg        I2C_INT_BUF: buffer interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
+{
+    I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
+}
+
+/*!
+    \brief      check I2C interrupt flag
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
+      \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
+      \arg        I2C_INT_FLAG_BTC: byte transmission finishes
+      \arg        I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
+      \arg        I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag
+      \arg        I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
+      \arg        I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
+      \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
+      \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
+      \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
+      \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
+      \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
+      \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
+      \arg        I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
+{
+    uint32_t intenable = 0U, flagstatus = 0U, bufie;
+    
+    /* check BUFIE */
+    bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
+    
+    /* get the interrupt enable bit status */
+    intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
+    /* get the corresponding flag bit status */
+    flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
+
+    if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){
+        if(intenable && bufie){
+            intenable = 1U;                       
+        }else{
+            intenable = 0U;
+        }
+    }
+    if((0U != flagstatus) && (0U != intenable)){
+        return SET;
+    }else{
+        return RESET; 
+    }
+}
+
+/*!
+    \brief      clear I2C interrupt flag
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
+      \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
+      \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
+      \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
+      \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
+      \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
+      \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
+      \arg        I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
+{
+    if(I2C_INT_FLAG_ADDSEND == int_flag){
+        /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
+        I2C_STAT0(i2c_periph);
+        I2C_STAT1(i2c_periph);
+    }else{
+        I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
+    }
+}

+ 187 - 0
Library/Source/gd32f10x_misc.c

@@ -0,0 +1,187 @@
+/*!
+    \file    gd32f10x_misc.c
+    \brief   MISC driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_misc.h"
+
+/*!
+    \brief      set the priority group
+    \param[in]  nvic_prigroup: the NVIC priority group
+      \arg        NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority
+      \arg        NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority
+      \arg        NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority
+      \arg        NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority
+      \arg        NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority
+    \param[out] none
+    \retval     none
+*/
+void nvic_priority_group_set(uint32_t nvic_prigroup)
+{
+    /* set the priority group value */
+    SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup;
+}
+
+/*!
+    \brief      enable NVIC request
+    \param[in]  nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
+    \param[in]  nvic_irq_pre_priority: the pre-emption priority needed to set
+    \param[in]  nvic_irq_sub_priority: the subpriority needed to set
+    \param[out] none
+    \retval     none
+*/
+void nvic_irq_enable(uint8_t nvic_irq, 
+                     uint8_t nvic_irq_pre_priority, 
+                     uint8_t nvic_irq_sub_priority)
+{
+    uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U;
+
+    /* use the priority group value to get the temp_pre and the temp_sub */
+    switch ((SCB->AIRCR) & (uint32_t)0x700U) {
+    case NVIC_PRIGROUP_PRE0_SUB4:
+        temp_pre = 0U;
+        temp_sub = 0x4U;
+        break;
+    case NVIC_PRIGROUP_PRE1_SUB3:
+        temp_pre = 1U;
+        temp_sub = 0x3U;
+        break;
+    case NVIC_PRIGROUP_PRE2_SUB2:
+        temp_pre = 2U;
+        temp_sub = 0x2U;
+        break;
+    case NVIC_PRIGROUP_PRE3_SUB1:
+        temp_pre = 3U;
+        temp_sub = 0x1U;
+        break;
+    case NVIC_PRIGROUP_PRE4_SUB0:
+        temp_pre = 4U;
+        temp_sub = 0x0U;
+        break;
+    default:
+        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
+        temp_pre = 2U;
+        temp_sub = 0x2U;
+        break;
+    }
+
+    /* get the temp_priority to fill the NVIC->IP register */
+    temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre);
+    temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub));
+    temp_priority = temp_priority << 0x04U;
+    NVIC->IP[nvic_irq] = (uint8_t)temp_priority;
+
+    /* enable the selected IRQ */
+    NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
+}
+
+/*!
+    \brief      disable NVIC request
+    \param[in]  nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
+    \param[out] none
+    \retval     none
+*/
+void nvic_irq_disable(uint8_t nvic_irq)
+{
+    /* disable the selected IRQ.*/
+    NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
+}
+
+/*!
+    \brief      set the NVIC vector table base address
+    \param[in]  nvic_vict_tab: the RAM or FLASH base address
+      \arg        NVIC_VECTTAB_RAM: RAM base address
+      \are        NVIC_VECTTAB_FLASH: Flash base address
+    \param[in]  offset: Vector Table offset
+    \param[out] none
+    \retval     none
+*/
+void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset)
+{
+    SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
+    __DSB();
+}
+
+/*!
+    \brief      set the state of the low power mode
+    \param[in]  lowpower_mode: the low power mode state
+      \arg        SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power 
+                    mode by exiting from ISR
+      \arg        SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode
+      \arg        SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up 
+                    by all the enable and disable interrupts
+    \param[out] none
+    \retval     none
+*/
+void system_lowpower_set(uint8_t lowpower_mode)
+{
+    SCB->SCR |= (uint32_t)lowpower_mode;
+}
+
+/*!
+    \brief      reset the state of the low power mode
+    \param[in]  lowpower_mode: the low power mode state
+      \arg        SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power 
+                    mode by exiting from ISR
+      \arg        SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode
+      \arg        SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be 
+                    woke up by the enable interrupts
+    \param[out] none
+    \retval     none
+*/
+void system_lowpower_reset(uint8_t lowpower_mode)
+{
+    SCB->SCR &= (~(uint32_t)lowpower_mode);
+}
+
+/*!
+    \brief      set the systick clock source
+    \param[in]  systick_clksource: the systick clock source needed to choose
+      \arg        SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK
+      \arg        SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8
+    \param[out] none
+    \retval     none
+*/
+
+void systick_clksource_set(uint32_t systick_clksource)
+{
+    if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){
+        /* set the systick clock source from HCLK */
+        SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
+    }else{
+        /* set the systick clock source from HCLK/8 */
+        SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8;
+    }
+}

+ 282 - 0
Library/Source/gd32f10x_pmu.c

@@ -0,0 +1,282 @@
+/*!
+    \file    gd32f10x_pmu.c
+    \brief   PMU driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2019-11-26, V2.1.1, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_pmu.h"
+
+/*!
+    \brief      reset PMU register
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_deinit(void)
+{
+    /* reset PMU */
+    rcu_periph_reset_enable(RCU_PMURST);
+    rcu_periph_reset_disable(RCU_PMURST);
+}
+
+/*!
+    \brief      select low voltage detector threshold
+    \param[in]  lvdt_n:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_LVDT_0: voltage threshold is 2.2V
+      \arg        PMU_LVDT_1: voltage threshold is 2.3V
+      \arg        PMU_LVDT_2: voltage threshold is 2.4V
+      \arg        PMU_LVDT_3: voltage threshold is 2.5V
+      \arg        PMU_LVDT_4: voltage threshold is 2.6V
+      \arg        PMU_LVDT_5: voltage threshold is 2.7V
+      \arg        PMU_LVDT_6: voltage threshold is 2.8V
+      \arg        PMU_LVDT_7: voltage threshold is 2.9V
+    \param[out] none
+    \retval     none
+*/
+void pmu_lvd_select(uint32_t lvdt_n)
+{
+    /* disable LVD */
+    PMU_CTL &= ~PMU_CTL_LVDEN;
+    /* clear LVDT bits */
+    PMU_CTL &= ~PMU_CTL_LVDT;
+    /* set LVDT bits according to lvdt_n */
+    PMU_CTL |= lvdt_n;
+    /* enable LVD */
+    PMU_CTL |= PMU_CTL_LVDEN;
+}
+
+/*!
+    \brief      disable PMU lvd
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_lvd_disable(void)
+{
+    /* disable LVD */
+    PMU_CTL &= ~PMU_CTL_LVDEN;
+}
+
+/*!
+    \brief      PMU work at sleep mode
+    \param[in]  sleepmodecmd:
+                only one parameter can be selected which is shown as below:
+      \arg        WFI_CMD: use WFI command
+      \arg        WFE_CMD: use WFE command
+    \param[out] none
+    \retval     none
+*/
+void pmu_to_sleepmode(uint8_t sleepmodecmd)
+{
+    /* clear sleepdeep bit of Cortex-M3 system control register */
+    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
+    
+    /* select WFI or WFE command to enter sleep mode */
+    if(WFI_CMD == sleepmodecmd){
+        __WFI();
+    }else{
+        __WFE();
+    }
+}
+
+/*!
+    \brief      PMU work at deepsleep mode
+    \param[in]  ldo:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode
+      \arg        PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode
+    \param[in]  deepsleepmodecmd:
+                only one parameter can be selected which is shown as below: 
+      \arg        WFI_CMD: use WFI command
+      \arg        WFE_CMD: use WFE command
+    \param[out] none
+    \retval     none
+*/
+void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
+{
+    static uint32_t reg_snap[ 4 ];   
+    /* clear stbmod and ldolp bits */
+    PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
+    
+    /* set ldolp bit according to pmu_ldo */
+    PMU_CTL |= ldo;
+    
+    /* set sleepdeep bit of Cortex-M3 system control register */
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    reg_snap[0] = REG32(0xE000E010U);
+    reg_snap[1] = REG32(0xE000E100U);
+    reg_snap[2] = REG32(0xE000E104U);
+    reg_snap[3] = REG32(0xE000E108U);
+    
+    REG32( 0xE000E010U ) &= 0x00010004U;
+    REG32( 0xE000E180U )  = 0XFF7FF83DU;
+    REG32( 0xE000E184U )  = 0XBFFFF8FFU;
+    REG32( 0xE000E188U )  = 0xFFFFFFFFU;
+    
+    /* select WFI or WFE command to enter deepsleep mode */
+    if(WFI_CMD == deepsleepmodecmd){
+        __WFI();
+    }else{
+        __SEV();
+        __WFE();
+        __WFE();
+    }
+
+    REG32(0xE000E010U) = reg_snap[0] ; 
+    REG32(0xE000E100U) = reg_snap[1] ;
+    REG32(0xE000E104U) = reg_snap[2] ;
+    REG32(0xE000E108U) = reg_snap[3] ;  
+
+    /* reset sleepdeep bit of Cortex-M3 system control register */
+    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
+}
+
+/*!
+    \brief      pmu work at standby mode
+    \param[in]  standbymodecmd:
+                only one parameter can be selected which is shown as below:
+      \arg        WFI_CMD: use WFI command
+      \arg        WFE_CMD: use WFE command
+    \param[out] none
+    \retval     none
+*/
+void pmu_to_standbymode(uint8_t standbymodecmd)
+{
+    /* set sleepdeep bit of Cortex-M3 system control register */
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    /* set stbmod bit */
+    PMU_CTL |= PMU_CTL_STBMOD;
+        
+    /* reset wakeup flag */
+    PMU_CTL |= PMU_CTL_WURST;
+    
+    /* select WFI or WFE command to enter standby mode */
+    if(WFI_CMD == standbymodecmd){
+        __WFI();
+    }else{
+        __WFE();
+    }
+}
+
+/*!
+    \brief      enable wakeup pin
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_wakeup_pin_enable(void)
+{
+    PMU_CS |= PMU_CS_WUPEN;
+}
+
+/*!
+    \brief      disable wakeup pin
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_wakeup_pin_disable(void)
+{
+    PMU_CS &= ~PMU_CS_WUPEN;
+}
+
+/*!
+    \brief      enable write access to the registers in backup domain
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_backup_write_enable(void)
+{
+    PMU_CTL |= PMU_CTL_BKPWEN;
+}
+
+/*!
+    \brief      disable write access to the registers in backup domain
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_backup_write_disable(void)
+{
+    PMU_CTL &= ~PMU_CTL_BKPWEN;
+}
+
+/*!
+    \brief      get flag state
+    \param[in]  flag:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_FLAG_WAKEUP: wakeup flag
+      \arg        PMU_FLAG_STANDBY: standby flag
+      \arg        PMU_FLAG_LVD: lvd flag
+    \param[out] none
+    \retval     FlagStatus SET or RESET
+*/
+FlagStatus pmu_flag_get(uint32_t flag)
+{
+    if(PMU_CS & flag){
+        return  SET;
+    }else{
+        return  RESET;
+    }
+}
+
+/*!
+    \brief      clear flag bit
+    \param[in]  flag_reset:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_FLAG_RESET_WAKEUP: reset wakeup flag
+      \arg        PMU_FLAG_RESET_STANDBY: reset standby flag
+    \param[out] none
+    \retval     none
+*/
+void pmu_flag_clear(uint32_t flag_reset)
+{
+    switch(flag_reset){
+    case PMU_FLAG_RESET_WAKEUP:
+        /* reset wakeup flag */
+        PMU_CTL |= PMU_CTL_WURST;
+        break;
+    case PMU_FLAG_RESET_STANDBY:
+        /* reset standby flag */
+        PMU_CTL |= PMU_CTL_STBRST;
+        break;
+    default :
+        break;
+    }
+}

+ 1195 - 0
Library/Source/gd32f10x_rcu.c

@@ -0,0 +1,1195 @@
+/*!
+    \file    gd32f10x_rcu.c
+    \brief   RCU driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_rcu.h"
+
+/* define clock source */
+#define SEL_IRC8M                   ((uint16_t)0U)
+#define SEL_HXTAL                   ((uint16_t)1U)
+#define SEL_PLL                     ((uint16_t)2U)
+
+/* define startup timeout count */
+#define OSC_STARTUP_TIMEOUT         ((uint32_t)0xFFFFFU)
+#define LXTAL_STARTUP_TIMEOUT       ((uint32_t)0x3FFFFFFU)
+
+/*!
+    \brief      deinitialize the RCU
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rcu_deinit(void)
+{
+    /* enable IRC8M */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+    rcu_osci_stab_wait(RCU_IRC8M);
+
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+
+    /* reset CTL register */
+    RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
+    RCU_CTL &= ~RCU_CTL_HXTALBPS;
+#ifdef GD32F10X_CL
+    RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN);
+#endif /* GD32F10X_CL */
+
+    /* reset CFG0 register */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
+                  RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF |
+                  RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2);
+#elif defined(GD32F10X_CL)
+    RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
+                  RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
+                  RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4);
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    /* reset INT and CFG1 register */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    RCU_INT = 0x009f0000U;
+#elif defined(GD32F10X_CL)
+    RCU_INT = 0x00ff0000U;
+    RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
+                  RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL);
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+}
+
+/*!
+    \brief      enable the peripherals clock
+    \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock
+      \arg        RCU_AF : alternate function clock
+      \arg        RCU_CRC: CRC clock
+      \arg        RCU_DMAx (x=0,1): DMA clock
+      \arg        RCU_ENET: ENET clock(CL series available)
+      \arg        RCU_ENETTX: ENETTX clock(CL series available)
+      \arg        RCU_ENETRX: ENETRX clock(CL series available)
+      \arg        RCU_USBD: USBD clock(HD,XD series available)
+      \arg        RCU_USBFS: USBFS clock(CL series available)
+      \arg        RCU_EXMC: EXMC clock
+      \arg        RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock
+      \arg        RCU_WWDGT: WWDGT clock
+      \arg        RCU_SPIx (x=0,1,2): SPI clock
+      \arg        RCU_USARTx (x=0,1,2): USART clock
+      \arg        RCU_UARTx (x=3,4): UART clock
+      \arg        RCU_I2Cx (x=0,1): I2C clock
+      \arg        RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock
+      \arg        RCU_PMU: PMU clock
+      \arg        RCU_DAC: DAC clock
+      \arg        RCU_RTC: RTC clock
+      \arg        RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock
+      \arg        RCU_SDIO: SDIO clock(not available for CL series)
+      \arg        RCU_BKPI: BKP interface clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_clock_enable(rcu_periph_enum periph)
+{
+    RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
+}
+
+/*!
+    \brief      disable the peripherals clock
+    \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock
+      \arg        RCU_AF: alternate function clock
+      \arg        RCU_CRC: CRC clock
+      \arg        RCU_DMAx (x=0,1): DMA clock
+      \arg        RCU_ENET: ENET clock(CL series available)
+      \arg        RCU_ENETTX: ENETTX clock(CL series available)
+      \arg        RCU_ENETRX: ENETRX clock(CL series available)
+      \arg        RCU_USBD: USBD clock(HD,XD series available)
+      \arg        RCU_USBFS: USBFS clock(CL series available)
+      \arg        RCU_EXMC: EXMC clock
+      \arg        RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock
+      \arg        RCU_WWDGT: WWDGT clock
+      \arg        RCU_SPIx (x=0,1,2): SPI clock
+      \arg        RCU_USARTx (x=0,1,2): USART clock
+      \arg        RCU_UARTx (x=3,4): UART clock
+      \arg        RCU_I2Cx (x=0,1): I2C clock
+      \arg        RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock
+      \arg        RCU_PMU: PMU clock
+      \arg        RCU_DAC: DAC clock
+      \arg        RCU_RTC: RTC clock
+      \arg        RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock
+      \arg        RCU_SDIO: SDIO clock(not available for CL series)
+      \arg        RCU_BKPI: BKP interface clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_clock_disable(rcu_periph_enum periph)
+{
+    RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
+}
+
+/*!
+    \brief      enable the peripherals clock when sleep mode
+    \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_FMC_SLP: FMC clock
+      \arg        RCU_SRAM_SLP: SRAM clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
+{
+    RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
+}
+
+/*!
+    \brief      disable the peripherals clock when sleep mode
+    \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_FMC_SLP: FMC clock
+      \arg        RCU_SRAM_SLP: SRAM clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
+{
+    RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
+}
+
+/*!
+    \brief      reset the peripherals
+    \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports
+      \arg        RCU_AFRST : reset alternate function clock
+      \arg        RCU_ENETRST: reset ENET(CL series available)
+      \arg        RCU_USBDRST: reset USBD(HD,XD series available)
+      \arg        RCU_USBFSRST: reset USBFS(CL series available)
+      \arg        RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER
+      \arg        RCU_WWDGTRST: reset WWDGT
+      \arg        RCU_SPIxRST (x=0,1,2): reset SPI
+      \arg        RCU_USARTxRST (x=0,1,2): reset USART
+      \arg        RCU_UARTxRST (x=3,4): reset UART
+      \arg        RCU_I2CxRST (x=0,1): reset I2C
+      \arg        RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN
+      \arg        RCU_PMURST: reset PMU
+      \arg        RCU_DACRST: reset DAC
+      \arg        RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC
+      \arg        RCU_BKPIRST: reset BKPI
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
+{
+    RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
+}
+
+/*!
+    \brief      disable reset the peripheral
+    \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports
+      \arg        RCU_AFRST : reset alternate function clock
+      \arg        RCU_ENETRST: reset ENET(CL series available)
+      \arg        RCU_USBDRST: reset USBD(HD,XD series available)
+      \arg        RCU_USBFSRST: reset USBFS(CL series available)
+      \arg        RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER
+      \arg        RCU_WWDGTRST: reset WWDGT
+      \arg        RCU_SPIxRST (x=0,1,2): reset SPI
+      \arg        RCU_USARTxRST (x=0,1,2): reset USART
+      \arg        RCU_UARTxRST (x=3,4): reset UART
+      \arg        RCU_I2CxRST (x=0,1): reset I2C
+      \arg        RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN
+      \arg        RCU_PMURST: reset PMU
+      \arg        RCU_DACRST: reset DAC
+      \arg        RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC
+      \arg        RCU_BKPIRST: reset BKPI
+    \param[out] none
+    \retval     none
+*/
+void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
+{
+    RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
+}
+
+/*!
+    \brief      reset the BKP domain
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rcu_bkp_reset_enable(void)
+{
+    RCU_BDCTL |= RCU_BDCTL_BKPRST;
+}
+
+/*!
+    \brief      disable the BKP domain reset
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rcu_bkp_reset_disable(void)
+{
+    RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
+}
+
+/*!
+    \brief      configure the system clock source
+    \param[in]  ck_sys: system clock source select
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
+      \arg        RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
+      \arg        RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
+    \param[out] none
+    \retval     none
+*/
+void rcu_system_clock_source_config(uint32_t ck_sys)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+    /* reset the SCS bits and set according to ck_sys */
+    reg &= ~RCU_CFG0_SCS;
+    RCU_CFG0 = (reg | ck_sys);
+}
+
+/*!
+    \brief      get the system clock source
+    \param[in]  none
+    \param[out] none
+    \retval     which clock is selected as CK_SYS source
+      \arg        RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source
+      \arg        RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
+      \arg        RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source
+*/
+uint32_t rcu_system_clock_source_get(void)
+{
+    return (RCU_CFG0 & RCU_CFG0_SCSS);
+}
+
+/*!
+    \brief      configure the AHB clock prescaler selection
+    \param[in]  ck_ahb: AHB clock prescaler selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
+    \param[out] none
+    \retval     none
+*/
+void rcu_ahb_clock_config(uint32_t ck_ahb)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+
+    /* reset the AHBPSC bits and set according to ck_ahb */
+    reg &= ~RCU_CFG0_AHBPSC;
+    RCU_CFG0 = (reg | ck_ahb);
+}
+
+/*!
+    \brief      configure the APB1 clock prescaler selection
+    \param[in]  ck_apb1: APB1 clock prescaler selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
+      \arg        RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
+      \arg        RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
+      \arg        RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
+      \arg        RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
+    \param[out] none
+    \retval     none
+*/
+void rcu_apb1_clock_config(uint32_t ck_apb1)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+
+    /* reset the APB1PSC and set according to ck_apb1 */
+    reg &= ~RCU_CFG0_APB1PSC;
+    RCU_CFG0 = (reg | ck_apb1);
+}
+
+/*!
+    \brief      configure the APB2 clock prescaler selection
+    \param[in]  ck_apb2: APB2 clock prescaler selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
+      \arg        RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
+      \arg        RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
+      \arg        RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
+      \arg        RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
+    \param[out] none
+    \retval     none
+*/
+void rcu_apb2_clock_config(uint32_t ck_apb2)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+
+    /* reset the APB2PSC and set according to ck_apb2 */
+    reg &= ~RCU_CFG0_APB2PSC;
+    RCU_CFG0 = (reg | ck_apb2);
+}
+
+/*!
+    \brief      configure the CK_OUT0 clock source
+    \param[in]  ckout0_src: CK_OUT0 clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_CKOUT0SRC_NONE: no clock selected
+      \arg        RCU_CKOUT0SRC_CKSYS: system clock selected
+      \arg        RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected
+      \arg        RCU_CKOUT0SRC_HXTAL: HXTAL selected
+      \arg        RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected
+      \arg        RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected
+      \arg        RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected
+      \arg        RCU_CKOUT0SRC_EXT1: EXT1 selected
+      \arg        RCU_CKOUT0SRC_CKPLL2: PLL2 selected
+    \param[out] none
+    \retval     none
+*/
+void rcu_ckout0_config(uint32_t ckout0_src)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+
+    /* reset the CKOUT0SRC, set according to ckout0_src */
+    reg &= ~RCU_CFG0_CKOUT0SEL;
+    RCU_CFG0 = (reg | ckout0_src);
+}
+
+/*!
+    \brief      configure the main PLL clock 
+    \param[in]  pll_src: PLL clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL
+      \arg        RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL
+    \param[in]  pll_mul: PLL clock multiplication factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PLL_MULx (XD series x = 2..32, CL series x = 2..14, 6.5, 16..32)
+    \param[out] none
+    \retval     none
+*/
+void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
+{
+    uint32_t reg = 0U;
+
+    reg = RCU_CFG0;
+
+    /* PLL clock source and multiplication factor configuration */
+    reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
+    reg |= (pll_src | pll_mul);
+
+    RCU_CFG0 = reg;
+}
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+/*!
+    \brief      configure the PREDV0 division factor
+    \param[in]  predv0_div: PREDV0 division factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PREDV0_DIVx, x = 1,2
+    \param[out] none
+    \retval     none
+*/
+void rcu_predv0_config(uint32_t predv0_div)
+{
+    uint32_t reg = 0U;
+
+    reg = RCU_CFG0;
+    /* reset PREDV0 bit */
+    reg &= ~RCU_CFG0_PREDV0;
+    if(RCU_PREDV0_DIV2 == predv0_div){
+        /* set the PREDV0 bit */
+        reg |= RCU_CFG0_PREDV0;
+    }
+
+    RCU_CFG0 = reg;
+}
+#elif defined(GD32F10X_CL)
+/*!
+    \brief      configure the PREDV0 division factor and clock source
+    \param[in]  predv0_source: PREDV0 input clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock
+      \arg        RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock
+    \param[in]  predv0_div: PREDV0 division factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PREDV0_DIVx, x = 1..16
+    \param[out] none
+    \retval     none
+*/
+void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div)
+{
+    uint32_t reg = 0U;
+    
+    reg = RCU_CFG1;
+    /* reset PREDV0SEL and PREDV0 bits */
+    reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0);
+    /* set the PREDV0SEL and PREDV0 division factor */
+    reg |= (predv0_source | predv0_div);
+
+    RCU_CFG1 = reg;
+}
+
+/*!
+    \brief      configure the PREDV1 division factor
+    \param[in]  predv1_div: PREDV1 division factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PREDV1_DIVx, x = 1..16
+    \param[out] none
+    \retval     none
+*/
+void rcu_predv1_config(uint32_t predv1_div)
+{
+    uint32_t reg = 0U;
+    
+    reg = RCU_CFG1;
+    /* reset the PREDV1 bits */
+    reg &= ~RCU_CFG1_PREDV1;
+    /* set the PREDV1 division factor */
+    reg |= predv1_div;
+
+    RCU_CFG1 = reg;
+}
+
+/*!
+    \brief      configure the PLL1 clock 
+    \param[in]  pll_mul: PLL clock multiplication factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PLL1_MULx (x = 8..16, 20)
+    \param[out] none
+    \retval     none
+*/
+void rcu_pll1_config(uint32_t pll_mul)
+{
+    RCU_CFG1 &= ~RCU_CFG1_PLL1MF;
+    RCU_CFG1 |= pll_mul;
+}
+
+/*!
+    \brief      configure the PLL2 clock 
+    \param[in]  pll_mul: PLL clock multiplication factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_PLL2_MULx (x = 8..16, 20)
+    \param[out] none
+    \retval     none
+*/
+void rcu_pll2_config(uint32_t pll_mul)
+{
+    RCU_CFG1 &= ~RCU_CFG1_PLL2MF;
+    RCU_CFG1 |= pll_mul; 
+}
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+/*!
+    \brief      configure the ADC prescaler factor
+    \param[in]  adc_psc: ADC prescaler factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2
+      \arg        RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4
+      \arg        RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6
+      \arg        RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8
+      \arg        RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12
+      \arg        RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16
+    \param[out] none
+    \retval     none
+*/
+void rcu_adc_clock_config(uint32_t adc_psc)
+{
+    uint32_t reg0;
+
+    /* reset the ADCPSC bits */
+    reg0 = RCU_CFG0;
+    reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC);
+
+    /* set the ADC prescaler factor */
+    switch(adc_psc){
+        case RCU_CKADC_CKAPB2_DIV2:
+        case RCU_CKADC_CKAPB2_DIV4:
+        case RCU_CKADC_CKAPB2_DIV6:
+        case RCU_CKADC_CKAPB2_DIV8:
+            reg0 |= (adc_psc << 14);
+            break;
+
+        case RCU_CKADC_CKAPB2_DIV12:
+        case RCU_CKADC_CKAPB2_DIV16:
+            adc_psc &= ~BIT(2);
+            reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2);
+            break;
+
+        default:
+            break;
+    }
+
+    /* set the register */
+    RCU_CFG0 = reg0;
+}
+
+/*!
+    \brief      configure the USBD/USBFS prescaler factor
+    \param[in]  usb_psc: USB prescaler factor
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5
+      \arg        RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1
+      \arg        RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5
+      \arg        RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2
+    \param[out] none
+    \retval     none
+*/
+void rcu_usb_clock_config(uint32_t usb_psc)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG0;
+
+    /* configure the USBD/USBFS prescaler factor */
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+    reg &= ~RCU_CFG0_USBDPSC;
+#elif defined(GD32F10X_CL)
+    reg &= ~RCU_CFG0_USBFSPSC;
+#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */
+
+    RCU_CFG0 = (reg | usb_psc);
+}
+
+/*!
+    \brief      configure the RTC clock source selection
+    \param[in]  rtc_clock_source: RTC clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_RTCSRC_NONE: no clock selected
+      \arg        RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
+      \arg        RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
+      \arg        RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_rtc_clock_config(uint32_t rtc_clock_source)
+{
+    uint32_t reg;
+    
+    reg = RCU_BDCTL; 
+    /* reset the RTCSRC bits and set according to rtc_clock_source */
+    reg &= ~RCU_BDCTL_RTCSRC;
+    RCU_BDCTL = (reg | rtc_clock_source);
+}
+
+#ifdef GD32F10X_CL
+/*!
+    \brief      configure the I2S1 clock source selection
+    \param[in]  i2s_clock_source: I2S1 clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock
+      \arg        RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_i2s1_clock_config(uint32_t i2s_clock_source)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG1; 
+    /* reset the I2S1SEL bit and set according to i2s_clock_source */
+    reg &= ~RCU_CFG1_I2S1SEL;
+    RCU_CFG1 = (reg | i2s_clock_source);
+}
+
+/*!
+    \brief      configure the I2S2 clock source selection
+    \param[in]  i2s_clock_source: I2S2 clock source selection
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock
+      \arg        RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock
+    \param[out] none
+    \retval     none
+*/
+void rcu_i2s2_clock_config(uint32_t i2s_clock_source)
+{
+    uint32_t reg;
+    
+    reg = RCU_CFG1; 
+    /* reset the I2S2SEL bit and set according to i2s_clock_source */
+    reg &= ~RCU_CFG1_I2S2SEL;
+    RCU_CFG1 = (reg | i2s_clock_source);
+}
+#endif /* GD32F10X_CL */
+
+/*!
+    \brief      get the clock stabilization and periphral reset flags
+    \param[in]  flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
+      \arg        RCU_FLAG_HXTALSTB: HXTAL stabilization flag
+      \arg        RCU_FLAG_PLLSTB: PLL stabilization flag
+      \arg        RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only)
+      \arg        RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only)
+      \arg        RCU_FLAG_LXTALSTB: LXTAL stabilization flag
+      \arg        RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
+      \arg        RCU_FLAG_EPRST: external PIN reset flag
+      \arg        RCU_FLAG_PORRST: power reset flag
+      \arg        RCU_FLAG_SWRST: software reset flag
+      \arg        RCU_FLAG_FWDGTRST: free watchdog timer reset flag
+      \arg        RCU_FLAG_WWDGTRST: window watchdog timer reset flag
+      \arg        RCU_FLAG_LPRST: low-power reset flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus rcu_flag_get(rcu_flag_enum flag)
+{
+    /* get the rcu flag */
+    if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear all the reset flag
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rcu_all_reset_flag_clear(void)
+{
+    RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
+}
+
+/*!
+    \brief      get the clock stabilization interrupt and ckm flags
+    \param[in]  int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
+      \arg        RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
+      \arg        RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
+      \arg        RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
+      \arg        RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
+      \arg        RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only)
+      \arg        RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only)
+      \arg        RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
+{
+    /* get the rcu interrupt flag */
+    if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear the interrupt flags
+    \param[in]  int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
+      \arg        RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
+      \arg        RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
+      \arg        RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
+      \arg        RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
+      \arg        RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only)
+      \arg        RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only)
+      \arg        RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
+    \param[out] none
+    \retval     none
+*/
+void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
+{
+    RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
+}
+
+/*!
+    \brief      enable the stabilization interrupt
+    \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
+                Only one parameter can be selected which is shown as below:
+      \arg        RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
+      \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
+      \arg        RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
+      \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
+      \arg        RCU_INT_PLLSTB: PLL stabilization interrupt enable
+      \arg        RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only)
+      \arg        RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only)
+    \param[out] none
+    \retval     none
+*/
+void rcu_interrupt_enable(rcu_int_enum stab_int)
+{
+    RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
+}
+
+/*!
+    \brief      disable the stabilization interrupt
+    \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
+      \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
+      \arg        RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
+      \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
+      \arg        RCU_INT_PLLSTB: PLL stabilization interrupt enable
+      \arg        RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only)
+      \arg        RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only)
+    \param[out] none
+    \retval     none
+*/
+void rcu_interrupt_disable(rcu_int_enum stab_int)
+{
+    RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
+}
+
+/*!
+    \brief      wait for oscillator stabilization flags is SET or oscillator startup is timeout
+    \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
+      \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
+      \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
+      \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
+      \arg        RCU_PLL_CK: phase locked loop(PLL)
+      \arg        RCU_PLL1_CK: phase locked loop 1(CL series only)
+      \arg        RCU_PLL2_CK: phase locked loop 2(CL series only)
+    \param[out] none
+    \retval     ErrStatus: SUCCESS or ERROR
+*/
+ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
+{
+    uint32_t stb_cnt = 0U;
+    ErrStatus reval = ERROR;
+    FlagStatus osci_stat = RESET;
+    
+    switch(osci){
+    /* wait HXTAL stable */
+    case RCU_HXTAL:
+        while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
+            reval = SUCCESS;
+        }
+        break;
+
+    /* wait LXTAL stable */
+    case RCU_LXTAL:
+        while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
+            reval = SUCCESS;
+        }
+        break;
+
+    /* wait IRC8M stable */
+    case RCU_IRC8M:
+        while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
+            reval = SUCCESS;
+        }
+        break;
+
+    /* wait IRC40K stable */
+    case RCU_IRC40K:
+        while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
+            reval = SUCCESS;
+        }
+        break;
+
+    /* wait PLL stable */
+    case RCU_PLL_CK:
+        while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
+            reval = SUCCESS;
+        }
+        break;
+
+#ifdef GD32F10X_CL
+    /* wait PLL1 stable */
+    case RCU_PLL1_CK:
+        while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){
+            reval = SUCCESS;
+        }
+        break;
+    /* wait PLL2 stable */
+    case RCU_PLL2_CK:
+        while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
+            osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB);
+            stb_cnt++;
+        }
+
+        /* check whether flag is set or not */
+        if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){
+            reval = SUCCESS;
+        }
+        break;
+#endif /* GD32F10X_CL */
+
+    default:
+        break;
+    }
+
+    /* return value */
+    return reval;
+}
+
+/*!
+    \brief      turn on the oscillator
+    \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
+      \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
+      \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
+      \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
+      \arg        RCU_PLL_CK: phase locked loop(PLL)
+      \arg        RCU_PLL1_CK: phase locked loop 1(CL series only)
+      \arg        RCU_PLL2_CK: phase locked loop 2(CL series only)
+    \param[out] none
+    \retval     none
+*/
+void rcu_osci_on(rcu_osci_type_enum osci)
+{
+    RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
+}
+
+/*!
+    \brief      turn off the oscillator
+    \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
+      \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
+      \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
+      \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
+      \arg        RCU_PLL_CK: phase locked loop(PLL)
+      \arg        RCU_PLL1_CK: phase locked loop 1(CL series only)
+      \arg        RCU_PLL2_CK: phase locked loop 2(CL series only)
+    \param[out] none
+    \retval     none
+*/
+void rcu_osci_off(rcu_osci_type_enum osci)
+{
+    RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
+}
+
+/*!
+    \brief      enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
+    \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
+      \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
+    \param[out] none
+    \retval     none
+*/
+void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
+{
+    uint32_t reg;
+
+    switch(osci){
+    /* enable HXTAL to bypass mode */
+    case RCU_HXTAL:
+        reg = RCU_CTL;
+        RCU_CTL &= ~RCU_CTL_HXTALEN;
+        RCU_CTL = (reg | RCU_CTL_HXTALBPS);
+        break;
+    /* enable LXTAL to bypass mode */
+    case RCU_LXTAL:
+        reg = RCU_BDCTL;
+        RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
+        RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
+        break;
+    case RCU_IRC8M:
+    case RCU_IRC40K:
+    case RCU_PLL_CK:
+#ifdef GD32F10X_CL
+    case RCU_PLL1_CK:
+    case RCU_PLL2_CK:
+#endif /* GD32F10X_CL */
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
+    \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
+      \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
+    \param[out] none
+    \retval     none
+*/
+void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
+{
+    uint32_t reg;
+    
+    switch(osci){
+    /* disable HXTAL to bypass mode */
+    case RCU_HXTAL:
+        reg = RCU_CTL;
+        RCU_CTL &= ~RCU_CTL_HXTALEN;
+        RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
+        break;
+    /* disable LXTAL to bypass mode */
+    case RCU_LXTAL:
+        reg = RCU_BDCTL;
+        RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
+        RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
+        break;
+    case RCU_IRC8M:
+    case RCU_IRC40K:
+    case RCU_PLL_CK:
+#ifdef GD32F10X_CL
+    case RCU_PLL1_CK:
+    case RCU_PLL2_CK:
+#endif /* GD32F10X_CL */
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      enable the HXTAL clock monitor
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+
+void rcu_hxtal_clock_monitor_enable(void)
+{
+    RCU_CTL |= RCU_CTL_CKMEN;
+}
+
+/*!
+    \brief      disable the HXTAL clock monitor
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rcu_hxtal_clock_monitor_disable(void)
+{
+    RCU_CTL &= ~RCU_CTL_CKMEN;
+}
+
+/*!
+    \brief      set the IRC8M adjust value
+    \param[in]  irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
+    \param[out] none
+    \retval     none
+*/
+void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval)
+{
+    uint32_t reg;
+    
+    reg = RCU_CTL;
+    /* reset the IRC8MADJ bits and set according to irc8m_adjval */
+    reg &= ~RCU_CTL_IRC8MADJ;
+    RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3));
+}
+
+/*!
+    \brief      deep-sleep mode voltage select
+    \param[in]  dsvol: deep sleep mode voltage
+                only one parameter can be selected which is shown as below:
+      \arg        RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V
+      \arg        RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V
+      \arg        RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
+      \arg        RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
+    \param[out] none
+    \retval     none
+*/
+void rcu_deepsleep_voltage_set(uint32_t dsvol)
+{    
+    dsvol &= RCU_DSV_DSLPVS;
+    RCU_DSV = dsvol;
+}
+
+/*!
+    \brief      get the system clock, bus and peripheral clock frequency
+    \param[in]  clock: the clock frequency which to get
+                only one parameter can be selected which is shown as below:
+      \arg        CK_SYS: system clock frequency
+      \arg        CK_AHB: AHB clock frequency
+      \arg        CK_APB1: APB1 clock frequency
+      \arg        CK_APB2: APB2 clock frequency
+    \param[out] none
+    \retval     clock frequency of system, AHB, APB1, APB2
+*/
+uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
+{
+    uint32_t sws, ck_freq = 0U;
+    uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
+    uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp;
+#ifdef GD32F10X_CL
+    uint32_t predv0, predv1, pll1mf;
+#endif /* GD32F10X_CL */
+
+    /* exponent of AHB, APB1 and APB2 clock divider */
+    uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+    uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
+    uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
+
+    sws = GET_BITS(RCU_CFG0, 2, 3);
+    switch(sws){
+    /* IRC8M is selected as CK_SYS */
+    case SEL_IRC8M:
+        cksys_freq = IRC8M_VALUE;
+        break;
+    /* HXTAL is selected as CK_SYS */
+    case SEL_HXTAL:
+        cksys_freq = HXTAL_VALUE;
+        break;
+    /* PLL is selected as CK_SYS */
+    case SEL_PLL:
+        /* PLL clock source selection, HXTAL or IRC8M/2 */
+        pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
+
+        if(RCU_PLLSRC_HXTAL == pllsel) {
+            /* PLL clock source is HXTAL */
+            ck_src = HXTAL_VALUE;
+
+#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD))
+            predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0);
+            /* PREDV0 input source clock divided by 2 */
+            if(RCU_CFG0_PREDV0 == predv0sel){
+                ck_src = HXTAL_VALUE/2U;
+            }
+#elif defined(GD32F10X_CL)
+            predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
+            /* source clock use PLL1 */
+            if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
+                predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
+                pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
+                if(17U == pll1mf){
+                    pll1mf = 20U;
+                }
+                ck_src = (ck_src / predv1) * pll1mf;
+            }
+            predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
+            ck_src /= predv0;
+#endif /* GD32F10X_HD and GD32F10X_XD */
+        }else{
+            /* PLL clock source is IRC8M/2 */
+            ck_src = IRC8M_VALUE/2U;
+        }
+
+        /* PLL multiplication factor */
+        pllmf = GET_BITS(RCU_CFG0, 18, 21);
+        if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
+            pllmf |= 0x10U;
+        }
+        if(pllmf < 15U){
+            pllmf += 2U;
+        }else{
+            pllmf += 1U;
+        }
+
+        cksys_freq = ck_src * pllmf;
+
+    #ifdef GD32F10X_CL
+        if(15U == pllmf){
+            /* PLL source clock multiply by 6.5 */
+            cksys_freq = ck_src * 6U + ck_src / 2U;
+        }
+    #endif /* GD32F10X_CL */
+
+        break;
+    /* IRC8M is selected as CK_SYS */
+    default:
+        cksys_freq = IRC8M_VALUE;
+        break;
+    }
+
+    /* calculate AHB clock frequency */
+    idx = GET_BITS(RCU_CFG0, 4, 7);
+    clk_exp = ahb_exp[idx];
+    ahb_freq = cksys_freq >> clk_exp;
+    
+    /* calculate APB1 clock frequency */
+    idx = GET_BITS(RCU_CFG0, 8, 10);
+    clk_exp = apb1_exp[idx];
+    apb1_freq = ahb_freq >> clk_exp;
+    
+    /* calculate APB2 clock frequency */
+    idx = GET_BITS(RCU_CFG0, 11, 13);
+    clk_exp = apb2_exp[idx];
+    apb2_freq = ahb_freq >> clk_exp;
+    
+    /* return the clocks frequency */
+    switch(clock){
+    case CK_SYS:
+        ck_freq = cksys_freq;
+        break;
+    case CK_AHB:
+        ck_freq = ahb_freq;
+        break;
+    case CK_APB1:
+        ck_freq = apb1_freq;
+        break;
+    case CK_APB2:
+        ck_freq = apb2_freq;
+        break;
+    default:
+        break;
+    }
+    return ck_freq;
+}

+ 276 - 0
Library/Source/gd32f10x_rtc.c

@@ -0,0 +1,276 @@
+/*!
+    \file    gd32f10x_rtc.c
+    \brief   RTC driver
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_rtc.h"
+
+/* RTC register high / low bits mask */
+#define RTC_HIGH_BITS_MASK         ((uint32_t)0x000F0000U)  /* RTC high bits mask */
+#define RTC_LOW_BITS_MASK          ((uint32_t)0x0000FFFFU)  /* RTC low bits mask */
+
+/* RTC register high bits offset */
+#define RTC_HIGH_BITS_OFFSET       ((uint32_t)16U)
+
+/*!
+    \brief      enter RTC configuration mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rtc_configuration_mode_enter(void)
+{
+    RTC_CTL |= RTC_CTL_CMF;
+}
+
+/*!
+    \brief      exit RTC configuration mode 
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rtc_configuration_mode_exit(void)
+{
+    RTC_CTL &= ~RTC_CTL_CMF;
+}
+
+/*!
+    \brief      set RTC counter value
+    \param[in]  cnt: RTC counter value
+    \param[out] none
+    \retval     none
+*/
+void rtc_counter_set(uint32_t cnt)
+{
+    rtc_configuration_mode_enter();
+    /* set the RTC counter high bits */
+    RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
+    /* set the RTC counter low bits */
+    RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
+    rtc_configuration_mode_exit();
+}
+
+/*!
+    \brief      set RTC prescaler value
+    \param[in]  psc: RTC prescaler value
+    \param[out] none
+    \retval     none
+*/
+void rtc_prescaler_set(uint32_t psc)
+{
+    rtc_configuration_mode_enter();
+    /* set the RTC prescaler high bits */
+    RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
+    /* set the RTC prescaler low bits */
+    RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
+    rtc_configuration_mode_exit();
+}
+
+/*!
+    \brief      wait RTC last write operation finished flag set
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rtc_lwoff_wait(void)
+{
+    /* loop until LWOFF flag is set */
+    while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){
+    }
+}
+
+/*!
+    \brief      wait RTC registers synchronized flag set
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void rtc_register_sync_wait(void)
+{
+    /* clear RSYNF flag */
+    RTC_CTL &= ~RTC_CTL_RSYNF;
+    /* loop until RSYNF flag is set */
+    while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){
+    }
+}
+
+/*!
+    \brief      set RTC alarm value
+    \param[in]  alarm: RTC alarm value
+    \param[out] none
+    \retval     none
+*/
+void rtc_alarm_config(uint32_t alarm)
+{
+    rtc_configuration_mode_enter();
+    /* set the alarm high bits */
+    RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
+    /* set the alarm low bits */
+    RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
+    rtc_configuration_mode_exit();
+}
+
+/*!
+    \brief      get RTC counter value
+    \param[in]  none
+    \param[out] none
+    \retval     RTC counter value
+*/
+uint32_t rtc_counter_get(void)
+{
+    uint32_t temp = 0x0U;
+    
+    temp = RTC_CNTL;
+    temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET);
+    return temp;
+}
+
+/*!
+    \brief      get RTC divider value
+    \param[in]  none
+    \param[out] none
+    \retval     RTC divider value
+*/
+uint32_t rtc_divider_get(void)
+{
+    uint32_t temp = 0x00U;
+    
+    temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
+    temp |= RTC_DIVL;
+    return temp;
+}
+
+/*!
+    \brief      get RTC flag status 
+    \param[in]  flag: specify which flag status to get
+                only one parameter can be selected which is shown as below:
+      \arg        RTC_FLAG_SECOND: second interrupt flag
+      \arg        RTC_FLAG_ALARM: alarm interrupt flag
+      \arg        RTC_FLAG_OVERFLOW: overflow interrupt flag
+      \arg        RTC_FLAG_RSYN: registers synchronized flag
+      \arg        RTC_FLAG_LWOF: last write operation finished flag
+    \param[out] none
+    \retval     SET or RESET
+*/
+FlagStatus rtc_flag_get(uint32_t flag)
+{
+    if(RESET != (RTC_CTL & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear RTC flag status
+    \param[in]  flag: specify which flag status to clear
+                one or more parameters can be selected which are shown as below:
+      \arg        RTC_FLAG_SECOND: second interrupt flag
+      \arg        RTC_FLAG_ALARM: alarm interrupt flag
+      \arg        RTC_FLAG_OVERFLOW: overflow interrupt flag
+      \arg        RTC_FLAG_RSYN: registers synchronized flag
+    \param[out] none
+    \retval     none
+*/
+void rtc_flag_clear(uint32_t flag)
+{
+    /* clear RTC flag */
+    RTC_CTL &= ~flag;
+}
+
+/*!
+    \brief      get RTC interrupt flag status 
+    \param[in]  flag: specify which flag status to get
+                only one parameter can be selected which is shown as below:
+      \arg        RTC_INT_FLAG_SECOND: second interrupt flag
+      \arg        RTC_INT_FLAG_ALARM: alarm interrupt flag
+      \arg        RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
+    \param[out] none
+    \retval     SET or RESET
+*/
+FlagStatus rtc_interrupt_flag_get(uint32_t flag)
+{
+    if(RESET != (RTC_CTL & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear RTC interrupt flag status
+    \param[in]  flag: specify which flag status to clear
+                one or more parameters can be selected which are shown as below:
+      \arg        RTC_INT_FLAG_SECOND: second interrupt flag
+      \arg        RTC_INT_FLAG_ALARM: alarm interrupt flag
+      \arg        RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void rtc_interrupt_flag_clear(uint32_t flag)
+{
+    /* clear RTC interrupt flag */
+    RTC_CTL &= ~flag;
+}
+
+/*!
+    \brief      enable RTC interrupt
+    \param[in]  interrupt: specify which interrupt to enbale
+                one or more parameters can be selected which are shown as below:
+      \arg        RTC_INT_SECOND: second interrupt
+      \arg        RTC_INT_ALARM: alarm interrupt
+      \arg        RTC_INT_OVERFLOW: overflow interrupt
+    \param[out] none
+    \retval     none
+*/
+void rtc_interrupt_enable(uint32_t interrupt)
+{
+    RTC_INTEN |= interrupt;
+}
+
+/*!
+    \brief      disable RTC interrupt
+    \param[in]  interrupt: specify which interrupt to disbale
+                one or more parameters can be selected which are shown as below:
+      \arg        RTC_INT_SECOND: second interrupt
+      \arg        RTC_INT_ALARM: alarm interrupt
+      \arg        RTC_INT_OVERFLOW: overflow interrupt
+    \param[out] none
+    \retval     none
+*/
+void rtc_interrupt_disable(uint32_t interrupt)
+{
+    RTC_INTEN &= ~interrupt;
+}

+ 807 - 0
Library/Source/gd32f10x_sdio.c

@@ -0,0 +1,807 @@
+/*!
+    \file    gd32f10x_sdio.c
+    \brief   SDIO driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_sdio.h"
+
+#define DEFAULT_RESET_VALUE 0x00000000U
+
+/*!
+    \brief      deinitialize the SDIO
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_deinit(void)
+{
+    SDIO_PWRCTL  = DEFAULT_RESET_VALUE;
+    SDIO_CLKCTL  = DEFAULT_RESET_VALUE;
+    SDIO_CMDAGMT = DEFAULT_RESET_VALUE;
+    SDIO_CMDCTL  = DEFAULT_RESET_VALUE;
+    SDIO_DATATO  = DEFAULT_RESET_VALUE;
+    SDIO_DATALEN = DEFAULT_RESET_VALUE;
+    SDIO_DATACTL = DEFAULT_RESET_VALUE;
+    SDIO_INTC    = DEFAULT_RESET_VALUE;
+    SDIO_INTEN   = DEFAULT_RESET_VALUE;
+}
+
+/*!
+    \brief      configure the SDIO clock
+    \param[in]  clock_edge: SDIO_CLK clock edge
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK
+      \arg        SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK
+    \param[in]  clock_bypass: clock bypass
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_CLOCKBYPASS_ENABLE: clock bypass
+      \arg        SDIO_CLOCKBYPASS_DISABLE: no bypass
+    \param[in]  clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle
+      \arg        SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on
+    \param[in]  clock_division: clock division, less than 256
+    \param[out] none
+    \retval     none
+*/
+void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division)
+{
+    uint32_t clock_config = 0U;
+    clock_config = SDIO_CLKCTL;
+    /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */
+    clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV);
+
+    /* configure the SDIO_CLKCTL according to the parameters */
+    clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division);
+    SDIO_CLKCTL = clock_config;
+}
+
+/*!
+    \brief      enable hardware clock control
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_hardware_clock_enable(void)
+{
+    SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN;
+}
+
+/*!
+    \brief      disable hardware clock control
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_hardware_clock_disable(void)
+{
+    SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN;
+}
+
+/*!
+    \brief      set different SDIO card bus mode
+    \param[in]  bus_mode: SDIO card bus mode
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode
+      \arg        SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode
+      \arg        SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode
+    \param[out] none
+    \retval     none
+*/
+void sdio_bus_mode_set(uint32_t bus_mode)
+{
+    /* reset the SDIO card bus mode bits and set according to bus_mode */
+    SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE;
+    SDIO_CLKCTL |= bus_mode;
+}
+
+/*!
+    \brief      set the SDIO power state
+    \param[in]  power_state: SDIO power state
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_POWER_ON: SDIO power on
+      \arg        SDIO_POWER_OFF: SDIO power off
+    \param[out] none
+    \retval     none
+*/
+void sdio_power_state_set(uint32_t power_state)
+{
+    SDIO_PWRCTL = power_state;
+}
+
+/*!
+    \brief      get the SDIO power state
+    \param[in]  none
+    \param[out] none
+    \retval     SDIO power state
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_POWER_ON: SDIO power on
+      \arg        SDIO_POWER_OFF: SDIO power off
+*/
+uint32_t sdio_power_state_get(void)
+{
+    return SDIO_PWRCTL;
+}
+
+/*!
+    \brief      enable SDIO_CLK clock output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_clock_enable(void)
+{
+    SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN;
+}
+
+/*!
+    \brief      disable SDIO_CLK clock output
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_clock_disable(void)
+{
+    SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN;
+}
+
+/*!
+    \brief      configure the command and response
+    \param[in]  cmd_index: command index, refer to the related specifications
+    \param[in]  cmd_argument: command argument, refer to the related specifications
+    \param[in]  response_type: response type
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_RESPONSETYPE_NO: no response
+      \arg        SDIO_RESPONSETYPE_SHORT: short response
+      \arg        SDIO_RESPONSETYPE_LONG: long response
+    \param[out] none
+    \retval     none
+*/
+void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type)
+{
+    uint32_t cmd_config = 0U;
+    /* reset the command index, command argument and response type */
+    SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT;
+    SDIO_CMDAGMT = cmd_argument;
+    cmd_config = SDIO_CMDCTL;
+    cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP);
+    /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */
+    cmd_config |= (cmd_index | response_type);
+    SDIO_CMDCTL = cmd_config;
+}
+
+/*!
+    \brief      set the command state machine wait type
+    \param[in]  wait_type: wait type
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_WAITTYPE_NO: not wait interrupt
+      \arg        SDIO_WAITTYPE_INTERRUPT: wait interrupt
+      \arg        SDIO_WAITTYPE_DATAEND: wait the end of data transfer
+    \param[out] none
+    \retval     none
+*/
+void sdio_wait_type_set(uint32_t wait_type)
+{
+    /* reset INTWAIT and WAITDEND */
+    SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND);
+    /* set the wait type according to wait_type */
+    SDIO_CMDCTL |= wait_type;
+}
+
+/*!
+    \brief      enable the CSM(command state machine)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_csm_enable(void)
+{
+    SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN;
+}
+
+/*!
+    \brief      disable the CSM(command state machine)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_csm_disable(void)
+{
+    SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN;
+}
+
+/*!
+    \brief      get the last response command index
+    \param[in]  none
+    \param[out] none
+    \retval     last response command index
+*/
+uint8_t sdio_command_index_get(void)
+{
+    return (uint8_t)SDIO_RSPCMDIDX;
+}
+
+/*!
+    \brief      get the response for the last received command
+    \param[in]  responsex: SDIO response
+                only one parameter can be selected which is shown as below:
+      \arg       SDIO_RESPONSE0: card response[31:0]/card response[127:96]
+      \arg       SDIO_RESPONSE1: card response[95:64]
+      \arg       SDIO_RESPONSE2: card response[63:32]
+      \arg       SDIO_RESPONSE3: card response[31:1], plus bit 0
+    \param[out] none
+    \retval     response for the last received command
+*/
+uint32_t sdio_response_get(uint32_t responsex)
+{
+    uint32_t resp_content = 0U;
+    switch(responsex){
+    case SDIO_RESPONSE0:
+        resp_content = SDIO_RESP0;
+        break;
+    case SDIO_RESPONSE1:
+        resp_content = SDIO_RESP1;
+        break;
+    case SDIO_RESPONSE2:
+        resp_content = SDIO_RESP2;
+        break;
+    case SDIO_RESPONSE3:
+        resp_content = SDIO_RESP3;
+        break;
+    default:
+        break;
+    }
+    return resp_content;
+}
+
+/*!
+    \brief      configure the data timeout, data length and data block size
+    \param[in]  data_timeout: data timeout period in card bus clock periods
+    \param[in]  data_length: number of data bytes to be transferred
+    \param[in]  data_blocksize: size of data block for block transfer
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte
+      \arg        SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes
+      \arg        SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes
+      \arg        SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes
+      \arg        SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes
+      \arg        SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes
+      \arg        SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes
+      \arg        SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes
+      \arg        SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes
+      \arg        SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes
+      \arg        SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes
+      \arg        SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes
+      \arg        SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes
+      \arg        SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes
+      \arg        SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes
+    \param[out] none
+    \retval     none
+*/
+void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize)
+{
+    /* reset data timeout, data length and data block size */
+    SDIO_DATATO &= ~SDIO_DATATO_DATATO;
+    SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN;
+    SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ;
+    /* configure the related parameters of data */
+    SDIO_DATATO = data_timeout;
+    SDIO_DATALEN = data_length;
+    SDIO_DATACTL |= data_blocksize;
+}
+
+/*!
+    \brief      configure the data transfer mode and direction
+    \param[in]  transfer_mode: mode of data transfer
+                only one parameter can be selected which is shown as below:
+      \arg       SDIO_TRANSMODE_BLOCK: block transfer
+      \arg       SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer
+    \param[in]  transfer_direction: data transfer direction, read or write
+                only one parameter can be selected which is shown as below:
+      \arg       SDIO_TRANSDIRECTION_TOCARD: write data to card
+      \arg       SDIO_TRANSDIRECTION_TOSDIO: read data from card
+    \param[out] none
+    \retval     none
+*/
+void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction)
+{
+    uint32_t data_trans = 0U;
+    /* reset the data transfer mode, transfer direction and set according to the parameters */
+    data_trans = SDIO_DATACTL;
+    data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR);
+    data_trans |= (transfer_mode | transfer_direction);
+    SDIO_DATACTL = data_trans;
+}
+
+/*!
+    \brief      enable the DSM(data state machine) for data transfer
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_dsm_enable(void)
+{
+    SDIO_DATACTL |= SDIO_DATACTL_DATAEN;
+}
+
+/*!
+    \brief      disable the DSM(data state machine)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_dsm_disable(void)
+{
+    SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN;
+}
+
+/*!
+    \brief      write data(one word) to the transmit FIFO
+    \param[in]  data: 32-bit data write to card
+    \param[out] none
+    \retval     none
+*/
+void sdio_data_write(uint32_t data)
+{
+    SDIO_FIFO = data;
+}
+
+/*!
+    \brief      read data(one word) from the receive FIFO
+    \param[in]  none
+    \param[out] none
+    \retval     received data
+*/
+uint32_t sdio_data_read(void)
+{
+    return SDIO_FIFO;
+}
+
+/*!
+    \brief      get the number of remaining data bytes to be transferred to card
+    \param[in]  none
+    \param[out] none
+    \retval     number of remaining data bytes to be transferred
+*/
+uint32_t sdio_data_counter_get(void)
+{
+    return SDIO_DATACNT;
+}
+
+/*!
+    \brief      get the number of words remaining to be written or read from FIFO
+    \param[in]  none
+    \param[out] none
+    \retval     remaining number of words
+*/
+uint32_t sdio_fifo_counter_get(void)
+{
+    return SDIO_FIFOCNT;
+}
+
+/*!
+    \brief      enable the DMA request for SDIO
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_dma_enable(void)
+{
+    SDIO_DATACTL |= SDIO_DATACTL_DMAEN;
+}
+
+/*!
+    \brief      disable the DMA request for SDIO
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_dma_disable(void)
+{
+    SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN;
+}
+
+/*!
+    \brief      get the flags state of SDIO
+    \param[in]  flag: flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag
+      \arg        SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
+      \arg        SDIO_FLAG_CMDTMOUT: command response timeout flag
+      \arg        SDIO_FLAG_DTTMOUT: data timeout flag
+      \arg        SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag
+      \arg        SDIO_FLAG_RXORE: received FIFO overrun error occurs flag
+      \arg        SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag
+      \arg        SDIO_FLAG_CMDSEND: command sent (no response required) flag
+      \arg        SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
+      \arg        SDIO_FLAG_STBITE: start bit error in the bus flag
+      \arg        SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
+      \arg        SDIO_FLAG_CMDRUN: command transmission in progress flag
+      \arg        SDIO_FLAG_TXRUN: data transmission in progress flag
+      \arg        SDIO_FLAG_RXRUN: data reception in progress flag
+      \arg        SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO
+      \arg        SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO
+      \arg        SDIO_FLAG_TFF: transmit FIFO is full flag
+      \arg        SDIO_FLAG_RFF: receive FIFO is full flag
+      \arg        SDIO_FLAG_TFE: transmit FIFO is empty flag
+      \arg        SDIO_FLAG_RFE: receive FIFO is empty flag
+      \arg        SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag
+      \arg        SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag
+      \arg        SDIO_FLAG_SDIOINT: SD I/O interrupt received flag
+      \arg        SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus sdio_flag_get(uint32_t flag)
+{
+    FlagStatus temp_flag = RESET;
+    if(RESET != (SDIO_STAT & flag)){
+        temp_flag = SET;
+    }
+    return temp_flag;
+}
+
+/*!
+    \brief      clear the pending flags of SDIO
+    \param[in]  flag: flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag
+      \arg        SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
+      \arg        SDIO_FLAG_CMDTMOUT: command response timeout flag
+      \arg        SDIO_FLAG_DTTMOUT: data timeout flag
+      \arg        SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag
+      \arg        SDIO_FLAG_RXORE: received FIFO overrun error occurs flag
+      \arg        SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag
+      \arg        SDIO_FLAG_CMDSEND: command sent (no response required) flag
+      \arg        SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
+      \arg        SDIO_FLAG_STBITE: start bit error in the bus flag
+      \arg        SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
+      \arg        SDIO_FLAG_SDIOINT: SD I/O interrupt received flag
+      \arg        SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
+    \param[out] none
+    \retval     none
+*/
+void sdio_flag_clear(uint32_t flag)
+{
+    SDIO_INTC = flag;
+}
+
+/*!
+    \brief      enable the SDIO interrupt
+    \param[in]  int_flag: interrupt flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_INT_CCRCERR: SDIO CCRCERR interrupt
+      \arg        SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt
+      \arg        SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt
+      \arg        SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt
+      \arg        SDIO_INT_TXURE: SDIO TXURE interrupt
+      \arg        SDIO_INT_RXORE: SDIO RXORE interrupt
+      \arg        SDIO_INT_CMDRECV: SDIO CMDRECV interrupt
+      \arg        SDIO_INT_CMDSEND: SDIO CMDSEND interrupt
+      \arg        SDIO_INT_DTEND: SDIO DTEND interrupt
+      \arg        SDIO_INT_STBITE: SDIO STBITE interrupt
+      \arg        SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt
+      \arg        SDIO_INT_CMDRUN: SDIO CMDRUN interrupt
+      \arg        SDIO_INT_TXRUN: SDIO TXRUN interrupt
+      \arg        SDIO_INT_RXRUN: SDIO RXRUN interrupt
+      \arg        SDIO_INT_TFH: SDIO TFH interrupt
+      \arg        SDIO_INT_RFH: SDIO RFH interrupt
+      \arg        SDIO_INT_TFF: SDIO TFF interrupt
+      \arg        SDIO_INT_RFF: SDIO RFF interrupt
+      \arg        SDIO_INT_TFE: SDIO TFE interrupt
+      \arg        SDIO_INT_RFE: SDIO RFE interrupt
+      \arg        SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt
+      \arg        SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt
+      \arg        SDIO_INT_SDIOINT: SDIO SDIOINT interrupt
+      \arg        SDIO_INT_ATAEND: SDIO ATAEND interrupt
+    \param[out] none
+    \retval     none
+*/
+void sdio_interrupt_enable(uint32_t int_flag)
+{
+    SDIO_INTEN |= int_flag;
+}
+
+/*!
+    \brief      disable the SDIO interrupt
+    \param[in]  int_flag: interrupt flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_INT_CCRCERR: SDIO CCRCERR interrupt
+      \arg        SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt
+      \arg        SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt
+      \arg        SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt
+      \arg        SDIO_INT_TXURE: SDIO TXURE interrupt
+      \arg        SDIO_INT_RXORE: SDIO RXORE interrupt
+      \arg        SDIO_INT_CMDRECV: SDIO CMDRECV interrupt
+      \arg        SDIO_INT_CMDSEND: SDIO CMDSEND interrupt
+      \arg        SDIO_INT_DTEND: SDIO DTEND interrupt
+      \arg        SDIO_INT_STBITE: SDIO STBITE interrupt
+      \arg        SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt
+      \arg        SDIO_INT_CMDRUN: SDIO CMDRUN interrupt
+      \arg        SDIO_INT_TXRUN: SDIO TXRUN interrupt
+      \arg        SDIO_INT_RXRUN: SDIO RXRUN interrupt
+      \arg        SDIO_INT_TFH: SDIO TFH interrupt
+      \arg        SDIO_INT_RFH: SDIO RFH interrupt
+      \arg        SDIO_INT_TFF: SDIO TFF interrupt
+      \arg        SDIO_INT_RFF: SDIO RFF interrupt
+      \arg        SDIO_INT_TFE: SDIO TFE interrupt
+      \arg        SDIO_INT_RFE: SDIO RFE interrupt
+      \arg        SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt
+      \arg        SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt
+      \arg        SDIO_INT_SDIOINT: SDIO SDIOINT interrupt
+      \arg        SDIO_INT_ATAEND: SDIO ATAEND interrupt
+    \param[out] none
+    \retval     none
+*/
+void sdio_interrupt_disable(uint32_t int_flag)
+{
+    SDIO_INTEN &= ~int_flag;
+}
+
+/*!
+    \brief      get the interrupt flags state of SDIO
+    \param[in]  int_flag: interrupt flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt flag
+      \arg        SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt flag
+      \arg        SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt flag
+      \arg        SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt flag
+      \arg        SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt flag
+      \arg        SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt flag
+      \arg        SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt flag
+      \arg        SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt flag
+      \arg        SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt flag
+      \arg        SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt flag
+      \arg        SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt flag
+      \arg        SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt flag
+      \arg        SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt flag
+      \arg        SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt flag
+      \arg        SDIO_INT_FLAG_TFH: SDIO TFH interrupt flag
+      \arg        SDIO_INT_FLAG_RFH: SDIO RFH interrupt flag
+      \arg        SDIO_INT_FLAG_TFF: SDIO TFF interrupt flag
+      \arg        SDIO_INT_FLAG_RFF: SDIO RFF interrupt flag
+      \arg        SDIO_INT_FLAG_TFE: SDIO TFE interrupt flag
+      \arg        SDIO_INT_FLAG_RFE: SDIO RFE interrupt flag
+      \arg        SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt flag
+      \arg        SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt flag
+      \arg        SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt flag
+      \arg        SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus sdio_interrupt_flag_get(uint32_t int_flag)
+{
+    if(RESET != (SDIO_STAT & int_flag)){
+        return SET;
+    }
+    return RESET;
+}
+
+/*!
+    \brief      clear the interrupt pending flags of SDIO
+    \param[in]  int_flag: interrupt flags state of SDIO
+                one or more parameters can be selected which are shown as below:
+      \arg        SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag
+      \arg        SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
+      \arg        SDIO_INT_FLAG_CMDTMOUT: command response timeout flag
+      \arg        SDIO_INT_FLAG_DTTMOUT: data timeout flag
+      \arg        SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag
+      \arg        SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag
+      \arg        SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag
+      \arg        SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag
+      \arg        SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
+      \arg        SDIO_INT_FLAG_STBITE: start bit error in the bus flag
+      \arg        SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
+      \arg        SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag
+      \arg        SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
+    \param[out] none
+    \retval     none
+*/
+void sdio_interrupt_flag_clear(uint32_t int_flag)
+{
+    SDIO_INTC = int_flag;
+}
+
+/*!
+    \brief      enable the read wait mode(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_readwait_enable(void)
+{
+    SDIO_DATACTL |= SDIO_DATACTL_RWEN;
+}
+
+/*!
+    \brief      disable the read wait mode(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_readwait_disable(void)
+{
+    SDIO_DATACTL &= ~SDIO_DATACTL_RWEN;
+}
+
+/*!
+    \brief      enable the function that stop the read wait process(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_stop_readwait_enable(void)
+{
+    SDIO_DATACTL |= SDIO_DATACTL_RWSTOP;
+}
+
+/*!
+    \brief      disable the function that stop the read wait process(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_stop_readwait_disable(void)
+{
+    SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP;
+}
+
+/*!
+    \brief      set the read wait type(SD I/O only)
+    \param[in]  readwait_type: SD I/O read wait type
+                only one parameter can be selected which is shown as below:
+      \arg        SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK
+      \arg        SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2]
+    \param[out] none
+    \retval     none
+*/
+void sdio_readwait_type_set(uint32_t readwait_type)
+{
+    if(SDIO_READWAITTYPE_CLK == readwait_type){
+        SDIO_DATACTL |= SDIO_DATACTL_RWTYPE;
+    }else{
+        SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE;
+    }
+}
+
+/*!
+    \brief      enable the SD I/O mode specific operation(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_operation_enable(void)
+{
+    SDIO_DATACTL |= SDIO_DATACTL_IOEN;
+}
+
+/*!
+    \brief      disable the SD I/O mode specific operation(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_operation_disable(void)
+{
+    SDIO_DATACTL &= ~SDIO_DATACTL_IOEN;
+}
+
+/*!
+    \brief      enable the SD I/O suspend operation(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_suspend_enable(void)
+{
+    SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND;
+}
+
+/*!
+    \brief      disable the SD I/O suspend operation(SD I/O only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_suspend_disable(void)
+{
+    SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND;
+}
+
+/*!
+    \brief      enable the CE-ATA command(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_command_enable(void)
+{
+    SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN;
+}
+
+/*!
+    \brief      disable the CE-ATA command(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_command_disable(void)
+{
+    SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN;
+}
+
+/*!
+    \brief      enable the CE-ATA interrupt(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_interrupt_enable(void)
+{
+    SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN;
+}
+
+/*!
+    \brief      disable the CE-ATA interrupt(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_interrupt_disable(void)
+{
+    SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN;
+}
+
+/*!
+    \brief      enable the CE-ATA command completion signal(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_command_completion_enable(void)
+{
+    SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC;
+}
+
+/*!
+    \brief      disable the CE-ATA command completion signal(CE-ATA only)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void sdio_ceata_command_completion_disable(void)
+{
+    SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC;
+}

+ 717 - 0
Library/Source/gd32f10x_spi.c

@@ -0,0 +1,717 @@
+/*!
+    \file    gd32f10x_spi.c
+    \brief   SPI driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_spi.h"
+
+/* SPI/I2S parameter initialization mask */
+#define SPI_INIT_MASK                   ((uint32_t)0x00003040U)  /*!< SPI parameter initialization mask */
+#define I2S_INIT_MASK                   ((uint32_t)0x0000F047U)  /*!< I2S parameter initialization mask */
+
+/* I2S clock source selection, multiplication and division mask */
+#define I2S1_CLOCK_SEL                  ((uint32_t)0x00020000U)  /* I2S1 clock source selection */
+#define I2S2_CLOCK_SEL                  ((uint32_t)0x00040000U)  /* I2S2 clock source selection */
+#define I2S_CLOCK_MUL_MASK              ((uint32_t)0x0000F000U)  /* I2S clock multiplication mask */
+#define I2S_CLOCK_DIV_MASK              ((uint32_t)0x000000F0U)  /* I2S clock division mask */
+
+/* default value and offset */
+#define SPI_I2SPSC_DEFAULT_VALUE        ((uint32_t)0x00000002U)  /* default value of SPI_I2SPSC register */
+#define RCU_CFG1_PREDV1_OFFSET          4U                       /* PREDV1 offset in RCU_CFG1 */
+#define RCU_CFG1_PLL2MF_OFFSET          12U                      /* PLL2MF offset in RCU_CFG1 */
+
+/*!
+    \brief      reset SPI and I2S 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_i2s_deinit(uint32_t spi_periph)
+{
+    switch(spi_periph){
+    case SPI0:
+        /* reset SPI0 */
+        rcu_periph_reset_enable(RCU_SPI0RST);
+        rcu_periph_reset_disable(RCU_SPI0RST);
+        break;
+    case SPI1:
+        /* reset SPI1 and I2S1 */
+        rcu_periph_reset_enable(RCU_SPI1RST);
+        rcu_periph_reset_disable(RCU_SPI1RST);
+        break;
+    case SPI2:
+        /* reset SPI2 and I2S2 */
+        rcu_periph_reset_enable(RCU_SPI2RST);
+        rcu_periph_reset_disable(RCU_SPI2RST);
+        break;
+    default :
+        break;
+    }
+}
+
+/*!
+    \brief      initialize the parameters of SPI struct with the default values
+    \param[in]  spi_struct: SPI parameter stuct
+    \param[out] none
+    \retval     none
+*/
+void spi_struct_para_init(spi_parameter_struct* spi_struct)
+{
+    /* set the SPI struct with the default values */
+    spi_struct->device_mode = SPI_SLAVE;
+    spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
+    spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
+    spi_struct->nss = SPI_NSS_HARD;
+    spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
+    spi_struct->prescale = SPI_PSC_2;
+}
+
+/*!
+    \brief      initialize SPI parameter
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  spi_struct: SPI parameter initialization stuct members of the structure 
+                            and the member values are shown as below:
+                  device_mode: SPI_MASTER, SPI_SLAVE
+                  trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
+                              SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
+                  frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
+                  nss: SPI_NSS_SOFT, SPI_NSS_HARD
+                  endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
+                  clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
+                                        SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
+                  prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
+    \param[out] none
+    \retval     none
+*/
+void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
+{   
+    uint32_t reg = 0U;
+    reg = SPI_CTL0(spi_periph);
+    reg &= SPI_INIT_MASK;
+
+    /* select SPI as master or slave */
+    reg |= spi_struct->device_mode;
+    /* select SPI transfer mode */
+    reg |= spi_struct->trans_mode;
+    /* select SPI frame size */
+    reg |= spi_struct->frame_size;
+    /* select SPI NSS use hardware or software */
+    reg |= spi_struct->nss;
+    /* select SPI LSB or MSB */
+    reg |= spi_struct->endian;
+    /* select SPI polarity and phase */
+    reg |= spi_struct->clock_polarity_phase;
+    /* select SPI prescale to adjust transmit speed */
+    reg |= spi_struct->prescale;
+
+    /* write to SPI_CTL0 register */
+    SPI_CTL0(spi_periph) = (uint32_t)reg;
+
+    SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
+}
+
+/*!
+    \brief      enable SPI
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_enable(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
+}
+
+/*!
+    \brief      disable SPI 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_disable(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
+}
+
+/*!
+    \brief      initialize I2S parameter 
+    \param[in]  spi_periph: SPIx(x=1,2)
+    \param[in]  mode: I2S operation mode
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_MODE_SLAVETX: I2S slave transmit mode
+      \arg        I2S_MODE_SLAVERX: I2S slave receive mode
+      \arg        I2S_MODE_MASTERTX: I2S master transmit mode
+      \arg        I2S_MODE_MASTERRX: I2S master receive mode
+    \param[in]  standard: I2S standard
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_STD_PHILLIPS: I2S phillips standard
+      \arg        I2S_STD_MSB: I2S MSB standard
+      \arg        I2S_STD_LSB: I2S LSB standard
+      \arg        I2S_STD_PCMSHORT: I2S PCM short standard
+      \arg        I2S_STD_PCMLONG: I2S PCM long standard
+    \param[in]  ckpl: I2S idle state clock polarity
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_CKPL_LOW: I2S clock polarity low level
+      \arg        I2S_CKPL_HIGH: I2S clock polarity high level
+    \param[out] none
+    \retval     none
+*/
+void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
+{
+    uint32_t reg = 0U;
+    reg = SPI_I2SCTL(spi_periph);
+    reg &= I2S_INIT_MASK;
+
+    /* enable I2S mode */
+    reg |= (uint32_t)SPI_I2SCTL_I2SSEL; 
+    /* select I2S mode */
+    reg |= (uint32_t)mode;
+    /* select I2S standard */
+    reg |= (uint32_t)standard;
+    /* select I2S polarity */
+    reg |= (uint32_t)ckpl;
+
+    /* write to SPI_I2SCTL register */
+    SPI_I2SCTL(spi_periph) = (uint32_t)reg;
+}
+
+/*!
+    \brief      configure I2S prescaler 
+    \param[in]  spi_periph: SPIx(x=1,2)
+    \param[in]  audiosample: I2S audio sample rate
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
+      \arg        I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
+      \arg        I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
+      \arg        I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
+      \arg        I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
+      \arg        I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
+      \arg        I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
+      \arg        I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
+      \arg        I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
+    \param[in]  frameformat: I2S data length and channel length
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
+      \arg        I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
+      \arg        I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
+      \arg        I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
+    \param[in]  mckout: I2S master clock output
+                only one parameter can be selected which is shown as below:
+      \arg        I2S_MCKOUT_ENABLE: I2S master clock output enable
+      \arg        I2S_MCKOUT_DISABLE: I2S master clock output disable
+    \param[out] none
+    \retval     none
+*/
+void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
+{
+    uint32_t i2sdiv = 2U, i2sof = 0U;
+    uint32_t clks = 0U;
+    uint32_t i2sclock = 0U;
+
+    /* deinit SPI_I2SPSC register */
+    SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
+
+#ifdef GD32F10X_CL
+    /* get the I2S clock source */
+    if(SPI1 == ((uint32_t)spi_periph)){
+        /* I2S1 clock source selection */
+        clks = I2S1_CLOCK_SEL;
+    }else{
+        /* I2S2 clock source selection */
+        clks = I2S2_CLOCK_SEL;
+    }
+    
+    if(0U != (RCU_CFG1 & clks)){
+        /* get RCU PLL2 clock multiplication factor */
+        clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
+ 
+        if((clks > 5U) && (clks < 15U)){
+            /* multiplier is between 8 and 14 */
+            clks += 2U;
+        }else{
+            if(15U == clks){
+                /* multiplier is 20 */
+                clks = 20U;
+            }
+        }
+        
+        /* get the PREDV1 value */
+        i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >>  RCU_CFG1_PREDV1_OFFSET) + 1U);
+        /* calculate I2S clock based on PLL2 and PREDV1 */
+        i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); 
+    }else{
+        /* get system clock */
+        i2sclock = rcu_clock_freq_get(CK_SYS);
+    }
+#else
+    /* get system clock */
+    i2sclock = rcu_clock_freq_get(CK_SYS);
+#endif /* GD32F10X_CL */ 
+    
+    /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
+    if(I2S_MCKOUT_ENABLE == mckout){
+        clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
+    }else{
+        if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
+            clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample);
+        }else{
+            clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample);
+        }
+    }
+    
+    /* remove the floating point */
+    clks = (clks + 5U) / 10U;
+    i2sof  = (clks & 0x00000001U);
+    i2sdiv = ((clks - i2sof) / 2U);
+    i2sof  = (i2sof << 8U);
+
+    /* set the default values */
+    if((i2sdiv < 2U) || (i2sdiv > 255U)){
+        i2sdiv = 2U;
+        i2sof = 0U;
+    }
+
+    /* configure SPI_I2SPSC */
+    SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
+
+    /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
+    SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
+    /* configure data frame format */
+    SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
+}
+
+/*!
+    \brief      enable I2S 
+    \param[in]  spi_periph: SPIx(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void i2s_enable(uint32_t spi_periph)
+{
+    SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
+}
+
+/*!
+    \brief      disable I2S 
+    \param[in]  spi_periph: SPIx(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void i2s_disable(uint32_t spi_periph)
+{
+    SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
+}
+
+/*!
+    \brief      enable SPI NSS output 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_nss_output_enable(uint32_t spi_periph)
+{
+    SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
+}
+
+/*!
+    \brief      disable SPI NSS output 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_nss_output_disable(uint32_t spi_periph)
+{
+    SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
+}
+
+/*!
+    \brief      SPI NSS pin high level in software mode
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_nss_internal_high(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
+}
+
+/*!
+    \brief      SPI NSS pin low level in software mode
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_nss_internal_low(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
+}
+
+/*!
+    \brief      enable SPI DMA send or receive 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  dma: SPI DMA mode
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_DMA_TRANSMIT: SPI transmit data using DMA
+      \arg        SPI_DMA_RECEIVE: SPI receive data using DMA
+    \param[out] none
+    \retval     none
+*/
+void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
+{
+    if(SPI_DMA_TRANSMIT == dma){
+        SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
+    }else{
+        SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
+    }
+}
+
+/*!
+    \brief      disable SPI DMA send or receive 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  dma: SPI DMA mode
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_DMA_TRANSMIT: SPI transmit data using DMA
+      \arg        SPI_DMA_RECEIVE: SPI receive data using DMA
+    \param[out] none
+    \retval     none
+*/
+void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
+{
+    if(SPI_DMA_TRANSMIT == dma){
+        SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
+    }else{
+        SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
+    }
+}
+
+/*!
+    \brief      configure SPI/I2S data frame format
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  frame_format: SPI frame size
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
+      \arg        SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
+    \param[out] none
+    \retval     none
+*/
+void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
+{
+    /* clear SPI_CTL0_FF16 bit */
+    SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
+    /* configure SPI_CTL0_FF16 bit */
+    SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
+}
+
+/*!
+    \brief      SPI transmit data
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  data: 16-bit data
+    \param[out] none
+    \retval     none
+*/
+void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
+{
+    SPI_DATA(spi_periph) = (uint32_t)data;
+}
+
+/*!
+    \brief      SPI receive data
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     16-bit data
+*/
+uint16_t spi_i2s_data_receive(uint32_t spi_periph)
+{
+    return ((uint16_t)SPI_DATA(spi_periph));
+}
+
+/*!
+    \brief      configure SPI bidirectional transfer direction
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  transfer_direction: SPI transfer direction
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
+      \arg        SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
+    \param[out] none
+    \retval     none
+*/
+void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
+{
+    if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){
+        /* set the transmit only mode */
+        SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
+    }else{
+        /* set the receive only mode */
+        SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
+    }
+}
+
+/*!
+    \brief      set CRC polynomial 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  crc_poly: CRC polynomial value
+    \param[out] none
+    \retval     none
+*/
+void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly)
+{
+    /* enable SPI CRC */
+    SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
+    /* set SPI CRC polynomial */
+    SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
+}
+
+/*!
+    \brief      get SPI CRC polynomial 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     16-bit CRC polynomial
+*/
+uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
+{
+    return ((uint16_t)SPI_CRCPOLY(spi_periph));
+}
+
+/*!
+    \brief      turn on CRC function 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_crc_on(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
+}
+
+/*!
+    \brief      turn off CRC function 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_crc_off(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
+}
+/*!
+    \brief      SPI next data is CRC value
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_crc_next(uint32_t spi_periph)
+{
+    SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
+}
+
+/*!
+    \brief      get SPI CRC send value or receive value
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  crc: SPI crc value
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_CRC_TX: get transmit crc value
+      \arg        SPI_CRC_RX: get receive crc value
+    \param[out] none
+    \retval     16-bit CRC value
+*/
+uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc)
+{
+    if(SPI_CRC_TX == crc){
+        return ((uint16_t)(SPI_TCRC(spi_periph)));
+    }else{
+        return ((uint16_t)(SPI_RCRC(spi_periph)));
+    }
+}
+
+/*!
+    \brief      enable SPI and I2S interrupt 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  interrupt: SPI/I2S interrupt
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_I2S_INT_TBE: transmit buffer empty interrupt
+      \arg        SPI_I2S_INT_RBNE: receive buffer not empty interrupt
+      \arg        SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
+                                   transmission underrun error and format error interrupt
+    \param[out] none
+    \retval     none
+*/
+void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
+{
+    switch(interrupt){
+    /* SPI/I2S transmit buffer empty interrupt */
+    case SPI_I2S_INT_TBE:
+        SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
+        break;
+    /* SPI/I2S receive buffer not empty interrupt */
+    case SPI_I2S_INT_RBNE:
+        SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
+        break;
+    /* SPI/I2S error */
+    case SPI_I2S_INT_ERR:
+        SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      disable SPI and I2S interrupt 
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  interrupt: SPI/I2S interrupt
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_I2S_INT_TBE: transmit buffer empty interrupt
+      \arg        SPI_I2S_INT_RBNE: receive buffer not empty interrupt
+      \arg        SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
+                                   transmission underrun error and format error interrupt
+    \param[out] none
+    \retval     none
+*/
+void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
+{
+    switch(interrupt){
+    /* SPI/I2S transmit buffer empty interrupt */
+    case SPI_I2S_INT_TBE:
+        SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
+        break;
+    /* SPI/I2S receive buffer not empty interrupt */
+    case SPI_I2S_INT_RBNE:
+        SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
+        break;
+    /* SPI/I2S error */
+    case SPI_I2S_INT_ERR:
+        SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
+        break;
+    default :
+        break;
+    }
+}
+
+/*!
+    \brief      get SPI and I2S interrupt flag status
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  interrupt: SPI/I2S interrupt flag status
+                only one parameter can be selected which is shown as below:
+      \arg        SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
+      \arg        SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
+      \arg        SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
+      \arg        SPI_INT_FLAG_CONFERR: config error interrupt flag
+      \arg        SPI_INT_FLAG_CRCERR: CRC error interrupt flag
+      \arg        I2S_INT_FLAG_TXURERR: underrun error interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
+{
+    uint32_t reg1 = SPI_STAT(spi_periph);
+    uint32_t reg2 = SPI_CTL1(spi_periph);
+
+    switch(interrupt){
+    /* SPI/I2S transmit buffer empty interrupt */
+    case SPI_I2S_INT_FLAG_TBE:
+        reg1 = reg1 & SPI_STAT_TBE;
+        reg2 = reg2 & SPI_CTL1_TBEIE;
+        break;
+    /* SPI/I2S receive buffer not empty interrupt */
+    case SPI_I2S_INT_FLAG_RBNE:
+        reg1 = reg1 & SPI_STAT_RBNE;
+        reg2 = reg2 & SPI_CTL1_RBNEIE;
+        break;
+    /* SPI/I2S overrun interrupt */
+    case SPI_I2S_INT_FLAG_RXORERR:
+        reg1 = reg1 & SPI_STAT_RXORERR;
+        reg2 = reg2 & SPI_CTL1_ERRIE;
+        break;
+    /* SPI config error interrupt */
+    case SPI_INT_FLAG_CONFERR:
+        reg1 = reg1 & SPI_STAT_CONFERR;
+        reg2 = reg2 & SPI_CTL1_ERRIE;
+        break;
+    /* SPI CRC error interrupt */
+    case SPI_INT_FLAG_CRCERR:
+        reg1 = reg1 & SPI_STAT_CRCERR;
+        reg2 = reg2 & SPI_CTL1_ERRIE;
+        break;
+    /* I2S underrun error interrupt */
+    case I2S_INT_FLAG_TXURERR:
+        reg1 = reg1 & SPI_STAT_TXURERR;
+        reg2 = reg2 & SPI_CTL1_ERRIE;
+        break;
+    default :
+        break;
+    }
+    /*get SPI/I2S interrupt flag status */
+    if((0U != reg1) && (0U != reg2)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      get SPI and I2S flag status
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[in]  flag: SPI/I2S flag status
+                one or more parameters can be selected which are shown as below:
+      \arg        SPI_FLAG_TBE: transmit buffer empty flag
+      \arg        SPI_FLAG_RBNE: receive buffer not empty flag
+      \arg        SPI_FLAG_TRANS: transmit on-going flag
+      \arg        SPI_FLAG_RXORERR: receive overrun error flag
+      \arg        SPI_FLAG_CONFERR: mode config error flag
+      \arg        SPI_FLAG_CRCERR: CRC error flag
+      \arg        I2S_FLAG_RXORERR: overrun error flag
+      \arg        I2S_FLAG_TXURERR: underrun error flag
+      \arg        I2S_FLAG_CH: channel side flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
+{
+    if(RESET != (SPI_STAT(spi_periph) & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear SPI CRC error flag status
+    \param[in]  spi_periph: SPIx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void spi_crc_error_clear(uint32_t spi_periph)
+{
+    SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR);
+}

+ 2002 - 0
Library/Source/gd32f10x_timer.c

@@ -0,0 +1,2002 @@
+/*!
+    \file    gd32f10x_timer.c
+    \brief   TIMER driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_timer.h"
+
+/* TIMER init parameter mask */
+#define ALIGNEDMODE_MASK            ((uint32_t)0x00000060U)   /*!< TIMER init parameter aligne dmode mask */
+#define COUNTERDIRECTION_MASK       ((uint32_t)0x00000010U)   /*!< TIMER init parameter counter direction mask */
+#define CLOCKDIVISION_MASK          ((uint32_t)0x00000300U)   /*!< TIMER init parameter clock division value mask */
+
+/*!
+    \brief      deinit a TIMER
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_deinit(uint32_t timer_periph)
+{
+    switch(timer_periph){
+    case TIMER0:
+        /* reset TIMER0 */
+        rcu_periph_reset_enable(RCU_TIMER0RST);
+        rcu_periph_reset_disable(RCU_TIMER0RST);
+        break;
+    case TIMER1:
+        /* reset TIMER1 */
+        rcu_periph_reset_enable(RCU_TIMER1RST);
+        rcu_periph_reset_disable(RCU_TIMER1RST);
+        break;
+    case TIMER2:
+        /* reset TIMER2 */
+        rcu_periph_reset_enable(RCU_TIMER2RST);
+        rcu_periph_reset_disable(RCU_TIMER2RST);
+        break;
+    case TIMER3:
+        /* reset TIMER3 */
+        rcu_periph_reset_enable(RCU_TIMER3RST);
+        rcu_periph_reset_disable(RCU_TIMER3RST);
+        break;
+    case TIMER4:
+        /* reset TIMER4 */
+        rcu_periph_reset_enable(RCU_TIMER4RST);
+        rcu_periph_reset_disable(RCU_TIMER4RST);
+        break;
+    case TIMER5:
+        /* reset TIMER5 */
+        rcu_periph_reset_enable(RCU_TIMER5RST);
+        rcu_periph_reset_disable(RCU_TIMER5RST);
+        break;
+    case TIMER6:
+        /* reset TIMER6 */
+        rcu_periph_reset_enable(RCU_TIMER6RST);
+        rcu_periph_reset_disable(RCU_TIMER6RST);
+        break;
+    case TIMER7:
+        /* reset TIMER7 */
+        rcu_periph_reset_enable(RCU_TIMER7RST);
+        rcu_periph_reset_disable(RCU_TIMER7RST);
+        break;
+#ifdef GD32F10X_XD
+    case TIMER8:
+        /* reset TIMER8 */
+        rcu_periph_reset_enable(RCU_TIMER8RST);
+        rcu_periph_reset_disable(RCU_TIMER8RST);
+        break;
+    case TIMER9:
+        /* reset TIMER9 */
+        rcu_periph_reset_enable(RCU_TIMER9RST);
+        rcu_periph_reset_disable(RCU_TIMER9RST);
+        break;
+    case TIMER10:
+        /* reset TIMER10 */
+        rcu_periph_reset_enable(RCU_TIMER10RST);
+        rcu_periph_reset_disable(RCU_TIMER10RST);
+        break;
+    case TIMER11:
+        /* reset TIMER11 */
+        rcu_periph_reset_enable(RCU_TIMER11RST);
+        rcu_periph_reset_disable(RCU_TIMER11RST);
+        break;
+    case TIMER12:
+        /* reset TIMER12 */
+        rcu_periph_reset_enable(RCU_TIMER12RST);
+        rcu_periph_reset_disable(RCU_TIMER12RST);
+        break;
+    case TIMER13:
+        /* reset TIMER13 */
+        rcu_periph_reset_enable(RCU_TIMER13RST);
+        rcu_periph_reset_disable(RCU_TIMER13RST);
+        break;
+#endif /* GD32F10X_XD */
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      initialize TIMER init parameter struct with a default value
+    \param[in]  initpara: init parameter struct
+    \param[out] none
+    \retval     none
+*/
+void timer_struct_para_init(timer_parameter_struct* initpara)
+{
+    /* initialize the init parameter struct member with the default value */
+    initpara->prescaler         = 0U;
+    initpara->alignedmode       = TIMER_COUNTER_EDGE;
+    initpara->counterdirection  = TIMER_COUNTER_UP;
+    initpara->period            = 65535U;
+    initpara->clockdivision     = TIMER_CKDIV_DIV1;
+    initpara->repetitioncounter = 0U;
+}
+
+/*!
+    \brief      initialize TIMER counter
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[in]  initpara: init parameter struct
+                prescaler: prescaler value of the counter clock,0~65535
+                alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,
+                             TIMER_COUNTER_CENTER_BOTH
+                counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN
+                period: counter auto reload value,0~65535
+                clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4
+                repetitioncounter: counter repetition value,0~255
+    \param[out] none
+    \retval     none
+*/
+void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara)
+{
+    /* configure the counter prescaler value */
+    TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler;
+
+    /* configure the counter direction and aligned mode */
+    if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) ||
+       (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) ||
+       (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){
+        TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM));
+        TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK);
+        TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK);
+    }
+
+    /* configure the autoreload value */
+    TIMER_CAR(timer_periph) = (uint32_t)initpara->period;
+
+    if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){
+        /* reset the CKDIV bit */
+        TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV);
+        TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK);
+    }
+
+    if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){
+        /* configure the repetition counter value */
+        TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter;
+    }
+
+    /* generate an update event */
+    TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG;
+}
+
+/*!
+    \brief      enable a TIMER
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_enable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN;
+}
+
+/*!
+    \brief      disable a TIMER
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_disable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN;
+}
+
+/*!
+    \brief      enable the auto reload shadow function
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_auto_reload_shadow_enable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE;
+}
+
+/*!
+    \brief      disable the auto reload shadow function
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_auto_reload_shadow_disable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE;
+}
+
+/*!
+    \brief      enable the update event
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_update_event_enable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS;
+}
+
+/*!
+    \brief      disable the update event
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_update_event_disable(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS;
+}
+
+/*!
+    \brief      set TIMER counter alignment mode
+    \param[in]  timer_periph: TIMERx(x=0..4,7..13)
+    \param[in]  aligned:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_COUNTER_EDGE: edge-aligned mode
+      \arg        TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode
+      \arg        TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode
+      \arg        TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode
+    \param[out] none
+    \retval     none
+*/
+void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned)
+{
+    TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM;
+    TIMER_CTL0(timer_periph) |= (uint32_t)aligned;
+}
+
+/*!
+    \brief      set TIMER counter up direction
+    \param[in]  timer_periph: TIMERx(x=0..4,7..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_counter_up_direction(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR;
+}
+
+/*!
+    \brief      set TIMER counter down direction
+    \param[in]  timer_periph: TIMERx(x=0..4,7..13)
+    \param[out] none
+    \retval     none
+*/
+void timer_counter_down_direction(uint32_t timer_periph)
+{
+    TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR;
+}
+
+/*!
+    \brief      configure TIMER prescaler
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[in]  prescaler: prescaler value
+    \param[in]  pscreload: prescaler reload mode
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now
+      \arg        TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event
+    \param[out] none
+    \retval     none
+*/
+void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload)
+{
+    TIMER_PSC(timer_periph) = (uint32_t)prescaler;
+    
+    if(TIMER_PSC_RELOAD_NOW == pscreload){
+        TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG;
+    }
+}
+
+/*!
+    \brief      configure TIMER repetition register value
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  repetition: the counter repetition value,0~255
+    \param[out] none
+    \retval     none
+*/
+void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition)
+{
+    TIMER_CREP(timer_periph) = (uint32_t)repetition;
+} 
+ 
+/*!
+    \brief      configure TIMER autoreload register value
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[in]  autoreload: the counter auto-reload value
+    \param[out] none
+    \retval     none
+*/         
+void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload)
+{
+    TIMER_CAR(timer_periph) = (uint32_t)autoreload;
+}
+
+/*!
+    \brief      configure TIMER counter register value
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[in]  counter: the counter value
+    \param[out] none
+    \retval     none
+*/         
+void timer_counter_value_config(uint32_t timer_periph, uint32_t counter)
+{
+    TIMER_CNT(timer_periph) = (uint32_t)counter;
+}
+
+/*!
+    \brief      read TIMER counter value
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     counter value
+*/         
+uint32_t timer_counter_read(uint32_t timer_periph)
+{
+    uint32_t count_value = 0U;
+    count_value = TIMER_CNT(timer_periph);
+    return (count_value);
+}
+
+/*!
+    \brief      read TIMER prescaler value
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[out] none
+    \retval     prescaler register value
+*/         
+uint16_t timer_prescaler_read(uint32_t timer_periph)
+{
+    uint16_t prescaler_value = 0U;
+    prescaler_value = (uint16_t)(TIMER_PSC(timer_periph));
+    return (prescaler_value);
+}
+
+/*!
+    \brief      configure TIMER single pulse mode
+    \param[in]  timer_periph: TIMERx(x=0..8,11)
+    \param[in]  spmode:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_SP_MODE_SINGLE: single pulse mode
+      \arg        TIMER_SP_MODE_REPETITIVE: repetitive pulse mode
+    \param[out] none
+    \retval     none
+*/
+void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode)
+{
+    if(TIMER_SP_MODE_SINGLE == spmode){
+        TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM;
+    }else if(TIMER_SP_MODE_REPETITIVE == spmode){
+        TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM);
+    }else{
+        /* illegal parameters */        
+    }
+}
+
+/*!
+    \brief      configure TIMER update source 
+    \param[in]  timer_periph: TIMERx(x=0..13)
+    \param[in]  update:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,
+                  or the slave mode controller trigger
+      \arg        TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow
+    \param[out] none
+    \retval     none
+*/
+void timer_update_source_config(uint32_t timer_periph, uint32_t update)
+{
+    if(TIMER_UPDATE_SRC_REGULAR == update){
+        TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS;
+    }else if(TIMER_UPDATE_SRC_GLOBAL == update){
+        TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS;
+    }else{
+        /* illegal parameters */
+    }
+}
+
+/*!
+    \brief      enable the TIMER DMA
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  dma: timer DMA source enable
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_DMA_UPD:  update DMA enable,TIMERx(x=0..7)
+      \arg        TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7)
+      \arg        TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_dma_enable(uint32_t timer_periph, uint16_t dma)
+{
+    TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; 
+}
+
+/*!
+    \brief      disable the TIMER DMA
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  dma: timer DMA source disable
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_DMA_UPD:  update DMA disable,TIMERx(x=0..7)
+      \arg        TIMER_DMA_CH0D: channel 0 DMA disable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7)
+      \arg        TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7)
+      \arg        TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_dma_disable(uint32_t timer_periph, uint16_t dma)
+{
+    TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); 
+}
+
+/*!
+    \brief      channel DMA request source selection
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[in]  dma_request: channel DMA request source selection
+                only one parameter can be selected which is shown as below:
+       \arg        TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs
+       \arg        TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs 
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request)
+{
+    if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){
+        TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS;
+    }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){
+        TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS;
+    }else{
+        /* illegal parameters */        
+    }
+}
+
+/*!
+    \brief      configure the TIMER DMA transfer
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  dma_baseaddr:
+                only one parameter can be selected which is shown as below:
+       \arg        TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7)
+       \arg        TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7)
+       \arg        TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7)
+       \arg        TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7)
+    \param[in]  dma_lenth:
+                only one parameter can be selected which is shown as below:
+       \arg        TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time
+    \param[out] none
+    \retval     none
+*/
+void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth)
+{
+    TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC));
+    TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth);
+}
+
+/*!
+    \brief      software generate events 
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  event: the timer software event generation sources
+                one or more parameters can be selected which are shown as below:
+      \arg        TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13)
+      \arg        TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) 
+      \arg        TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) 
+      \arg        TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) 
+      \arg        TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) 
+      \arg        TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_EVENT_SRC_BRKG:  break event generation, TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_event_software_generate(uint32_t timer_periph, uint16_t event)
+{
+    TIMER_SWEVG(timer_periph) |= (uint32_t)event;
+}
+
+/*!
+    \brief      initialize TIMER break parameter struct with a default value
+    \param[in]  breakpara: TIMER break parameter struct
+    \param[out] none
+    \retval     none
+*/
+void timer_break_struct_para_init(timer_break_parameter_struct* breakpara)
+{
+    /* initialize the break parameter struct member with the default value */
+    breakpara->runoffstate     = TIMER_ROS_STATE_DISABLE;
+    breakpara->ideloffstate    = TIMER_IOS_STATE_DISABLE;
+    breakpara->deadtime        = 0U;
+    breakpara->breakpolarity   = TIMER_BREAK_POLARITY_LOW;
+    breakpara->outputautostate = TIMER_OUTAUTO_DISABLE;
+    breakpara->protectmode     = TIMER_CCHP_PROT_OFF;
+    breakpara->breakstate      = TIMER_BREAK_DISABLE;
+}
+
+/*!
+    \brief      configure TIMER break function 
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  breakpara: TIMER break parameter struct
+                runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE
+                ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE
+                deadtime: 0~255
+                breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH
+                outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE
+                protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2
+                breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE
+    \param[out] none
+    \retval     none
+*/
+void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara)
+{
+    TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) |
+                                          ((uint32_t)(breakpara->ideloffstate)) |
+                                          ((uint32_t)(breakpara->deadtime)) |
+                                          ((uint32_t)(breakpara->breakpolarity)) |
+                                          ((uint32_t)(breakpara->outputautostate)) |
+                                          ((uint32_t)(breakpara->protectmode)) |
+                                          ((uint32_t)(breakpara->breakstate))) ;
+}
+
+/*!
+    \brief      enable TIMER break function
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_break_enable(uint32_t timer_periph)
+{
+    TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN;
+}
+
+/*!
+    \brief      disable TIMER break function
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_break_disable(uint32_t timer_periph)
+{
+    TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN;
+}
+
+/*!
+    \brief      enable TIMER output automatic function
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_automatic_output_enable(uint32_t timer_periph)
+{
+    TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN;
+}
+
+/*!
+    \brief      disable TIMER output automatic function
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_automatic_output_disable(uint32_t timer_periph)
+{
+    TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN;
+}
+
+/*!
+    \brief      enable or disable TIMER primary output function
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  newvalue: ENABLE or DISABLE
+    \param[out] none
+    \retval     none
+*/
+void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue)
+{
+    if(ENABLE == newvalue){
+        TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN;
+    }else{
+        TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN);
+    }
+}
+
+/*!
+    \brief      enable or disable channel capture/compare control shadow register 
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  newvalue: ENABLE or DISABLE 
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue)
+{
+     if(ENABLE == newvalue){
+        TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE;
+    }else{
+        TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE);
+    }
+}
+
+/*!
+    \brief      configure TIMER channel control shadow register update control
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  ccuctl: channel control shadow register update control
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set
+      \arg        TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs 
+    \param[out] none
+    \retval     none
+*/              
+void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl)
+{
+    if(TIMER_UPDATECTL_CCU == ccuctl){
+        TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC);
+    }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){
+        TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC;
+    }else{
+        /* illegal parameters */        
+    }
+}
+
+/*!
+    \brief      initialize TIMER channel output parameter struct with a default value
+    \param[in]  ocpara: TIMER channel n output parameter struct
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara)
+{
+    /* initialize the channel output parameter struct member with the default value */
+    ocpara->outputstate  = TIMER_CCX_DISABLE;
+    ocpara->outputnstate = TIMER_CCXN_DISABLE;
+    ocpara->ocpolarity   = TIMER_OC_POLARITY_HIGH;
+    ocpara->ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
+    ocpara->ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
+    ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
+}
+
+/*!
+    \brief      configure TIMER channel output function
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7))
+    \param[in]  ocpara: TIMER channeln output parameter struct
+                outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE
+                outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE
+                ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW
+                ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW
+                ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH
+                ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        /* reset the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+        TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS;
+        /* set the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate;
+        /* reset the CH0P bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P);
+        /* set the CH0P bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity;
+
+        if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){
+            /* reset the CH0NEN bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN);
+            /* set the CH0NEN bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate;
+            /* reset the CH0NP bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP);
+            /* set the CH0NP bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity;
+            /* reset the ISO0 bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0);
+            /* set the ISO0 bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate;
+            /* reset the ISO0N bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N);
+            /* set the ISO0N bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate;
+        }
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        /* reset the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+        TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS;
+        /* set the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U);
+        /* reset the CH1P bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P);
+        /* set the CH1P bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U);
+
+        if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){
+            /* reset the CH1NEN bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN);
+            /* set the CH1NEN bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U);
+            /* reset the CH1NP bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP);
+            /* set the CH1NP bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U);
+            /* reset the ISO1 bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1);
+            /* set the ISO1 bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U);
+            /* reset the ISO1N bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N);
+            /* set the ISO1N bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U);
+        }
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        /* reset the CH2EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN);
+        TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS;
+        /* set the CH2EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U);
+        /* reset the CH2P bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P);
+        /* set the CH2P bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U);
+
+        if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){
+            /* reset the CH2NEN bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN);
+            /* set the CH2NEN bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U);
+            /* reset the CH2NP bit */
+            TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP);
+            /* set the CH2NP bit */
+            TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U);
+            /* reset the ISO2 bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2);
+            /* set the ISO2 bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U);
+            /* reset the ISO2N bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N);
+            /* set the ISO2N bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U);
+        }
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        /* reset the CH3EN bit */
+        TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN);
+        TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS;
+        /* set the CH3EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U);
+        /* reset the CH3P bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P);
+        /* set the CH3P bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U);
+
+        if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){
+            /* reset the ISO3 bit */
+            TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3);
+            /* set the ISO3 bit */
+            TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output compare mode
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  ocmode: channel output compare mode
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OC_MODE_TIMING: timing mode
+      \arg        TIMER_OC_MODE_ACTIVE: active mode
+      \arg        TIMER_OC_MODE_INACTIVE: inactive mode
+      \arg        TIMER_OC_MODE_TOGGLE: toggle mode
+      \arg        TIMER_OC_MODE_LOW: force low mode
+      \arg        TIMER_OC_MODE_HIGH: force high mode
+      \arg        TIMER_OC_MODE_PWM0: PWM0 mode
+      \arg        TIMER_OC_MODE_PWM1: PWM1 mode
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output pulse value
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  pulse: channel output pulse value
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CH0CV(timer_periph) = (uint32_t)pulse;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CH1CV(timer_periph) = (uint32_t)pulse;
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CH2CV(timer_periph) = (uint32_t)pulse;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+         TIMER_CH3CV(timer_periph) = (uint32_t)pulse;
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output shadow function
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  ocshadow: channel output shadow state
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OC_SHADOW_ENABLE: channel output shadow state enable
+      \arg        TIMER_OC_SHADOW_DISABLE: channel output shadow state disable
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output fast function
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  ocfast: channel output fast function
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OC_FAST_ENABLE: channel output fast function enable
+      \arg        TIMER_OC_FAST_DISABLE: channel output fast function disable
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output clear function
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0
+      \arg        TIMER_CH_1: TIMER channel1
+      \arg        TIMER_CH_2: TIMER channel2
+      \arg        TIMER_CH_3: TIMER channel3
+    \param[in]  occlear: channel output clear function
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OC_CLEAR_ENABLE: channel output clear function enable
+      \arg        TIMER_OC_CLEAR_DISABLE: channel output clear function disable
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel output polarity 
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  ocpolarity: channel output polarity
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OC_POLARITY_HIGH: channel output polarity is high
+      \arg        TIMER_OC_POLARITY_LOW: channel output polarity is low
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U);
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel complementary output polarity 
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+    \param[in]  ocnpolarity: channel complementary output polarity 
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high
+      \arg        TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel enable state
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  state: TIMER channel enable state
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CCX_ENABLE: channel enable 
+      \arg        TIMER_CCX_DISABLE: channel disable 
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)state;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U);
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure TIMER channel complementary output enable state
+    \param[in]  timer_periph: TIMERx(x=0,7)
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0
+      \arg        TIMER_CH_1: TIMER channel1
+      \arg        TIMER_CH_2: TIMER channel2
+    \param[in]  ocnstate: TIMER channel complementary output enable state
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CCXN_ENABLE: channel complementary enable 
+      \arg        TIMER_CCXN_DISABLE: channel complementary disable 
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN);
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      initialize TIMER channel input parameter struct with a default value
+    \param[in]  icpara: TIMER channel intput parameter struct
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara)
+{
+    /* initialize the channel input parameter struct member with the default value */
+    icpara->icpolarity  = TIMER_IC_POLARITY_RISING;
+    icpara->icselection = TIMER_IC_SELECTION_DIRECTTI;
+    icpara->icprescaler = TIMER_IC_PSC_DIV1;
+    icpara->icfilter    = 0U;
+}
+
+/*!
+    \brief      configure TIMER input capture parameter 
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below: 
+      \arg        TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7))
+    \param[in]  icpara: TIMER channel intput parameter struct
+                  icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING
+                  icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI,
+                               TIMER_IC_SELECTION_ITS
+                  icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4,
+                               TIMER_IC_PSC_DIV8
+                  icfilter: 0~15
+    \param[out]  none
+    \retval      none
+*/
+void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        /* reset the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+
+        /* reset the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP));
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity);
+        /* reset the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection);
+        /* reset the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U);
+
+        /* set the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN;
+        break;
+    
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        /* reset the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+
+        /* reset the CH1P and CH1NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP));
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U);
+        /* reset the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U);
+        /* reset the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U);
+
+        /* set the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN;
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        /* reset the CH2EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN);
+
+        /* reset the CH2P and CH2NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP));
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U);
+
+        /* reset the CH2MS bit */
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection));
+
+        /* reset the CH2CAPFLT bit */
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U);
+
+        /* set the CH2EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        /* reset the CH3EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN);
+
+        /* reset the CH3P bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P));
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U);
+
+        /* reset the CH3MS bit */
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U);
+
+        /* reset the CH3CAPFLT bit */
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U);
+
+        /* set the CH3EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN;
+        break;
+    default:
+        break;
+    }
+    /* configure TIMER channel input capture prescaler value */
+    timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler));
+}
+
+/*!
+    \brief      configure TIMER channel input capture prescaler value
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[in]  prescaler: channel input capture prescaler value
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_IC_PSC_DIV1: no prescaler
+      \arg        TIMER_IC_PSC_DIV2: divided by 2
+      \arg        TIMER_IC_PSC_DIV4: divided by 4
+      \arg        TIMER_IC_PSC_DIV8: divided by 8
+    \param[out] none
+    \retval     none
+*/
+void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler)
+{
+    switch(channel){
+    /* configure TIMER_CH_0 */
+    case TIMER_CH_0:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC);
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler;
+        break;
+    /* configure TIMER_CH_1 */
+    case TIMER_CH_1:
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC);
+        TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U);
+        break;
+    /* configure TIMER_CH_2 */
+    case TIMER_CH_2:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC);
+        TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler;
+        break;
+    /* configure TIMER_CH_3 */
+    case TIMER_CH_3:
+        TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC);
+        TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      read TIMER channel capture compare register value
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13))
+      \arg        TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11))
+      \arg        TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7))
+      \arg        TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7))
+    \param[out] none
+    \retval     channel capture compare register value
+*/
+uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel)
+{
+    uint32_t count_value = 0U;
+
+    switch(channel){
+    case TIMER_CH_0:
+        /* read TIMER channel 0 capture compare register value */
+        count_value = TIMER_CH0CV(timer_periph);
+        break;
+    case TIMER_CH_1:
+        /* read TIMER channel 1 capture compare register value */
+        count_value = TIMER_CH1CV(timer_periph);
+        break;
+    case TIMER_CH_2:
+        /* read TIMER channel 2 capture compare register value */
+        count_value = TIMER_CH2CV(timer_periph);
+        break;
+    case TIMER_CH_3:
+        /* read TIMER channel 3 capture compare register value */
+        count_value = TIMER_CH3CV(timer_periph);
+        break;
+    default:
+        break;
+    }
+    return (count_value);
+}
+
+/*!
+    \brief      configure TIMER input pwm capture function 
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  channel:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_CH_0: TIMER channel0
+      \arg        TIMER_CH_1: TIMER channel1
+     \param[in]  icpwm:TIMER channel intput pwm parameter struct
+                 icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING
+                 icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI
+                 icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8
+                 icfilter: 0~15
+    \param[out] none
+    \retval     none
+*/
+void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm)
+{
+    uint16_t icpolarity  = 0x0U;
+    uint16_t icselection = 0x0U;
+
+    /* Set channel input polarity */
+    if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){
+        icpolarity = TIMER_IC_POLARITY_FALLING;
+    }else{
+        icpolarity = TIMER_IC_POLARITY_RISING;
+    }
+    /* Set channel input mode selection */
+    if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){
+        icselection = TIMER_IC_SELECTION_INDIRECTTI;
+    }else{
+        icselection = TIMER_IC_SELECTION_DIRECTTI;
+    }
+
+    if(TIMER_CH_0 == channel){
+        /* reset the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+        /* reset the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP));
+        /* set the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity);
+        /* reset the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS);
+        /* set the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection);
+        /* reset the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT);
+        /* set the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U);
+        /* set the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN;
+        /* configure TIMER channel input capture prescaler value */
+        timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler));
+
+        /* reset the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+        /* reset the CH1P and CH1NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP));
+        /* set the CH1P and CH1NP bits */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U);
+        /* reset the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS);
+        /* set the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U);
+        /* reset the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT);
+        /* set the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U);
+        /* set the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN;
+        /* configure TIMER channel input capture prescaler value */
+        timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler));
+    }else{
+        /* reset the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+        /* reset the CH1P and CH1NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP));
+        /* set the CH1P and CH1NP bits */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U);
+        /* reset the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS);
+        /* set the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U);
+        /* reset the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT);
+        /* set the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U);
+        /* set the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN;
+        /* configure TIMER channel input capture prescaler value */
+        timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler));
+
+        /* reset the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+        /* reset the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP));
+        /* set the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity;
+        /* reset the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS);
+        /* set the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection;
+        /* reset the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT);
+        /* set the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U);
+        /* set the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN;
+        /* configure TIMER channel input capture prescaler value */
+        timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler));
+    }
+}
+
+/*!
+    \brief      configure TIMER hall sensor mode
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[in]  hallmode:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable
+      \arg        TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable
+    \param[out] none
+    \retval     none
+*/
+void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode)    
+{
+    if(TIMER_HALLINTERFACE_ENABLE == hallmode){
+        TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S;
+    }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){
+        TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S;
+    }else{
+        /* illegal parameters */        
+    }
+}
+
+/*!
+    \brief      select TIMER input trigger source 
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  intrigger:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger)
+{
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS);
+    TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger;
+}
+
+/*!
+    \brief      select TIMER master mode output trigger source 
+    \param[in]  timer_periph: TIMERx(x=0..7)
+    \param[in]  outrigger:
+                only one parameter can be selected which is shown as below: 
+      \arg        TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7))
+      \arg        TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7))
+      \arg        TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7))
+      \arg        TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4,7))
+      \arg        TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7))
+      \arg        TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7))
+      \arg        TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7))
+      \arg        TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7))
+    \param[out] none
+    \retval     none
+*/
+void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger)
+{
+    TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC);
+    TIMER_CTL1(timer_periph) |= (uint32_t)outrigger;
+}
+
+/*!
+    \brief      select TIMER slave mode 
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  slavemode:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_SLAVE_MODE_DISABLE: slave mode disable
+      \arg        TIMER_ENCODER_MODE0: encoder mode 0
+      \arg        TIMER_ENCODER_MODE1: encoder mode 1
+      \arg        TIMER_ENCODER_MODE2: encoder mode 2
+      \arg        TIMER_SLAVE_MODE_RESTART: restart mode
+      \arg        TIMER_SLAVE_MODE_PAUSE: pause mode
+      \arg        TIMER_SLAVE_MODE_EVENT: event mode
+      \arg        TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0.
+    \param[out] none
+    \retval     none
+*/
+
+void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode)
+{
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC);
+
+    TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode;
+}
+
+/*!
+    \brief      configure TIMER master slave mode 
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  masterslave:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable
+      \arg        TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable
+    \param[out] none
+    \retval     none
+*/ 
+void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave)
+{
+    if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){
+        TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM;
+    }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){
+        TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM;
+    }else{
+        /* illegal parameters */        
+    }
+}
+
+/*!
+    \brief      configure TIMER external trigger input
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[in]  extprescaler:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_EXT_TRI_PSC_OFF: no divided
+      \arg        TIMER_EXT_TRI_PSC_DIV2: divided by 2
+      \arg        TIMER_EXT_TRI_PSC_DIV4: divided by 4
+      \arg        TIMER_EXT_TRI_PSC_DIV8: divided by 8
+    \param[in]  expolarity:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_ETP_FALLING: active low or falling edge active
+      \arg        TIMER_ETP_RISING: active high or rising edge active
+    \param[in]  extfilter: a value between 0 and 15
+    \param[out] none
+    \retval     none
+*/
+void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter)
+{
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC));
+    TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity);
+    TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U);
+}
+
+/*!
+    \brief      configure TIMER quadrature decoder mode
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  decomode:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level
+      \arg        TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level
+      \arg        TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input
+    \param[in]  ic0polarity:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_IC_POLARITY_RISING: capture rising edge
+      \arg        TIMER_IC_POLARITY_FALLING: capture falling edge
+    \param[in]  ic1polarity:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_IC_POLARITY_RISING: capture rising edge
+      \arg        TIMER_IC_POLARITY_FALLING: capture falling edge
+    \param[out] none
+    \retval     none
+*/
+void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity)
+{
+    /* configure the quadrature decoder mode */
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC);
+    TIMER_SMCFG(timer_periph) |= (uint32_t)decomode;
+    /* configure input capture selection */
+    TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS)));
+    TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U));
+    /* configure channel input capture polarity */
+    TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP));
+    TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP));
+    TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U));
+}
+
+/*!
+    \brief      configure TIMER internal clock mode
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[out] none
+    \retval     none
+*/
+void timer_internal_clock_config(uint32_t timer_periph)
+{
+    TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC;
+}
+
+/*!
+    \brief      configure TIMER the internal trigger as external clock input
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  intrigger: 
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0
+      \arg        TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1
+      \arg        TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2
+      \arg        TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3
+    \param[out] none
+    \retval     none
+*/
+void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger)
+{
+    timer_input_trigger_source_select(timer_periph,intrigger);
+    TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC;
+    TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0;
+}
+
+/*!
+    \brief      configure TIMER the external trigger as external clock input
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  extrigger:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector
+      \arg        TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0
+      \arg        TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1
+    \param[in]  expolarity:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_IC_POLARITY_RISING: active high or rising edge active
+      \arg        TIMER_IC_POLARITY_FALLING: active low or falling edge active
+    \param[in]  extfilter: a value between 0 and 15
+    \param[out] none
+    \retval     none
+*/
+void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter)
+{
+    if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){
+        /* reset the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN);
+        /* reset the CH1NP bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP));
+        /* set the CH1NP bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U);
+        /* reset the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS);
+        /* set the CH1MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U);
+        /* reset the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT);
+        /* set the CH1CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U);
+        /* set the CH1EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN;
+    }else{
+        /* reset the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN);
+        /* reset the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP));
+        /* set the CH0P and CH0NP bits */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity;
+        /* reset the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS);
+        /* set the CH0MS bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI;
+        /* reset the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT);
+        /* reset the CH0CAPFLT bit */
+        TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U);
+        /* set the CH0EN bit */
+        TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN;
+    }
+    /* select TIMER input trigger source */
+    timer_input_trigger_source_select(timer_periph,extrigger);
+    /* reset the SMC bit */
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC);
+    /* set the SMC bit */
+    TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0;
+}
+
+/*!
+    \brief      configure TIMER the external clock mode0
+    \param[in]  timer_periph: TIMERx(x=0..4,7,8,11)
+    \param[in]  extprescaler:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_EXT_TRI_PSC_OFF: no divided
+      \arg        TIMER_EXT_TRI_PSC_DIV2: divided by 2
+      \arg        TIMER_EXT_TRI_PSC_DIV4: divided by 4
+      \arg        TIMER_EXT_TRI_PSC_DIV8: divided by 8
+    \param[in]  expolarity:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_ETP_FALLING: active low or falling edge active
+      \arg        TIMER_ETP_RISING: active high or rising edge active
+    \param[in]  extfilter: a value between 0 and 15
+    \param[out] none
+    \retval     none
+*/
+void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter)
+{
+    /* configure TIMER external trigger input */
+    timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter);
+    /* reset the SMC bit,TRGS bit */
+    TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS));
+    /* set the SMC bit,TRGS bit */
+    TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP);
+}
+
+/*!
+    \brief      configure TIMER the external clock mode1
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[in]  extprescaler:
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_EXT_TRI_PSC_OFF: no divided
+      \arg        TIMER_EXT_TRI_PSC_DIV2: divided by 2
+      \arg        TIMER_EXT_TRI_PSC_DIV4: divided by 4
+      \arg        TIMER_EXT_TRI_PSC_DIV8: divided by 8
+    \param[in]  extpolarity:
+                only one parameter can be selected which is shown as below:  
+      \arg        TIMER_ETP_FALLING: active low or falling edge active
+      \arg        TIMER_ETP_RISING: active high or rising edge active
+    \param[in]  extfilter: a value between 0 and 15
+    \param[out] none
+    \retval     none
+*/
+void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter)
+{
+    /* configure TIMER external trigger input */
+    timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter);
+    TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1;
+}
+
+/*!
+    \brief      disable TIMER the external clock mode1
+    \param[in]  timer_periph: TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_external_clock_mode1_disable(uint32_t timer_periph)
+{
+    TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1;
+}
+
+/*!
+    \brief      enable the TIMER interrupt
+    \param[in]  timer_periph: please refer to the following parameters 
+    \param[in]  interrupt: timer interrupt enable source
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13)
+      \arg        TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13)
+      \arg        TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7)
+      \arg        TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7)
+      \arg        TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7)
+      \arg        TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt)
+{
+    TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; 
+}
+
+/*!
+    \brief      disable the TIMER interrupt
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  interrupt: timer interrupt source disable
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13)
+      \arg        TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13)
+      \arg        TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7)
+      \arg        TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7)
+      \arg        TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7)
+      \arg        TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt)
+{
+    TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); 
+}
+
+/*!
+    \brief      get timer interrupt flag
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  interrupt: the timer interrupt bits
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13)
+      \arg        TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13)
+      \arg        TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7)
+      \arg        TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7)
+      \arg        TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) 
+      \arg        TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11)
+      \arg        TIMER_INT_FLAG_BRK:  break interrupt flag,TIMERx(x=0,7)
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)
+{
+    uint32_t val;
+    val = (TIMER_DMAINTEN(timer_periph) & interrupt);
+    if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear TIMER interrupt flag
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  interrupt: the timer interrupt bits
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13)
+      \arg        TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13)
+      \arg        TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7)
+      \arg        TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7)
+      \arg        TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) 
+      \arg        TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11)
+      \arg        TIMER_INT_FLAG_BRK:  break interrupt flag,TIMERx(x=0,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
+{
+    TIMER_INTF(timer_periph) = (~(uint32_t)interrupt);
+}
+
+/*!
+    \brief      get TIMER flags
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  flag: the timer interrupt flags
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_FLAG_UP: update flag,TIMERx(x=0..13)
+      \arg        TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13)
+      \arg        TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) 
+      \arg        TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) 
+      \arg        TIMER_FLAG_BRK: break flag,TIMERx(x=0,7)
+      \arg        TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11)
+      \arg        TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag)
+{
+    if(RESET != (TIMER_INTF(timer_periph) & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear TIMER flags
+    \param[in]  timer_periph: please refer to the following parameters
+    \param[in]  flag: the timer interrupt flags
+                only one parameter can be selected which is shown as below:
+      \arg        TIMER_FLAG_UP: update flag,TIMERx(x=0..13)
+      \arg        TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13)
+      \arg        TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) 
+      \arg        TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) 
+      \arg        TIMER_FLAG_BRK: break flag,TIMERx(x=0,7)
+      \arg        TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11)
+      \arg        TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11)
+      \arg        TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7)
+      \arg        TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7)
+    \param[out] none
+    \retval     none
+*/
+void timer_flag_clear(uint32_t timer_periph, uint32_t flag)
+{
+    TIMER_INTF(timer_periph) = (~(uint32_t)flag);
+}

+ 766 - 0
Library/Source/gd32f10x_usart.c

@@ -0,0 +1,766 @@
+/*!
+    \file    gd32f10x_usart.c
+    \brief   USART driver
+
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.1, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_usart.h"
+
+/*!
+    \brief      reset USART/UART 
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_deinit(uint32_t usart_periph)
+{
+    switch(usart_periph){
+    case USART0:
+        /* reset USART0 */
+        rcu_periph_reset_enable(RCU_USART0RST);
+        rcu_periph_reset_disable(RCU_USART0RST);
+        break;
+    case USART1:
+        /* reset USART1 */
+        rcu_periph_reset_enable(RCU_USART1RST);
+        rcu_periph_reset_disable(RCU_USART1RST);
+        break;
+    case USART2:
+        /* reset USART2 */
+        rcu_periph_reset_enable(RCU_USART2RST);
+        rcu_periph_reset_disable(RCU_USART2RST);
+        break;
+    case UART3:
+        /* reset UART3 */
+        rcu_periph_reset_enable(RCU_UART3RST);
+        rcu_periph_reset_disable(RCU_UART3RST);
+        break;
+    case UART4:
+        /* reset UART4 */
+        rcu_periph_reset_enable(RCU_UART4RST);
+        rcu_periph_reset_disable(RCU_UART4RST);
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure USART baud rate value
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  baudval: baud rate value
+    \param[out] none
+    \retval     none
+*/ 
+void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
+{
+    uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U;
+    switch(usart_periph){
+         /* get clock frequency */
+    case USART0:
+         /* get USART0 clock */
+         uclk=rcu_clock_freq_get(CK_APB2);
+         break;
+    case USART1:
+         /* get USART1 clock */
+         uclk=rcu_clock_freq_get(CK_APB1);
+         break;
+    case USART2:
+         /* get USART2 clock */
+         uclk=rcu_clock_freq_get(CK_APB1);
+         break;
+    case UART3:
+         /* get UART3 clock */
+         uclk=rcu_clock_freq_get(CK_APB1);
+         break;
+    case UART4:
+         /* get UART4 clock */
+         uclk=rcu_clock_freq_get(CK_APB1);
+         break;  
+    default:
+         break;
+    }
+    /* oversampling by 16, configure the value of USART_BAUD */
+    udiv = (uclk+baudval/2U)/baudval;
+    intdiv = udiv & (0x0000fff0U);
+    fradiv = udiv & (0x0000000fU);
+    USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
+}
+
+/*!
+    \brief     configure USART parity
+    \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in] paritycfg: configure USART parity
+               only one parameter can be selected which is shown as below:
+      \arg       USART_PM_NONE: no parity
+      \arg       USART_PM_ODD:  odd parity
+      \arg       USART_PM_EVEN: even parity 
+    \param[out] none
+    \retval     none
+*/
+void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
+{
+    /* clear USART_CTL0 PM,PCEN bits */
+    USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
+    /* configure USART parity mode */
+    USART_CTL0(usart_periph) |= paritycfg ;
+}
+
+/*!
+    \brief     configure USART word length
+    \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in] wlen: USART word length configure
+               only one parameter can be selected which is shown as below:
+      \arg       USART_WL_8BIT: 8 bits
+      \arg       USART_WL_9BIT: 9 bits
+    \param[out] none
+    \retval     none
+*/
+void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
+{
+    /* clear USART_CTL0 WL bit */
+    USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
+    /* configure USART word length */
+    USART_CTL0(usart_periph) |= wlen;
+}
+
+/*!
+    \brief     configure USART stop bit length
+    \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in] stblen: USART stop bit configure
+               only one parameter can be selected which is shown as below:
+      \arg       USART_STB_1BIT:   1 bit
+      \arg       USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4)
+      \arg       USART_STB_2BIT:   2 bits
+      \arg       USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
+{
+    /* clear USART_CTL1 STB bits */
+    USART_CTL1(usart_periph) &= ~USART_CTL1_STB; 
+    /* configure USART stop bits */
+    USART_CTL1(usart_periph) |= stblen;
+}
+/*!
+    \brief      enable USART
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_enable(uint32_t usart_periph)
+{
+    USART_CTL0(usart_periph) |= USART_CTL0_UEN;
+}
+
+/*!
+    \brief     disable USART
+    \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_disable(uint32_t usart_periph)
+{
+    USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN);
+}
+
+/*!
+    \brief      configure USART transmitter
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  txconfig: enable or disable USART transmitter
+                only one parameter can be selected which is shown as below:
+      \arg        USART_TRANSMIT_ENABLE: enable USART transmission
+      \arg        USART_TRANSMIT_DISABLE: disable USART transmission
+    \param[out] none
+    \retval     none
+*/
+void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL0(usart_periph);
+    ctl &= ~USART_CTL0_TEN;
+    ctl |= txconfig;
+    /* configure transfer mode */
+    USART_CTL0(usart_periph) = ctl;
+}
+
+/*!
+    \brief      configure USART receiver
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  rxconfig: enable or disable USART receiver
+                only one parameter can be selected which is shown as below:
+      \arg        USART_RECEIVE_ENABLE: enable USART reception
+      \arg        USART_RECEIVE_DISABLE: disable USART reception
+    \param[out] none
+    \retval     none
+*/
+void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL0(usart_periph);
+    ctl &= ~USART_CTL0_REN;
+    ctl |= rxconfig;
+    /* configure receiver mode */
+    USART_CTL0(usart_periph) = ctl;
+}
+
+/*!
+    \brief      USART transmit data function
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  data: data of transmission 
+    \param[out] none
+    \retval     none
+*/
+void usart_data_transmit(uint32_t usart_periph, uint16_t data)
+{
+    USART_DATA(usart_periph) = USART_DATA_DATA & data;
+}
+
+/*!
+    \brief      USART receive data function
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     data of received
+*/
+uint16_t usart_data_receive(uint32_t usart_periph)
+{
+    return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U));
+}
+
+/*!
+    \brief      configure the address of the USART in wake up by address match mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  addr: address of USART/UART
+    \param[out] none
+    \retval     none
+*/
+void usart_address_config(uint32_t usart_periph, uint8_t addr)
+{
+    USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
+    USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr);
+}
+
+/*!
+    \brief      receiver in mute mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_mute_mode_enable(uint32_t usart_periph)
+{
+    USART_CTL0(usart_periph) |= USART_CTL0_RWU;
+}
+
+/*!
+    \brief      receiver in active mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_mute_mode_disable(uint32_t usart_periph)
+{
+    USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU);
+}
+
+/*!
+    \brief      configure wakeup method in mute mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  wmethod: two methods be used to enter or exit the mute mode
+                only one parameter can be selected which is shown as below:
+      \arg        USART_WM_IDLE: idle line
+      \arg        USART_WM_ADDR: address mask
+    \param[out] none
+    \retval     none
+*/
+void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod)
+{
+    USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
+    USART_CTL0(usart_periph) |= wmethod;
+}
+
+/*!
+    \brief      enable LIN mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_lin_mode_enable(uint32_t usart_periph)
+{   
+    USART_CTL1(usart_periph) |= USART_CTL1_LMEN;
+}
+
+/*!
+    \brief      disable LIN mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_lin_mode_disable(uint32_t usart_periph)
+{   
+    USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN);
+}
+
+/*!
+    \brief      configure lin break frame length
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  lblen: lin break frame length
+                only one parameter can be selected which is shown as below:
+      \arg        USART_LBLEN_10B: 10 bits
+      \arg        USART_LBLEN_11B: 11 bits
+    \param[out] none
+    \retval     none
+*/
+void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen)
+{
+    USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
+    USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
+}
+
+/*!
+    \brief      send break frame
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_send_break(uint32_t usart_periph)
+{
+    USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD;
+}
+
+/*!
+    \brief      enable half duplex mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_halfduplex_enable(uint32_t usart_periph)
+{   
+    USART_CTL2(usart_periph) |= USART_CTL2_HDEN;
+}
+
+/*!
+    \brief      disable half duplex mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_halfduplex_disable(uint32_t usart_periph)
+{  
+    USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN);
+}
+
+/*!
+    \brief      enable CK pin in synchronous mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_synchronous_clock_enable(uint32_t usart_periph)
+{
+    USART_CTL1(usart_periph) |= USART_CTL1_CKEN;
+}
+
+/*!
+    \brief      disable CK pin in synchronous mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_synchronous_clock_disable(uint32_t usart_periph)
+{
+    USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN);
+}
+
+/*!
+    \brief      configure USART synchronous mode parameters
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[in]  clen: CK length
+                only one parameter can be selected which is shown as below:
+      \arg        USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame 
+      \arg        USART_CLEN_EN:   there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame
+    \param[in]  cph: clock phase
+                only one parameter can be selected which is shown as below:
+      \arg        USART_CPH_1CK: first clock transition is the first data capture edge 
+      \arg        USART_CPH_2CK: second clock transition is the first data capture edge
+    \param[in]  cpl: clock polarity
+                only one parameter can be selected which is shown as below:
+      \arg        USART_CPL_LOW:  steady low value on CK pin 
+      \arg        USART_CPL_HIGH: steady high value on CK pin
+    \param[out] none
+    \retval     none
+*/
+void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl)
+{
+    uint32_t ctl = 0U;
+    
+    /* read USART_CTL1 register */
+    ctl = USART_CTL1(usart_periph);
+    ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
+    /* set CK length, CK phase, CK polarity */
+    ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
+
+    USART_CTL1(usart_periph) = ctl;
+}
+
+/*!
+    \brief      configure guard time value in smartcard mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[in]  gaut: guard time value
+    \param[out] none
+    \retval     none
+*/
+void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut)
+{
+    USART_GP(usart_periph) &= ~(USART_GP_GUAT);
+    USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8));
+}
+
+/*!
+    \brief      enable smartcard mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_smartcard_mode_enable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) |= USART_CTL2_SCEN;
+}
+
+/*!
+    \brief      disable smartcard mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_smartcard_mode_disable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN);
+}
+
+/*!
+    \brief      enable NACK in smartcard mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) |= USART_CTL2_NKEN;
+}
+
+/*!
+    \brief      disable NACK in smartcard mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[out] none
+    \retval     none
+*/
+void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN);
+}
+
+/*!
+    \brief      enable IrDA mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_irda_mode_enable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) |= USART_CTL2_IREN;
+}
+
+/*!
+    \brief      disable IrDA mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[out] none
+    \retval     none
+*/
+void usart_irda_mode_disable(uint32_t usart_periph)
+{
+    USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN);
+}
+
+/*!
+    \brief      configure the peripheral clock prescaler in USART IrDA low-power mode
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  psc: 0x00-0xFF
+    \param[out] none
+    \retval     none
+*/
+void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
+{
+    USART_GP(usart_periph) &= ~(USART_GP_PSC);
+    USART_GP(usart_periph) |= psc;
+}
+
+/*!
+    \brief      configure IrDA low-power
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  irlp: IrDA low-power or normal
+                only one parameter can be selected which is shown as below:
+      \arg        USART_IRLP_LOW: low-power
+      \arg        USART_IRLP_NORMAL: normal
+    \param[out] none
+    \retval     none
+*/
+void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
+{
+    USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
+    USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
+}
+
+/*!
+    \brief      configure hardware flow control RTS
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[in]  rtsconfig: enable or disable RTS
+                only one parameter can be selected which is shown as below:
+      \arg        USART_RTS_ENABLE:  enable RTS
+      \arg        USART_RTS_DISABLE: disable RTS
+    \param[out] none
+    \retval     none
+*/
+void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL2(usart_periph);
+    ctl &= ~USART_CTL2_RTSEN;
+    ctl |= rtsconfig;
+    /* configure RTS */
+    USART_CTL2(usart_periph) = ctl;
+}
+
+/*!
+    \brief      configure hardware flow control CTS
+    \param[in]  usart_periph: USARTx(x=0,1,2)
+    \param[in]  ctsconfig: enable or disable CTS
+                only one parameter can be selected which is shown as below:
+      \arg        USART_CTS_ENABLE:  enable CTS
+      \arg        USART_CTS_DISABLE: disable CTS
+    \param[out] none
+    \retval     none
+*/
+void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL2(usart_periph);
+    ctl &= ~USART_CTL2_CTSEN;
+    ctl |= ctsconfig;
+    /* configure CTS */
+    USART_CTL2(usart_periph) = ctl;
+}
+
+/*!
+    \brief      configure USART DMA reception
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
+    \param[in]  dmacmd: enable or disable DMA for reception
+                only one parameter can be selected which is shown as below:
+      \arg        USART_DENR_ENABLE:  DMA enable for reception
+      \arg        USART_DENR_DISABLE: DMA disable for reception
+    \param[out] none
+    \retval     none
+*/
+void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL2(usart_periph);
+    ctl &= ~USART_CTL2_DENR;
+    ctl |= dmacmd;
+    /* configure DMA reception */
+    USART_CTL2(usart_periph) = ctl;
+}
+
+/*!
+    \brief      configure USART DMA transmission
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
+    \param[in]  dmacmd: enable or disable DMA for transmission
+                only one parameter can be selected which is shown as below:
+      \arg        USART_DENT_ENABLE:  DMA enable for transmission
+      \arg        USART_DENT_DISABLE: DMA disable for transmission
+    \param[out] none
+    \retval     none
+*/
+void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd)
+{
+    uint32_t ctl = 0U;
+    
+    ctl = USART_CTL2(usart_periph);
+    ctl &= ~USART_CTL2_DENT;
+    ctl |= dmacmd;
+    /* configure DMA transmission */
+    USART_CTL2(usart_periph) = ctl;
+}
+
+/*!
+    \brief      get flag in STAT register
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  flag: USART flags, refer to usart_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        USART_FLAG_CTSF: CTS change flag
+      \arg        USART_FLAG_LBDF: LIN break detected flag 
+      \arg        USART_FLAG_TBE: transmit data buffer empty 
+      \arg        USART_FLAG_TC: transmission complete 
+      \arg        USART_FLAG_RBNE: read data buffer not empty 
+      \arg        USART_FLAG_IDLEF: IDLE frame detected flag 
+      \arg        USART_FLAG_ORERR: overrun error 
+      \arg        USART_FLAG_NERR: noise error flag 
+      \arg        USART_FLAG_FERR: frame error flag 
+      \arg        USART_FLAG_PERR: parity error flag 
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
+{
+    if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear flag in STAT register
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  flag: USART flags, refer to usart_flag_enum
+                only one parameter can be selected which is shown as below:
+      \arg        USART_FLAG_CTSF: CTS change flag
+      \arg        USART_FLAG_LBDF: LIN break detected flag
+      \arg        USART_FLAG_TC: transmission complete
+      \arg        USART_FLAG_RBNE: read data buffer not empty
+    \param[out] none
+    \retval     none
+*/
+void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
+{
+    USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag));
+}
+
+/*!
+    \brief      enable USART interrupt
+     \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  int_flag
+                only one parameter can be selected which is shown as below:
+      \arg        USART_INT_PERR: parity error interrupt
+      \arg        USART_INT_TBE: transmitter buffer empty interrupt
+      \arg        USART_INT_TC: transmission complete interrupt
+      \arg        USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
+      \arg        USART_INT_IDLE: IDLE line detected interrupt
+      \arg        USART_INT_LBD: LIN break detected interrupt
+      \arg        USART_INT_ERR: error interrupt
+      \arg        USART_INT_CTS: CTS interrupt
+    \param[out] none
+    \retval     none
+*/
+void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag)
+{
+    USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag));
+}
+
+/*!
+    \brief      disable USART interrupt
+     \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  int_flag
+                only one parameter can be selected which is shown as below:
+      \arg        USART_INT_PERR: parity error interrupt
+      \arg        USART_INT_TBE: transmitter buffer empty interrupt
+      \arg        USART_INT_TC: transmission complete interrupt
+      \arg        USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
+      \arg        USART_INT_IDLE: IDLE line detected interrupt
+      \arg        USART_INT_LBD: LIN break detected interrupt
+      \arg        USART_INT_ERR: error interrupt
+      \arg        USART_INT_CTS: CTS interrupt
+    \param[out] none
+    \retval     none
+*/
+void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag)
+{
+    USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag));
+}
+
+/*!
+    \brief      get USART interrupt and flag status
+     \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  int_flag
+                only one parameter can be selected which is shown as below:
+      \arg        USART_INT_FLAG_PERR: parity error interrupt and flag
+      \arg        USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag
+      \arg        USART_INT_FLAG_TC: transmission complete interrupt and flag
+      \arg        USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag
+      \arg        USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag
+      \arg        USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag
+      \arg        USART_INT_FLAG_LBD: LIN break detected interrupt and flag
+      \arg        USART_INT_FLAG_CTS: CTS interrupt and flag
+      \arg        USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error
+      \arg        USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag
+      \arg        USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag)
+{
+    uint32_t intenable = 0U, flagstatus = 0U;
+    /* get the interrupt enable bit status */
+    intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag)));
+    /* get the corresponding flag bit status */
+    flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag)));
+
+    if(flagstatus && intenable){
+        return SET;
+    }else{
+        return RESET; 
+    }
+}
+
+/*!
+    \brief      clear USART interrupt flag in STAT register
+    \param[in]  usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
+    \param[in]  flag: USART interrupt flag
+                only one parameter can be selected which is shown as below:
+      \arg        USART_INT_FLAG_CTS: CTS change flag
+      \arg        USART_INT_FLAG_LBD: LIN break detected flag
+      \arg        USART_INT_FLAG_TC: transmission complete
+      \arg        USART_INT_FLAG_RBNE: read data buffer not empty
+    \param[out] none
+    \retval     none
+*/
+void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag)
+{
+    USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag));
+}

+ 133 - 0
Library/Source/gd32f10x_wwdgt.c

@@ -0,0 +1,133 @@
+/*!
+    \file    gd32f10x_wwdgt.c
+    \brief   WWDGT driver
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_wwdgt.h"
+
+/* write value to WWDGT_CTL_CNT bit field */
+#define CTL_CNT(regval)             (BITS(0,6) & ((uint32_t)(regval) << 0))
+/* write value to WWDGT_CFG_WIN bit field */
+#define CFG_WIN(regval)             (BITS(0,6) & ((uint32_t)(regval) << 0))
+
+/*!
+    \brief      reset the window watchdog timer configuration
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_deinit(void)
+{
+    rcu_periph_reset_enable(RCU_WWDGTRST);
+    rcu_periph_reset_disable(RCU_WWDGTRST);
+}
+
+/*!
+    \brief      start the window watchdog timer counter
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_enable(void)
+{
+    WWDGT_CTL |= WWDGT_CTL_WDGTEN;
+}
+
+/*!
+    \brief      configure the window watchdog timer counter value
+    \param[in]  counter_value: 0x00 - 0x7F
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_counter_update(uint16_t counter_value)
+{
+    WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value));
+}
+
+/*!
+    \brief      configure counter value, window value, and prescaler divider value  
+    \param[in]  counter: 0x00 - 0x7F   
+    \param[in]  window: 0x00 - 0x7F
+    \param[in]  prescaler: wwdgt prescaler value
+                only one parameter can be selected which is shown as below:
+      \arg        WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1
+      \arg        WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2
+      \arg        WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4
+      \arg        WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
+{
+    WWDGT_CTL = (uint32_t)(CTL_CNT(counter));
+    WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler);
+}
+
+/*!
+    \brief      enable early wakeup interrupt of WWDGT
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_interrupt_enable(void)
+{
+    WWDGT_CFG |= WWDGT_CFG_EWIE;
+}
+
+/*!
+    \brief      check early wakeup interrupt state of WWDGT
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus wwdgt_flag_get(void)
+{
+    if(WWDGT_STAT & WWDGT_STAT_EWIF){
+        return SET;
+    }
+
+    return RESET;
+}
+
+/*!
+    \brief      clear early wakeup interrupt state of WWDGT
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void wwdgt_flag_clear(void)
+{
+    WWDGT_STAT = (uint32_t)(RESET);
+}

+ 642 - 0
Project/XspBoardPro.uvprojx

@@ -0,0 +1,642 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
+
+  <SchemaVersion>2.1</SchemaVersion>
+
+  <Header>### uVision Project, (C) Keil Software</Header>
+
+  <Targets>
+    <Target>
+      <TargetName>XSPBOARDPRO</TargetName>
+      <ToolsetNumber>0x4</ToolsetNumber>
+      <ToolsetName>ARM-ADS</ToolsetName>
+      <pCCUsed>5060960::V5.06 update 7 (build 960)::ARMCC</pCCUsed>
+      <uAC6>0</uAC6>
+      <TargetOption>
+        <TargetCommonOption>
+          <Device>GD32F103VE</Device>
+          <Vendor>GigaDevice</Vendor>
+          <PackID>GigaDevice.GD32F10x_DFP.2.0.2</PackID>
+          <PackURL>http://gd32mcu.com/data/documents/pack/</PackURL>
+          <Cpu>IRAM(0x20000000,0x00010000) IROM(0x08000000,0x00080000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE</Cpu>
+          <FlashUtilSpec></FlashUtilSpec>
+          <StartupFile></StartupFile>
+          <FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_HD -FS08000000 -FL080000 -FP0($$Device:GD32F103VE$Flash\GD32F10x_HD.FLM))</FlashDriverDll>
+          <DeviceId>0</DeviceId>
+          <RegisterFile>$$Device:GD32F103VE$Device\Include\gd32f10x.h</RegisterFile>
+          <MemoryEnv></MemoryEnv>
+          <Cmp></Cmp>
+          <Asm></Asm>
+          <Linker></Linker>
+          <OHString></OHString>
+          <InfinionOptionDll></InfinionOptionDll>
+          <SLE66CMisc></SLE66CMisc>
+          <SLE66AMisc></SLE66AMisc>
+          <SLE66LinkerMisc></SLE66LinkerMisc>
+          <SFDFile>$$Device:GD32F103VE$SVD\GD32F10x\GD32F10x_HD.svd</SFDFile>
+          <bCustSvd>0</bCustSvd>
+          <UseEnv>0</UseEnv>
+          <BinPath></BinPath>
+          <IncludePath></IncludePath>
+          <LibPath></LibPath>
+          <RegisterFilePath></RegisterFilePath>
+          <DBRegisterFilePath></DBRegisterFilePath>
+          <TargetStatus>
+            <Error>0</Error>
+            <ExitCodeStop>0</ExitCodeStop>
+            <ButtonStop>0</ButtonStop>
+            <NotGenerated>0</NotGenerated>
+            <InvalidFlash>1</InvalidFlash>
+          </TargetStatus>
+          <OutputDirectory>.\Objects\</OutputDirectory>
+          <OutputName>TestBoard</OutputName>
+          <CreateExecutable>1</CreateExecutable>
+          <CreateLib>0</CreateLib>
+          <CreateHexFile>1</CreateHexFile>
+          <DebugInformation>1</DebugInformation>
+          <BrowseInformation>1</BrowseInformation>
+          <ListingPath>.\Listings\</ListingPath>
+          <HexFormatSelection>1</HexFormatSelection>
+          <Merge32K>0</Merge32K>
+          <CreateBatchFile>0</CreateBatchFile>
+          <BeforeCompile>
+            <RunUserProg1>0</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name></UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopU1X>0</nStopU1X>
+            <nStopU2X>0</nStopU2X>
+          </BeforeCompile>
+          <BeforeMake>
+            <RunUserProg1>0</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name></UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopB1X>0</nStopB1X>
+            <nStopB2X>0</nStopB2X>
+          </BeforeMake>
+          <AfterMake>
+            <RunUserProg1>1</RunUserProg1>
+            <RunUserProg2>1</RunUserProg2>
+            <UserProg1Name>fromelf --bin !L --output app.bin</UserProg1Name>
+            <UserProg2Name>wbjw_bin.exe -a 08018000 -d 0904 -f 3 -v 02A -r .\app.bin</UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopA1X>0</nStopA1X>
+            <nStopA2X>0</nStopA2X>
+          </AfterMake>
+          <SelectedForBatchBuild>0</SelectedForBatchBuild>
+          <SVCSIdString></SVCSIdString>
+        </TargetCommonOption>
+        <CommonProperty>
+          <UseCPPCompiler>0</UseCPPCompiler>
+          <RVCTCodeConst>0</RVCTCodeConst>
+          <RVCTZI>0</RVCTZI>
+          <RVCTOtherData>0</RVCTOtherData>
+          <ModuleSelection>0</ModuleSelection>
+          <IncludeInBuild>1</IncludeInBuild>
+          <AlwaysBuild>0</AlwaysBuild>
+          <GenerateAssemblyFile>0</GenerateAssemblyFile>
+          <AssembleAssemblyFile>0</AssembleAssemblyFile>
+          <PublicsOnly>0</PublicsOnly>
+          <StopOnExitCode>3</StopOnExitCode>
+          <CustomArgument></CustomArgument>
+          <IncludeLibraryModules></IncludeLibraryModules>
+          <ComprImg>1</ComprImg>
+        </CommonProperty>
+        <DllOption>
+          <SimDllName>SARMCM3.DLL</SimDllName>
+          <SimDllArguments> -REMAP</SimDllArguments>
+          <SimDlgDll>DCM.DLL</SimDlgDll>
+          <SimDlgDllArguments>-pCM3</SimDlgDllArguments>
+          <TargetDllName>SARMCM3.DLL</TargetDllName>
+          <TargetDllArguments></TargetDllArguments>
+          <TargetDlgDll>TCM.DLL</TargetDlgDll>
+          <TargetDlgDllArguments>-pCM3</TargetDlgDllArguments>
+        </DllOption>
+        <DebugOption>
+          <OPTHX>
+            <HexSelection>1</HexSelection>
+            <HexRangeLowAddress>0</HexRangeLowAddress>
+            <HexRangeHighAddress>0</HexRangeHighAddress>
+            <HexOffset>0</HexOffset>
+            <Oh166RecLen>16</Oh166RecLen>
+          </OPTHX>
+        </DebugOption>
+        <Utilities>
+          <Flash1>
+            <UseTargetDll>1</UseTargetDll>
+            <UseExternalTool>0</UseExternalTool>
+            <RunIndependent>0</RunIndependent>
+            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
+            <Capability>1</Capability>
+            <DriverSelection>4096</DriverSelection>
+          </Flash1>
+          <bUseTDR>1</bUseTDR>
+          <Flash2>BIN\UL2CM3.DLL</Flash2>
+          <Flash3>"" ()</Flash3>
+          <Flash4></Flash4>
+          <pFcarmOut></pFcarmOut>
+          <pFcarmGrp></pFcarmGrp>
+          <pFcArmRoot></pFcArmRoot>
+          <FcArmLst>0</FcArmLst>
+        </Utilities>
+        <TargetArmAds>
+          <ArmAdsMisc>
+            <GenerateListings>0</GenerateListings>
+            <asHll>1</asHll>
+            <asAsm>1</asAsm>
+            <asMacX>1</asMacX>
+            <asSyms>1</asSyms>
+            <asFals>1</asFals>
+            <asDbgD>1</asDbgD>
+            <asForm>1</asForm>
+            <ldLst>0</ldLst>
+            <ldmm>1</ldmm>
+            <ldXref>1</ldXref>
+            <BigEnd>0</BigEnd>
+            <AdsALst>1</AdsALst>
+            <AdsACrf>1</AdsACrf>
+            <AdsANop>0</AdsANop>
+            <AdsANot>0</AdsANot>
+            <AdsLLst>1</AdsLLst>
+            <AdsLmap>1</AdsLmap>
+            <AdsLcgr>1</AdsLcgr>
+            <AdsLsym>1</AdsLsym>
+            <AdsLszi>1</AdsLszi>
+            <AdsLtoi>1</AdsLtoi>
+            <AdsLsun>1</AdsLsun>
+            <AdsLven>1</AdsLven>
+            <AdsLsxf>1</AdsLsxf>
+            <RvctClst>0</RvctClst>
+            <GenPPlst>0</GenPPlst>
+            <AdsCpuType>"Cortex-M3"</AdsCpuType>
+            <RvctDeviceName></RvctDeviceName>
+            <mOS>0</mOS>
+            <uocRom>0</uocRom>
+            <uocRam>0</uocRam>
+            <hadIROM>1</hadIROM>
+            <hadIRAM>1</hadIRAM>
+            <hadXRAM>0</hadXRAM>
+            <uocXRam>0</uocXRam>
+            <RvdsVP>0</RvdsVP>
+            <RvdsMve>0</RvdsMve>
+            <RvdsCdeCp>0</RvdsCdeCp>
+            <hadIRAM2>0</hadIRAM2>
+            <hadIROM2>0</hadIROM2>
+            <StupSel>8</StupSel>
+            <useUlib>1</useUlib>
+            <EndSel>0</EndSel>
+            <uLtcg>0</uLtcg>
+            <nSecure>0</nSecure>
+            <RoSelD>3</RoSelD>
+            <RwSelD>3</RwSelD>
+            <CodeSel>0</CodeSel>
+            <OptFeed>0</OptFeed>
+            <NoZi1>0</NoZi1>
+            <NoZi2>0</NoZi2>
+            <NoZi3>0</NoZi3>
+            <NoZi4>0</NoZi4>
+            <NoZi5>0</NoZi5>
+            <Ro1Chk>0</Ro1Chk>
+            <Ro2Chk>0</Ro2Chk>
+            <Ro3Chk>0</Ro3Chk>
+            <Ir1Chk>1</Ir1Chk>
+            <Ir2Chk>0</Ir2Chk>
+            <Ra1Chk>0</Ra1Chk>
+            <Ra2Chk>0</Ra2Chk>
+            <Ra3Chk>0</Ra3Chk>
+            <Im1Chk>1</Im1Chk>
+            <Im2Chk>0</Im2Chk>
+            <OnChipMemories>
+              <Ocm1>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm1>
+              <Ocm2>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm2>
+              <Ocm3>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm3>
+              <Ocm4>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm4>
+              <Ocm5>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm5>
+              <Ocm6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm6>
+              <IRAM>
+                <Type>0</Type>
+                <StartAddress>0x20000000</StartAddress>
+                <Size>0x10000</Size>
+              </IRAM>
+              <IROM>
+                <Type>1</Type>
+                <StartAddress>0x8000000</StartAddress>
+                <Size>0x80000</Size>
+              </IROM>
+              <XRAM>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </XRAM>
+              <OCR_RVCT1>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT1>
+              <OCR_RVCT2>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT2>
+              <OCR_RVCT3>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT3>
+              <OCR_RVCT4>
+                <Type>1</Type>
+                <StartAddress>0x8018000</StartAddress>
+                <Size>0x80000</Size>
+              </OCR_RVCT4>
+              <OCR_RVCT5>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT5>
+              <OCR_RVCT6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT6>
+              <OCR_RVCT7>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT7>
+              <OCR_RVCT8>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT8>
+              <OCR_RVCT9>
+                <Type>0</Type>
+                <StartAddress>0x20000000</StartAddress>
+                <Size>0x10000</Size>
+              </OCR_RVCT9>
+              <OCR_RVCT10>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT10>
+            </OnChipMemories>
+            <RvctStartVector></RvctStartVector>
+          </ArmAdsMisc>
+          <Cads>
+            <interw>1</interw>
+            <Optim>1</Optim>
+            <oTime>0</oTime>
+            <SplitLS>0</SplitLS>
+            <OneElfS>1</OneElfS>
+            <Strict>0</Strict>
+            <EnumInt>0</EnumInt>
+            <PlainCh>0</PlainCh>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <wLevel>2</wLevel>
+            <uThumb>0</uThumb>
+            <uSurpInc>0</uSurpInc>
+            <uC99>0</uC99>
+            <uGnu>0</uGnu>
+            <useXO>0</useXO>
+            <v6Lang>3</v6Lang>
+            <v6LangP>3</v6LangP>
+            <vShortEn>1</vShortEn>
+            <vShortWch>1</vShortWch>
+            <v6Lto>0</v6Lto>
+            <v6WtE>0</v6WtE>
+            <v6Rtti>0</v6Rtti>
+            <VariousControls>
+              <MiscControls></MiscControls>
+              <Define>USE_STDPERIPH_DRIVER,GD32F10X_HD</Define>
+              <Undefine></Undefine>
+              <IncludePath>..\CMSIS;..\Library\Include;..\Startup\ARM;..\User;..\Hardware;..\App</IncludePath>
+            </VariousControls>
+          </Cads>
+          <Aads>
+            <interw>1</interw>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <thumb>0</thumb>
+            <SplitLS>0</SplitLS>
+            <SwStkChk>0</SwStkChk>
+            <NoWarn>0</NoWarn>
+            <uSurpInc>0</uSurpInc>
+            <useXO>0</useXO>
+            <ClangAsOpt>1</ClangAsOpt>
+            <VariousControls>
+              <MiscControls></MiscControls>
+              <Define></Define>
+              <Undefine></Undefine>
+              <IncludePath></IncludePath>
+            </VariousControls>
+          </Aads>
+          <LDads>
+            <umfTarg>1</umfTarg>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <noStLib>0</noStLib>
+            <RepFail>1</RepFail>
+            <useFile>0</useFile>
+            <TextAddressRange>0x08000000</TextAddressRange>
+            <DataAddressRange>0x20000000</DataAddressRange>
+            <pXoBase></pXoBase>
+            <ScatterFile></ScatterFile>
+            <IncludeLibs></IncludeLibs>
+            <IncludeLibsPath></IncludeLibsPath>
+            <Misc></Misc>
+            <LinkerInputFile></LinkerInputFile>
+            <DisabledWarnings></DisabledWarnings>
+          </LDads>
+        </TargetArmAds>
+      </TargetOption>
+      <Groups>
+        <Group>
+          <GroupName>CMISIS</GroupName>
+          <Files>
+            <File>
+              <FileName>system_gd32f10x.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\CMSIS\system_gd32f10x.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>Startup</GroupName>
+          <Files>
+            <File>
+              <FileName>startup_gd32f10x_hd.s</FileName>
+              <FileType>2</FileType>
+              <FilePath>..\Startup\ARM\startup_gd32f10x_hd.s</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>Libary</GroupName>
+          <Files>
+            <File>
+              <FileName>gd32f10x_bkp.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_bkp.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_can.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_can.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_crc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_crc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_dac.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_dac.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_dbg.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_dbg.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_dma.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_dma.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_enet.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_enet.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_exmc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_exmc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_exti.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_exti.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_fmc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_fmc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_fwdgt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_fwdgt.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_gpio.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_gpio.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_i2c.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_i2c.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_misc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_misc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_pmu.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_pmu.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_rcu.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_rcu.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_rtc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_rtc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_sdio.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_sdio.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_timer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_timer.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_usart.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_usart.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f10x_wwdgt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Library\Source\gd32f10x_wwdgt.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>User</GroupName>
+          <Files>
+            <File>
+              <FileName>gd32f10x_it.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\User\gd32f10x_it.c</FilePath>
+            </File>
+            <File>
+              <FileName>main.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\User\main.c</FilePath>
+            </File>
+            <File>
+              <FileName>systick.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\User\systick.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>Hardware</GroupName>
+          <Files>
+            <File>
+              <FileName>Uart.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\Uart.c</FilePath>
+            </File>
+            <File>
+              <FileName>boardinit.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\boardinit.c</FilePath>
+            </File>
+            <File>
+              <FileName>Timer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\Timer.c</FilePath>
+            </File>
+            <File>
+              <FileName>flash.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\flash.c</FilePath>
+            </File>
+            <File>
+              <FileName>fifo.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\fifo.c</FilePath>
+            </File>
+            <File>
+              <FileName>timeout.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\timeout.c</FilePath>
+            </File>
+            <File>
+              <FileName>epprom.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\epprom.c</FilePath>
+            </File>
+            <File>
+              <FileName>I2C.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\I2C.c</FilePath>
+            </File>
+            <File>
+              <FileName>rtc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\rtc.c</FilePath>
+            </File>
+            <File>
+              <FileName>key.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Hardware\key.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>App</GroupName>
+          <Files>
+            <File>
+              <FileName>xspDataOpt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\xspDataOpt.c</FilePath>
+            </File>
+            <File>
+              <FileName>xspOptFlash.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\xspOptFlash.c</FilePath>
+            </File>
+            <File>
+              <FileName>taskOpt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\taskOpt.c</FilePath>
+            </File>
+            <File>
+              <FileName>public.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\public.c</FilePath>
+            </File>
+            <File>
+              <FileName>masterslave.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\masterslave.c</FilePath>
+            </File>
+            <File>
+              <FileName>ota_update.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\App\ota_update.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+      </Groups>
+    </Target>
+  </Targets>
+
+  <RTE>
+    <apis/>
+    <components/>
+    <files/>
+  </RTE>
+
+  <LayerInfo>
+    <Layers>
+      <Layer>
+        <LayName>TestBoard</LayName>
+        <LayPrjMark>1</LayPrjMark>
+      </Layer>
+    </Layers>
+  </LayerInfo>
+
+</Project>

+ 390 - 0
Startup/ARM/startup_gd32f10x_cl.s

@@ -0,0 +1,390 @@
+;/*!
+;    \file    startup_gd32f10x_cl.s
+;    \brief   start up file
+;
+;    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+;    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+;    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+;*/
+;
+;/*
+;    Copyright (c) 2018, GigaDevice Semiconductor Inc.
+;
+;    All rights reserved.
+;
+;    Redistribution and use in source and binary forms, with or without modification, 
+;are permitted provided that the following conditions are met:
+;
+;    1. Redistributions of source code must retain the above copyright notice, this 
+;       list of conditions and the following disclaimer.
+;    2. Redistributions in binary form must reproduce the above copyright notice, 
+;       this list of conditions and the following disclaimer in the documentation 
+;       and/or other materials provided with the distribution.
+;    3. Neither the name of the copyright holder nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software without 
+;       specific prior written permission.
+;
+;    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+;OF SUCH DAMAGE.
+;*/
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size          EQU     0x00000400
+
+                    AREA    STACK, NOINIT, READWRITE, ALIGN = 3
+Stack_Mem           SPACE   Stack_Size
+__initial_sp
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size           EQU     0x00000200
+
+                    AREA    HEAP, NOINIT, READWRITE, ALIGN = 3
+__heap_base
+Heap_Mem            SPACE   Heap_Size
+__heap_limit
+
+
+                    PRESERVE8
+                    THUMB
+
+;                   /* reset Vector Mapped to at Address 0 */
+                    AREA    RESET, DATA, READONLY
+                    EXPORT  __Vectors
+                    EXPORT  __Vectors_End
+                    EXPORT  __Vectors_Size
+
+__Vectors           DCD     __initial_sp                      ; Top of Stack
+                    DCD     Reset_Handler                     ; Reset Handler
+                    DCD     NMI_Handler                       ; NMI Handler
+                    DCD     HardFault_Handler                 ; Hard Fault Handler
+                    DCD     MemManage_Handler                 ; MPU Fault Handler
+                    DCD     BusFault_Handler                  ; Bus Fault Handler
+                    DCD     UsageFault_Handler                ; Usage Fault Handler
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     SVC_Handler                       ; SVCall Handler
+                    DCD     DebugMon_Handler                  ; Debug Monitor Handler
+                    DCD     0                                 ; Reserved
+                    DCD     PendSV_Handler                    ; PendSV Handler
+                    DCD     SysTick_Handler                   ; SysTick Handler
+
+;                   /* external interrupts handler */
+                    DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
+                    DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
+                    DCD     TAMPER_IRQHandler                 ; 18:Tamper Interrupt   
+                    DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                    DCD     FMC_IRQHandler                    ; 20:FMC
+                    DCD     RCU_IRQHandler                    ; 21:RCU
+                    DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
+                    DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
+                    DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
+                    DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
+                    DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
+                    DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel 0
+                    DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel 1
+                    DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel 2
+                    DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel 3
+                    DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel 4
+                    DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel 5 
+                    DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel 6
+                    DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                    DCD     CAN0_TX_IRQHandler                ; 35:CAN0 TX
+                    DCD     CAN0_RX0_IRQHandler               ; 36:CAN0 RX0
+                    DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                    DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                    DCD     EXTI5_9_IRQHandler                ; 39:EXTI Line 5 to EXTI Line 9
+                    DCD     TIMER0_BRK_IRQHandler             ; 40:TIMER0 Break
+                    DCD     TIMER0_UP_IRQHandler              ; 41:TIMER0 Update
+                    DCD     TIMER0_TRG_CMT_IRQHandler         ; 42:TIMER0 Trigger and Commutation
+                    DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
+                    DCD     TIMER1_IRQHandler                 ; 44:TIMER1
+                    DCD     TIMER2_IRQHandler                 ; 45:TIMER2
+                    DCD     TIMER3_IRQHandler                 ; 46:TIMER3
+                    DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
+                    DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
+                    DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
+                    DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
+                    DCD     SPI0_IRQHandler                   ; 51:SPI0
+                    DCD     SPI1_IRQHandler                   ; 52:SPI1
+                    DCD     USART0_IRQHandler                 ; 53:USART0
+                    DCD     USART1_IRQHandler                 ; 54:USART1
+                    DCD     USART2_IRQHandler                 ; 55:USART2
+                    DCD     EXTI10_15_IRQHandler              ; 56:EXTI Line 10 to EXTI Line 15
+                    DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm through EXTI Line
+                    DCD     USBFS_WKUP_IRQHandler             ; 58:USBFS WakeUp from suspend through EXTI Line
+                    DCD     TIMER7_BRK_IRQHandler             ; 59:TIMER7 Break Interrupt
+                    DCD     TIMER7_UP_IRQHandler              ; 60:TIMER7 Update Interrupt
+                    DCD     TIMER7_TRG_CMT_IRQHandler         ; 61:TIMER7 Trigger
+                    DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare 
+                    DCD     0                                 ; Reserved
+                    DCD     EXMC_IRQHandler                   ; 64:EXMC
+                    DCD     0                                 ; Reserved
+                    DCD     TIMER4_IRQHandler                 ; 66:TIMER4
+                    DCD     SPI2_IRQHandler                   ; 67:SPI2
+                    DCD     UART3_IRQHandler                  ; 68:UART3
+                    DCD     UART4_IRQHandler                  ; 69:UART4
+                    DCD     TIMER5_IRQHandler                 ; 70:TIMER5
+                    DCD     TIMER6_IRQHandler                 ; 71:TIMER6
+                    DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
+                    DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
+                    DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
+                    DCD     DMA1_Channel3_IRQHandler          ; 75:DMA1 Channel3
+                    DCD     DMA1_Channel4_IRQHandler          ; 76:DMA1 Channel4
+                    DCD     ENET_IRQHandler                   ; 77:Ethernet
+                    DCD     ENET_WKUP_IRQHandler              ; 78:Ethernet Wakeup through EXTI line
+                    DCD     CAN1_TX_IRQHandler                ; 79:CAN1 TX
+                    DCD     CAN1_RX0_IRQHandler               ; 80:CAN1 RX0
+                    DCD     CAN1_RX1_IRQHandler               ; 81:CAN1 RX1
+                    DCD     CAN1_EWMC_IRQHandler              ; 82:CAN1 EWMC
+                    DCD     USBFS_IRQHandler                  ; 83:USBFS
+
+__Vectors_End
+
+__Vectors_Size      EQU  __Vectors_End - __Vectors
+
+                    AREA    |.text|, CODE, READONLY
+
+;/* reset Handler */
+Reset_Handler       PROC
+                    EXPORT  Reset_Handler                     [WEAK]
+                    IMPORT  __main
+                    IMPORT  SystemInit  
+                    LDR     R0, =SystemInit
+                    BLX     R0
+                    LDR     R0, =__main
+                    BX      R0
+                    ENDP
+
+;/* dummy Exception Handlers */
+NMI_Handler         PROC
+                    EXPORT  NMI_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+HardFault_Handler   PROC
+                    EXPORT  HardFault_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+MemManage_Handler   PROC
+                    EXPORT  MemManage_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+BusFault_Handler    PROC
+                    EXPORT  BusFault_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+UsageFault_Handler  PROC
+                    EXPORT  UsageFault_Handler                  [WEAK]
+                    B       .
+                    ENDP
+
+SVC_Handler         PROC
+                    EXPORT  SVC_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+DebugMon_Handler    PROC
+                    EXPORT  DebugMon_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+PendSV_Handler      PROC
+                    EXPORT  PendSV_Handler                      [WEAK]
+                    B       .
+                    ENDP
+
+SysTick_Handler     PROC
+                    EXPORT  SysTick_Handler                     [WEAK]
+                    B       .
+                    ENDP
+
+Default_Handler     PROC
+;                   /* external interrupts handler */    
+                    EXPORT  WWDGT_IRQHandler                    [WEAK]
+                    EXPORT  LVD_IRQHandler                      [WEAK]
+                    EXPORT  TAMPER_IRQHandler                   [WEAK]
+                    EXPORT  RTC_IRQHandler                      [WEAK]
+                    EXPORT  FMC_IRQHandler                      [WEAK]
+                    EXPORT  RCU_IRQHandler                      [WEAK]
+                    EXPORT  EXTI0_IRQHandler                    [WEAK]
+                    EXPORT  EXTI1_IRQHandler                    [WEAK]
+                    EXPORT  EXTI2_IRQHandler                    [WEAK]
+                    EXPORT  EXTI3_IRQHandler                    [WEAK]
+                    EXPORT  EXTI4_IRQHandler                    [WEAK]
+                    EXPORT  DMA0_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel3_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel4_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel5_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel6_IRQHandler            [WEAK]
+                    EXPORT  ADC0_1_IRQHandler                   [WEAK]
+                    EXPORT  CAN0_TX_IRQHandler                  [WEAK]
+                    EXPORT  CAN0_RX0_IRQHandler                 [WEAK]
+                    EXPORT  CAN0_RX1_IRQHandler                 [WEAK]
+                    EXPORT  CAN0_EWMC_IRQHandler                [WEAK]
+                    EXPORT  EXTI5_9_IRQHandler                  [WEAK]
+                    EXPORT  TIMER0_BRK_IRQHandler               [WEAK]
+                    EXPORT  TIMER0_UP_IRQHandler                [WEAK]
+                    EXPORT  TIMER0_TRG_CMT_IRQHandler           [WEAK]
+                    EXPORT  TIMER0_Channel_IRQHandler           [WEAK]
+                    EXPORT  TIMER1_IRQHandler                   [WEAK]
+                    EXPORT  TIMER2_IRQHandler                   [WEAK]
+                    EXPORT  TIMER3_IRQHandler                   [WEAK]
+                    EXPORT  I2C0_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C0_ER_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_ER_IRQHandler                  [WEAK]
+                    EXPORT  SPI0_IRQHandler                     [WEAK]
+                    EXPORT  SPI1_IRQHandler                     [WEAK]
+                    EXPORT  USART0_IRQHandler                   [WEAK]
+                    EXPORT  USART1_IRQHandler                   [WEAK]
+                    EXPORT  USART2_IRQHandler                   [WEAK]
+                    EXPORT  EXTI10_15_IRQHandler                [WEAK]
+                    EXPORT  RTC_Alarm_IRQHandler                [WEAK]
+                    EXPORT  USBFS_WKUP_IRQHandler               [WEAK]
+                    EXPORT  TIMER7_BRK_IRQHandler               [WEAK]
+                    EXPORT  TIMER7_UP_IRQHandler                [WEAK]
+                    EXPORT  TIMER7_TRG_CMT_IRQHandler           [WEAK]
+                    EXPORT  TIMER7_Channel_IRQHandler           [WEAK]
+                    EXPORT  EXMC_IRQHandler                     [WEAK]
+                    EXPORT  TIMER4_IRQHandler                   [WEAK]
+                    EXPORT  SPI2_IRQHandler                     [WEAK]
+                    EXPORT  UART3_IRQHandler                    [WEAK]
+                    EXPORT  UART4_IRQHandler                    [WEAK]
+                    EXPORT  TIMER5_IRQHandler                   [WEAK]
+                    EXPORT  TIMER6_IRQHandler                   [WEAK]
+                    EXPORT  DMA1_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel3_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel4_IRQHandler            [WEAK]
+                    EXPORT  ENET_IRQHandler                     [WEAK]
+                    EXPORT  ENET_WKUP_IRQHandler                [WEAK]
+                    EXPORT  CAN1_TX_IRQHandler                  [WEAK]
+                    EXPORT  CAN1_RX0_IRQHandler                 [WEAK]
+                    EXPORT  CAN1_RX1_IRQHandler                 [WEAK]
+                    EXPORT  CAN1_EWMC_IRQHandler                [WEAK]
+                    EXPORT  USBFS_IRQHandler                    [WEAK]                                
+   
+
+;/* external interrupts handler */
+WWDGT_IRQHandler
+LVD_IRQHandler
+TAMPER_IRQHandler
+RTC_IRQHandler
+FMC_IRQHandler 
+RCU_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA0_Channel0_IRQHandler
+DMA0_Channel1_IRQHandler
+DMA0_Channel2_IRQHandler
+DMA0_Channel3_IRQHandler
+DMA0_Channel4_IRQHandler
+DMA0_Channel5_IRQHandler
+DMA0_Channel6_IRQHandler
+ADC0_1_IRQHandler
+CAN0_TX_IRQHandler
+CAN0_RX0_IRQHandler
+CAN0_RX1_IRQHandler
+CAN0_EWMC_IRQHandler
+EXTI5_9_IRQHandler
+TIMER0_BRK_IRQHandler
+TIMER0_UP_IRQHandler
+TIMER0_TRG_CMT_IRQHandler
+TIMER0_Channel_IRQHandler
+TIMER1_IRQHandler
+TIMER2_IRQHandler
+TIMER3_IRQHandler
+I2C0_EV_IRQHandler
+I2C0_ER_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+SPI0_IRQHandler
+SPI1_IRQHandler
+USART0_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+EXTI10_15_IRQHandler
+RTC_Alarm_IRQHandler
+USBFS_WKUP_IRQHandler
+TIMER7_BRK_IRQHandler
+TIMER7_UP_IRQHandler
+TIMER7_TRG_CMT_IRQHandler
+TIMER7_Channel_IRQHandler
+EXMC_IRQHandler
+TIMER4_IRQHandler
+SPI2_IRQHandler
+UART3_IRQHandler
+UART4_IRQHandler
+TIMER5_IRQHandler
+TIMER6_IRQHandler
+DMA1_Channel0_IRQHandler
+DMA1_Channel1_IRQHandler
+DMA1_Channel2_IRQHandler
+DMA1_Channel3_IRQHandler
+DMA1_Channel4_IRQHandler
+ENET_IRQHandler
+ENET_WKUP_IRQHandler
+CAN1_TX_IRQHandler
+CAN1_RX0_IRQHandler
+CAN1_RX1_IRQHandler
+CAN1_EWMC_IRQHandler
+USBFS_IRQHandler
+
+
+                B       .
+                ENDP
+
+                ALIGN
+
+; user Initial Stack & Heap
+
+                 IF      :DEF:__MICROLIB
+                
+                 EXPORT  __initial_sp
+                 EXPORT  __heap_base
+                 EXPORT  __heap_limit
+                
+                 ELSE
+                
+                 IMPORT  __use_two_region_memory
+                 EXPORT  __user_initial_stackheap
+                 
+__user_initial_stackheap PROC
+                 LDR     R0, =  Heap_Mem
+                 LDR     R1, =(Stack_Mem + Stack_Size)
+                 LDR     R2, = (Heap_Mem +  Heap_Size)
+                 LDR     R3, = Stack_Mem
+                 BX      LR
+                 ENDP
+                     
+                 ALIGN
+
+                 ENDIF
+
+                 END

+ 371 - 0
Startup/ARM/startup_gd32f10x_hd.s

@@ -0,0 +1,371 @@
+;/*!
+;    \file    startup_gd32f10x_hd.s
+;    \brief   start up file
+;
+;    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+;    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+;    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+;*/
+;
+;/*
+;    Copyright (c) 2018, GigaDevice Semiconductor Inc.
+;
+;    All rights reserved.
+;
+;    Redistribution and use in source and binary forms, with or without modification, 
+;are permitted provided that the following conditions are met:
+;
+;    1. Redistributions of source code must retain the above copyright notice, this 
+;       list of conditions and the following disclaimer.
+;    2. Redistributions in binary form must reproduce the above copyright notice, 
+;       this list of conditions and the following disclaimer in the documentation 
+;       and/or other materials provided with the distribution.
+;    3. Neither the name of the copyright holder nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software without 
+;       specific prior written permission.
+;
+;    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+;OF SUCH DAMAGE.
+;*/
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size          EQU     0x00000400
+
+                    AREA    STACK, NOINIT, READWRITE, ALIGN = 3
+Stack_Mem           SPACE   Stack_Size
+__initial_sp
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size           EQU     0x00000200
+
+                    AREA    HEAP, NOINIT, READWRITE, ALIGN = 3
+__heap_base
+Heap_Mem            SPACE   Heap_Size
+__heap_limit
+
+
+                    PRESERVE8
+                    THUMB
+
+;                   /* reset Vector Mapped to at Address 0 */
+                    AREA    RESET, DATA, READONLY
+                    EXPORT  __Vectors
+                    EXPORT  __Vectors_End
+                    EXPORT  __Vectors_Size
+
+__Vectors           DCD     __initial_sp                      ; Top of Stack
+                    DCD     Reset_Handler                     ; Reset Handler
+                    DCD     NMI_Handler                       ; NMI Handler
+                    DCD     HardFault_Handler                 ; Hard Fault Handler
+                    DCD     MemManage_Handler                 ; MPU Fault Handler
+                    DCD     BusFault_Handler                  ; Bus Fault Handler
+                    DCD     UsageFault_Handler                ; Usage Fault Handler
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     SVC_Handler                       ; SVCall Handler
+                    DCD     DebugMon_Handler                  ; Debug Monitor Handler
+                    DCD     0                                 ; Reserved
+                    DCD     PendSV_Handler                    ; PendSV Handler
+                    DCD     SysTick_Handler                   ; SysTick Handler
+
+;                   /* external interrupts handler */
+                    DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
+                    DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
+                    DCD     TAMPER_IRQHandler                 ; 18:Tamper Interrupt   
+                    DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                    DCD     FMC_IRQHandler                    ; 20:FMC
+                    DCD     RCU_IRQHandler                    ; 21:RCU
+                    DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
+                    DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
+                    DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
+                    DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
+                    DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
+                    DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel 0
+                    DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel 1
+                    DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel 2
+                    DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel 3
+                    DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel 4
+                    DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel 5 
+                    DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel 6
+                    DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                    DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD and CAN0 TX
+                    DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD and CAN0 RX0
+                    DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                    DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                    DCD     EXTI5_9_IRQHandler                ; 39:EXTI Line 5 to EXTI Line 9
+                    DCD     TIMER0_BRK_IRQHandler             ; 40:TIMER0 Break
+                    DCD     TIMER0_UP_IRQHandler              ; 41:TIMER0 Update
+                    DCD     TIMER0_TRG_CMT_IRQHandler         ; 42:TIMER0 Trigger and Commutation
+                    DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
+                    DCD     TIMER1_IRQHandler                 ; 44:TIMER1
+                    DCD     TIMER2_IRQHandler                 ; 45:TIMER2
+                    DCD     TIMER3_IRQHandler                 ; 46:TIMER3
+                    DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
+                    DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
+                    DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
+                    DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
+                    DCD     SPI0_IRQHandler                   ; 51:SPI0
+                    DCD     SPI1_IRQHandler                   ; 52:SPI1
+                    DCD     USART0_IRQHandler                 ; 53:USART0
+                    DCD     USART1_IRQHandler                 ; 54:USART1
+                    DCD     USART2_IRQHandler                 ; 55:USART2
+                    DCD     EXTI10_15_IRQHandler              ; 56:EXTI Line 10 to EXTI Line 15
+                    DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm through EXTI Line
+                    DCD     USBD_WKUP_IRQHandler              ; 58:USBD WakeUp from suspend through EXTI Line
+                    DCD     TIMER7_BRK_IRQHandler             ; 59:TIMER7 Break Interrupt
+                    DCD     TIMER7_UP_IRQHandler              ; 60:TIMER7 Update Interrupt
+                    DCD     TIMER7_TRG_CMT_IRQHandler         ; 61:TIMER7 Trigger and Commutation Interrupt
+                    DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare 
+                    DCD     ADC2_IRQHandler                   ; 63:ADC2
+                    DCD     EXMC_IRQHandler                   ; 64:EXMC
+                    DCD     SDIO_IRQHandler                   ; 65:SDIO
+                    DCD     TIMER4_IRQHandler                 ; 66:TIMER4
+                    DCD     SPI2_IRQHandler                   ; 67:SPI2
+                    DCD     UART3_IRQHandler                  ; 68:UART3
+                    DCD     UART4_IRQHandler                  ; 69:UART4
+                    DCD     TIMER5_IRQHandler                 ; 70:TIMER5
+                    DCD     TIMER6_IRQHandler                 ; 71:TIMER6
+                    DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
+                    DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
+                    DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
+                    DCD     DMA1_Channel3_4_IRQHandler        ; 75:DMA1 Channel3 and Channel4
+
+__Vectors_End
+
+__Vectors_Size      EQU  __Vectors_End - __Vectors
+
+                    AREA    |.text|, CODE, READONLY
+
+;/* reset Handler */
+Reset_Handler       PROC
+                    EXPORT  Reset_Handler                     [WEAK]
+                    IMPORT  __main
+                    IMPORT  SystemInit  
+                    LDR     R0, =SystemInit
+                    BLX     R0
+                    LDR     R0, =__main
+                    BX      R0
+                    ENDP
+
+;/* dummy Exception Handlers */
+NMI_Handler         PROC
+                    EXPORT  NMI_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+HardFault_Handler   PROC
+                    EXPORT  HardFault_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+MemManage_Handler   PROC
+                    EXPORT  MemManage_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+BusFault_Handler    PROC
+                    EXPORT  BusFault_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+UsageFault_Handler  PROC
+                    EXPORT  UsageFault_Handler                  [WEAK]
+                    B       .
+                    ENDP
+
+SVC_Handler         PROC
+                    EXPORT  SVC_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+DebugMon_Handler    PROC
+                    EXPORT  DebugMon_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+PendSV_Handler      PROC
+                    EXPORT  PendSV_Handler                      [WEAK]
+                    B       .
+                    ENDP
+
+SysTick_Handler     PROC
+                    EXPORT  SysTick_Handler                     [WEAK]
+                    B       .
+                    ENDP
+
+Default_Handler     PROC
+;                   /* external interrupts handler */    
+                    EXPORT  WWDGT_IRQHandler                    [WEAK]
+                    EXPORT  LVD_IRQHandler                      [WEAK]
+                    EXPORT  TAMPER_IRQHandler                   [WEAK]
+                    EXPORT  RTC_IRQHandler                      [WEAK]
+                    EXPORT  FMC_IRQHandler                      [WEAK]
+                    EXPORT  RCU_IRQHandler                      [WEAK]
+                    EXPORT  EXTI0_IRQHandler                    [WEAK]
+                    EXPORT  EXTI1_IRQHandler                    [WEAK]
+                    EXPORT  EXTI2_IRQHandler                    [WEAK]
+                    EXPORT  EXTI3_IRQHandler                    [WEAK]
+                    EXPORT  EXTI4_IRQHandler                    [WEAK]
+                    EXPORT  DMA0_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel3_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel4_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel5_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel6_IRQHandler            [WEAK]
+                    EXPORT  ADC0_1_IRQHandler                   [WEAK]
+                    EXPORT  USBD_HP_CAN0_TX_IRQHandler          [WEAK]
+                    EXPORT  USBD_LP_CAN0_RX0_IRQHandler         [WEAK]
+                    EXPORT  CAN0_RX1_IRQHandler                 [WEAK]
+                    EXPORT  CAN0_EWMC_IRQHandler                [WEAK]
+                    EXPORT  EXTI5_9_IRQHandler                  [WEAK]
+                    EXPORT  TIMER0_BRK_IRQHandler               [WEAK]
+                    EXPORT  TIMER0_UP_IRQHandler                [WEAK]
+                    EXPORT  TIMER0_TRG_CMT_IRQHandler           [WEAK]
+                    EXPORT  TIMER0_Channel_IRQHandler           [WEAK]
+                    EXPORT  TIMER1_IRQHandler                   [WEAK]
+                    EXPORT  TIMER2_IRQHandler                   [WEAK]
+                    EXPORT  TIMER3_IRQHandler                   [WEAK]
+                    EXPORT  I2C0_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C0_ER_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_ER_IRQHandler                  [WEAK]
+                    EXPORT  SPI0_IRQHandler                     [WEAK]
+                    EXPORT  SPI1_IRQHandler                     [WEAK]
+                    EXPORT  USART0_IRQHandler                   [WEAK]
+                    EXPORT  USART1_IRQHandler                   [WEAK]
+                    EXPORT  USART2_IRQHandler                   [WEAK]
+                    EXPORT  EXTI10_15_IRQHandler                [WEAK]
+                    EXPORT  RTC_Alarm_IRQHandler                [WEAK]
+                    EXPORT  USBD_WKUP_IRQHandler                [WEAK]
+                    EXPORT  TIMER7_BRK_IRQHandler               [WEAK]
+                    EXPORT  TIMER7_UP_IRQHandler                [WEAK]
+                    EXPORT  TIMER7_TRG_CMT_IRQHandler           [WEAK]
+                    EXPORT  TIMER7_Channel_IRQHandler           [WEAK]
+                    EXPORT  ADC2_IRQHandler                     [WEAK]
+                    EXPORT  EXMC_IRQHandler                     [WEAK]
+                    EXPORT  SDIO_IRQHandler                     [WEAK]
+                    EXPORT  TIMER4_IRQHandler                   [WEAK]
+                    EXPORT  SPI2_IRQHandler                     [WEAK]
+                    EXPORT  UART3_IRQHandler                    [WEAK]
+                    EXPORT  UART4_IRQHandler                    [WEAK]
+                    EXPORT  TIMER5_IRQHandler                   [WEAK]
+                    EXPORT  TIMER6_IRQHandler                   [WEAK]
+                    EXPORT  DMA1_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel3_4_IRQHandler          [WEAK]
+   
+
+;/* external interrupts handler */
+WWDGT_IRQHandler
+LVD_IRQHandler
+TAMPER_IRQHandler
+RTC_IRQHandler
+FMC_IRQHandler 
+RCU_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA0_Channel0_IRQHandler
+DMA0_Channel1_IRQHandler
+DMA0_Channel2_IRQHandler
+DMA0_Channel3_IRQHandler
+DMA0_Channel4_IRQHandler
+DMA0_Channel5_IRQHandler
+DMA0_Channel6_IRQHandler
+ADC0_1_IRQHandler
+USBD_HP_CAN0_TX_IRQHandler
+USBD_LP_CAN0_RX0_IRQHandler
+CAN0_RX1_IRQHandler
+CAN0_EWMC_IRQHandler
+EXTI5_9_IRQHandler
+TIMER0_BRK_IRQHandler
+TIMER0_UP_IRQHandler
+TIMER0_TRG_CMT_IRQHandler
+TIMER0_Channel_IRQHandler
+TIMER1_IRQHandler
+TIMER2_IRQHandler
+TIMER3_IRQHandler
+I2C0_EV_IRQHandler
+I2C0_ER_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+SPI0_IRQHandler
+SPI1_IRQHandler
+USART0_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+EXTI10_15_IRQHandler
+RTC_Alarm_IRQHandler
+USBD_WKUP_IRQHandler
+TIMER7_BRK_IRQHandler
+TIMER7_UP_IRQHandler
+TIMER7_TRG_CMT_IRQHandler
+TIMER7_Channel_IRQHandler
+ADC2_IRQHandler
+EXMC_IRQHandler
+SDIO_IRQHandler
+TIMER4_IRQHandler
+SPI2_IRQHandler
+UART3_IRQHandler
+UART4_IRQHandler
+TIMER5_IRQHandler
+TIMER6_IRQHandler
+DMA1_Channel0_IRQHandler
+DMA1_Channel1_IRQHandler
+DMA1_Channel2_IRQHandler
+DMA1_Channel3_4_IRQHandler
+
+
+
+                B       .
+                ENDP
+
+                ALIGN
+
+; user Initial Stack & Heap
+
+                 IF      :DEF:__MICROLIB
+                
+                 EXPORT  __initial_sp
+                 EXPORT  __heap_base
+                 EXPORT  __heap_limit
+                
+                 ELSE
+                
+                 IMPORT  __use_two_region_memory
+                 EXPORT  __user_initial_stackheap
+                 
+__user_initial_stackheap PROC
+                 LDR     R0, =  Heap_Mem
+                 LDR     R1, =(Stack_Mem + Stack_Size)
+                 LDR     R2, = (Heap_Mem +  Heap_Size)
+                 LDR     R3, = Stack_Mem
+                 BX      LR
+                 ENDP
+                     
+                 ALIGN
+
+                 ENDIF
+
+                 END

+ 328 - 0
Startup/ARM/startup_gd32f10x_md.s

@@ -0,0 +1,328 @@
+;/*!
+;    \file    startup_gd32f10x_md.s
+;    \brief   start up file
+;
+;    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+;    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+;    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+;*/
+;
+;/*
+;    Copyright (c) 2018, GigaDevice Semiconductor Inc.
+;
+;    All rights reserved.
+;
+;    Redistribution and use in source and binary forms, with or without modification, 
+;are permitted provided that the following conditions are met:
+;
+;    1. Redistributions of source code must retain the above copyright notice, this 
+;       list of conditions and the following disclaimer.
+;    2. Redistributions in binary form must reproduce the above copyright notice, 
+;       this list of conditions and the following disclaimer in the documentation 
+;       and/or other materials provided with the distribution.
+;    3. Neither the name of the copyright holder nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software without 
+;       specific prior written permission.
+;
+;    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+;OF SUCH DAMAGE.
+;*/
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size          EQU     0x00000400
+
+                    AREA    STACK, NOINIT, READWRITE, ALIGN = 3
+Stack_Mem           SPACE   Stack_Size
+__initial_sp
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size           EQU     0x00000200
+
+                    AREA    HEAP, NOINIT, READWRITE, ALIGN = 3
+__heap_base
+Heap_Mem            SPACE   Heap_Size
+__heap_limit
+
+
+                    PRESERVE8
+                    THUMB
+
+;                   /* reset Vector Mapped to at Address 0 */
+                    AREA    RESET, DATA, READONLY
+                    EXPORT  __Vectors
+                    EXPORT  __Vectors_End
+                    EXPORT  __Vectors_Size
+
+__Vectors           DCD     __initial_sp                      ; Top of Stack
+                    DCD     Reset_Handler                     ; Reset Handler
+                    DCD     NMI_Handler                       ; NMI Handler
+                    DCD     HardFault_Handler                 ; Hard Fault Handler
+                    DCD     MemManage_Handler                 ; MPU Fault Handler
+                    DCD     BusFault_Handler                  ; Bus Fault Handler
+                    DCD     UsageFault_Handler                ; Usage Fault Handler
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     SVC_Handler                       ; SVCall Handler
+                    DCD     DebugMon_Handler                  ; Debug Monitor Handler
+                    DCD     0                                 ; Reserved
+                    DCD     PendSV_Handler                    ; PendSV Handler
+                    DCD     SysTick_Handler                   ; SysTick Handler
+
+;                   /* external interrupts handler */
+                    DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
+                    DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
+                    DCD     TAMPER_IRQHandler                 ; 18:Tamper Interrupt   
+                    DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                    DCD     FMC_IRQHandler                    ; 20:FMC
+                    DCD     RCU_IRQHandler                    ; 21:RCU
+                    DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
+                    DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
+                    DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
+                    DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
+                    DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
+                    DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel 0
+                    DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel 1
+                    DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel 2
+                    DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel 3
+                    DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel 4
+                    DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel 5 
+                    DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel 6
+                    DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                    DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD and CAN0 TX
+                    DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD and CAN0 RX0
+                    DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                    DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                    DCD     EXTI5_9_IRQHandler                ; 39:EXTI Line 5 to EXTI Line 9
+                    DCD     TIMER0_BRK_IRQHandler             ; 40:TIMER0 Break
+                    DCD     TIMER0_UP_IRQHandler              ; 41:TIMER0 Update
+                    DCD     TIMER0_TRG_CMT_IRQHandler         ; 42:TIMER0 Trigger
+                    DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
+                    DCD     TIMER1_IRQHandler                 ; 44:TIMER1
+                    DCD     TIMER2_IRQHandler                 ; 45:TIMER2
+                    DCD     TIMER3_IRQHandler                 ; 46:TIMER3
+                    DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
+                    DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
+                    DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
+                    DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
+                    DCD     SPI0_IRQHandler                   ; 51:SPI0
+                    DCD     SPI1_IRQHandler                   ; 52:SPI1
+                    DCD     USART0_IRQHandler                 ; 53:USART0
+                    DCD     USART1_IRQHandler                 ; 54:USART1
+                    DCD     USART2_IRQHandler                 ; 55:USART2
+                    DCD     EXTI10_15_IRQHandler              ; 56:EXTI Line 10 to EXTI Line 15
+                    DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm through EXTI Line
+                    DCD     USBD_WKUP_IRQHandler              ; 58:USBD WakeUp from suspend through EXTI Line
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     EXMC_IRQHandler                   ; 64:EXMC
+
+__Vectors_End
+
+__Vectors_Size      EQU  __Vectors_End - __Vectors
+
+                    AREA    |.text|, CODE, READONLY
+
+;/* reset Handler */
+Reset_Handler       PROC
+                    EXPORT  Reset_Handler                     [WEAK]
+                    IMPORT  __main
+                    IMPORT  SystemInit  
+                    LDR     R0, =SystemInit
+                    BLX     R0
+                    LDR     R0, =__main
+                    BX      R0
+                    ENDP
+
+;/* dummy Exception Handlers */
+NMI_Handler         PROC
+                    EXPORT  NMI_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+HardFault_Handler   PROC
+                    EXPORT  HardFault_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+MemManage_Handler   PROC
+                    EXPORT  MemManage_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+BusFault_Handler    PROC
+                    EXPORT  BusFault_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+UsageFault_Handler  PROC
+                    EXPORT  UsageFault_Handler                  [WEAK]
+                    B       .
+                    ENDP
+
+SVC_Handler         PROC
+                    EXPORT  SVC_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+DebugMon_Handler    PROC
+                    EXPORT  DebugMon_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+PendSV_Handler      PROC
+                    EXPORT  PendSV_Handler                      [WEAK]
+                    B       .
+                    ENDP
+
+SysTick_Handler     PROC
+                    EXPORT  SysTick_Handler                     [WEAK]
+                    B       .
+                    ENDP
+
+Default_Handler     PROC
+;                   /* external interrupts handler */    
+                    EXPORT  WWDGT_IRQHandler                    [WEAK]
+                    EXPORT  LVD_IRQHandler                      [WEAK]
+                    EXPORT  TAMPER_IRQHandler                   [WEAK]
+                    EXPORT  RTC_IRQHandler                      [WEAK]
+                    EXPORT  FMC_IRQHandler                      [WEAK]
+                    EXPORT  RCU_IRQHandler                      [WEAK]
+                    EXPORT  EXTI0_IRQHandler                    [WEAK]
+                    EXPORT  EXTI1_IRQHandler                    [WEAK]
+                    EXPORT  EXTI2_IRQHandler                    [WEAK]
+                    EXPORT  EXTI3_IRQHandler                    [WEAK]
+                    EXPORT  EXTI4_IRQHandler                    [WEAK]
+                    EXPORT  DMA0_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel3_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel4_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel5_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel6_IRQHandler            [WEAK]
+                    EXPORT  ADC0_1_IRQHandler                   [WEAK]
+                    EXPORT  USBD_HP_CAN0_TX_IRQHandler          [WEAK]
+                    EXPORT  USBD_LP_CAN0_RX0_IRQHandler         [WEAK]
+                    EXPORT  CAN0_RX1_IRQHandler                 [WEAK]
+                    EXPORT  CAN0_EWMC_IRQHandler                [WEAK]
+                    EXPORT  EXTI5_9_IRQHandler                  [WEAK]
+                    EXPORT  TIMER0_BRK_IRQHandler               [WEAK]
+                    EXPORT  TIMER0_UP_IRQHandler                [WEAK]
+                    EXPORT  TIMER0_TRG_CMT_IRQHandler           [WEAK]
+                    EXPORT  TIMER0_Channel_IRQHandler           [WEAK]
+                    EXPORT  TIMER1_IRQHandler                   [WEAK]
+                    EXPORT  TIMER2_IRQHandler                   [WEAK]
+                    EXPORT  TIMER3_IRQHandler                   [WEAK]
+                    EXPORT  I2C0_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C0_ER_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_ER_IRQHandler                  [WEAK]
+                    EXPORT  SPI0_IRQHandler                     [WEAK]
+                    EXPORT  SPI1_IRQHandler                     [WEAK]
+                    EXPORT  USART0_IRQHandler                   [WEAK]
+                    EXPORT  USART1_IRQHandler                   [WEAK]
+                    EXPORT  USART2_IRQHandler                   [WEAK]
+                    EXPORT  EXTI10_15_IRQHandler                [WEAK]
+                    EXPORT  RTC_Alarm_IRQHandler                [WEAK]
+                    EXPORT  USBD_WKUP_IRQHandler                [WEAK]
+                    EXPORT  EXMC_IRQHandler                     [WEAK]
+   
+
+;/* external interrupts handler */
+WWDGT_IRQHandler
+LVD_IRQHandler
+TAMPER_IRQHandler
+RTC_IRQHandler
+FMC_IRQHandler 
+RCU_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA0_Channel0_IRQHandler
+DMA0_Channel1_IRQHandler
+DMA0_Channel2_IRQHandler
+DMA0_Channel3_IRQHandler
+DMA0_Channel4_IRQHandler
+DMA0_Channel5_IRQHandler
+DMA0_Channel6_IRQHandler
+ADC0_1_IRQHandler
+USBD_HP_CAN0_TX_IRQHandler
+USBD_LP_CAN0_RX0_IRQHandler
+CAN0_RX1_IRQHandler
+CAN0_EWMC_IRQHandler
+EXTI5_9_IRQHandler
+TIMER0_BRK_IRQHandler
+TIMER0_UP_IRQHandler
+TIMER0_TRG_CMT_IRQHandler
+TIMER0_Channel_IRQHandler
+TIMER1_IRQHandler
+TIMER2_IRQHandler
+TIMER3_IRQHandler
+I2C0_EV_IRQHandler
+I2C0_ER_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+SPI0_IRQHandler
+SPI1_IRQHandler
+USART0_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+EXTI10_15_IRQHandler
+RTC_Alarm_IRQHandler
+USBD_WKUP_IRQHandler
+EXMC_IRQHandler
+
+
+
+                B       .
+                ENDP
+
+                ALIGN
+
+; user Initial Stack & Heap
+
+                 IF      :DEF:__MICROLIB
+                
+                 EXPORT  __initial_sp
+                 EXPORT  __heap_base
+                 EXPORT  __heap_limit
+                
+                 ELSE
+                
+                 IMPORT  __use_two_region_memory
+                 EXPORT  __user_initial_stackheap
+                 
+__user_initial_stackheap PROC
+                 LDR     R0, =  Heap_Mem
+                 LDR     R1, =(Stack_Mem + Stack_Size)
+                 LDR     R2, = (Heap_Mem +  Heap_Size)
+                 LDR     R3, = Stack_Mem
+                 BX      LR
+                 ENDP
+                     
+                 ALIGN
+
+                 ENDIF
+
+                 END

+ 371 - 0
Startup/ARM/startup_gd32f10x_xd.s

@@ -0,0 +1,371 @@
+;/*!
+;    \file    startup_gd32f10x_xd.s
+;    \brief   start up file
+;
+;    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+;    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+;    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+;*/
+;
+;/*
+;    Copyright (c) 2018, GigaDevice Semiconductor Inc.
+;
+;    All rights reserved.
+;
+;    Redistribution and use in source and binary forms, with or without modification, 
+;are permitted provided that the following conditions are met:
+;
+;    1. Redistributions of source code must retain the above copyright notice, this 
+;       list of conditions and the following disclaimer.
+;    2. Redistributions in binary form must reproduce the above copyright notice, 
+;       this list of conditions and the following disclaimer in the documentation 
+;       and/or other materials provided with the distribution.
+;    3. Neither the name of the copyright holder nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software without 
+;       specific prior written permission.
+;
+;    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+;OF SUCH DAMAGE.
+;*/
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size          EQU     0x00000400
+
+                    AREA    STACK, NOINIT, READWRITE, ALIGN = 3
+Stack_Mem           SPACE   Stack_Size
+__initial_sp
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size           EQU     0x00000200
+
+                    AREA    HEAP, NOINIT, READWRITE, ALIGN = 3
+__heap_base
+Heap_Mem            SPACE   Heap_Size
+__heap_limit
+
+
+                    PRESERVE8
+                    THUMB
+
+;                   /* reset Vector Mapped to at Address 0 */
+                    AREA    RESET, DATA, READONLY
+                    EXPORT  __Vectors
+                    EXPORT  __Vectors_End
+                    EXPORT  __Vectors_Size
+
+__Vectors           DCD     __initial_sp                      ; Top of Stack
+                    DCD     Reset_Handler                     ; Reset Handler
+                    DCD     NMI_Handler                       ; NMI Handler
+                    DCD     HardFault_Handler                 ; Hard Fault Handler
+                    DCD     MemManage_Handler                 ; MPU Fault Handler
+                    DCD     BusFault_Handler                  ; Bus Fault Handler
+                    DCD     UsageFault_Handler                ; Usage Fault Handler
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     0                                 ; Reserved
+                    DCD     SVC_Handler                       ; SVCall Handler
+                    DCD     DebugMon_Handler                  ; Debug Monitor Handler
+                    DCD     0                                 ; Reserved
+                    DCD     PendSV_Handler                    ; PendSV Handler
+                    DCD     SysTick_Handler                   ; SysTick Handler
+
+;                   /* external interrupts handler */
+                    DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
+                    DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
+                    DCD     TAMPER_IRQHandler                 ; 18:Tamper Interrupt   
+                    DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                    DCD     FMC_IRQHandler                    ; 20:FMC
+                    DCD     RCU_IRQHandler                    ; 21:RCU
+                    DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
+                    DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
+                    DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
+                    DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
+                    DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
+                    DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel 0
+                    DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel 1
+                    DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel 2
+                    DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel 3
+                    DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel 4
+                    DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel 5 
+                    DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel 6
+                    DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                    DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD and CAN0 TX
+                    DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD and CAN0 RX0
+                    DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                    DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                    DCD     EXTI5_9_IRQHandler                ; 39:EXTI Line 5 to EXTI Line 9
+                    DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8 global
+                    DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9 global
+                    DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 global
+                    DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
+                    DCD     TIMER1_IRQHandler                 ; 44:TIMER1
+                    DCD     TIMER2_IRQHandler                 ; 45:TIMER2
+                    DCD     TIMER3_IRQHandler                 ; 46:TIMER3
+                    DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
+                    DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
+                    DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
+                    DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
+                    DCD     SPI0_IRQHandler                   ; 51:SPI0
+                    DCD     SPI1_IRQHandler                   ; 52:SPI1
+                    DCD     USART0_IRQHandler                 ; 53:USART0
+                    DCD     USART1_IRQHandler                 ; 54:USART1
+                    DCD     USART2_IRQHandler                 ; 55:USART2
+                    DCD     EXTI10_15_IRQHandler              ; 56:EXTI Line 10 to EXTI Line 15
+                    DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm through EXTI Line
+                    DCD     USBD_WKUP_IRQHandler              ; 58:USBD WakeUp from suspend through EXTI Line
+                    DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break Interrupt and TIMER11 global
+                    DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update Interrupt and TIMER12 global
+                    DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 global
+                    DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare 
+                    DCD     ADC2_IRQHandler                   ; 63:ADC2
+                    DCD     EXMC_IRQHandler                   ; 64:EXMC
+                    DCD     SDIO_IRQHandler                   ; 65:SDIO
+                    DCD     TIMER4_IRQHandler                 ; 66:TIMER4
+                    DCD     SPI2_IRQHandler                   ; 67:SPI2
+                    DCD     UART3_IRQHandler                  ; 68:UART3
+                    DCD     UART4_IRQHandler                  ; 69:UART4
+                    DCD     TIMER5_IRQHandler                 ; 70:TIMER5
+                    DCD     TIMER6_IRQHandler                 ; 71:TIMER6
+                    DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
+                    DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
+                    DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
+                    DCD     DMA1_Channel3_4_IRQHandler        ; 75:DMA1 Channel3 and Channel4
+
+__Vectors_End
+
+__Vectors_Size      EQU  __Vectors_End - __Vectors
+
+                    AREA    |.text|, CODE, READONLY
+
+;/* reset Handler */
+Reset_Handler       PROC
+                    EXPORT  Reset_Handler                     [WEAK]
+                    IMPORT  __main
+                    IMPORT  SystemInit  
+                    LDR     R0, =SystemInit
+                    BLX     R0
+                    LDR     R0, =__main
+                    BX      R0
+                    ENDP
+
+;/* dummy Exception Handlers */
+NMI_Handler         PROC
+                    EXPORT  NMI_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+HardFault_Handler   PROC
+                    EXPORT  HardFault_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+MemManage_Handler   PROC
+                    EXPORT  MemManage_Handler                   [WEAK]
+                    B       .
+                    ENDP
+
+BusFault_Handler    PROC
+                    EXPORT  BusFault_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+UsageFault_Handler  PROC
+                    EXPORT  UsageFault_Handler                  [WEAK]
+                    B       .
+                    ENDP
+
+SVC_Handler         PROC
+                    EXPORT  SVC_Handler                         [WEAK]
+                    B       .
+                    ENDP
+
+DebugMon_Handler    PROC
+                    EXPORT  DebugMon_Handler                    [WEAK]
+                    B       .
+                    ENDP
+
+PendSV_Handler      PROC
+                    EXPORT  PendSV_Handler                      [WEAK]
+                    B       .
+                    ENDP
+
+SysTick_Handler     PROC
+                    EXPORT  SysTick_Handler                     [WEAK]
+                    B       .
+                    ENDP
+
+Default_Handler     PROC
+;                   /* external interrupts handler */    
+                    EXPORT  WWDGT_IRQHandler                    [WEAK]
+                    EXPORT  LVD_IRQHandler                      [WEAK]
+                    EXPORT  TAMPER_IRQHandler                   [WEAK]
+                    EXPORT  RTC_IRQHandler                      [WEAK]
+                    EXPORT  FMC_IRQHandler                      [WEAK]
+                    EXPORT  RCU_IRQHandler                      [WEAK]
+                    EXPORT  EXTI0_IRQHandler                    [WEAK]
+                    EXPORT  EXTI1_IRQHandler                    [WEAK]
+                    EXPORT  EXTI2_IRQHandler                    [WEAK]
+                    EXPORT  EXTI3_IRQHandler                    [WEAK]
+                    EXPORT  EXTI4_IRQHandler                    [WEAK]
+                    EXPORT  DMA0_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel3_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel4_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel5_IRQHandler            [WEAK]
+                    EXPORT  DMA0_Channel6_IRQHandler            [WEAK]
+                    EXPORT  ADC0_1_IRQHandler                   [WEAK]
+                    EXPORT  USBD_HP_CAN0_TX_IRQHandler          [WEAK]
+                    EXPORT  USBD_LP_CAN0_RX0_IRQHandler         [WEAK]
+                    EXPORT  CAN0_RX1_IRQHandler                 [WEAK]
+                    EXPORT  CAN0_EWMC_IRQHandler                [WEAK]
+                    EXPORT  EXTI5_9_IRQHandler                  [WEAK]
+                    EXPORT  TIMER0_BRK_TIMER8_IRQHandler        [WEAK]
+                    EXPORT  TIMER0_UP_TIMER9_IRQHandler         [WEAK]
+                    EXPORT  TIMER0_TRG_CMT_TIMER10_IRQHandler   [WEAK]
+                    EXPORT  TIMER0_Channel_IRQHandler           [WEAK]
+                    EXPORT  TIMER1_IRQHandler                   [WEAK]
+                    EXPORT  TIMER2_IRQHandler                   [WEAK]
+                    EXPORT  TIMER3_IRQHandler                   [WEAK]
+                    EXPORT  I2C0_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C0_ER_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_EV_IRQHandler                  [WEAK]
+                    EXPORT  I2C1_ER_IRQHandler                  [WEAK]
+                    EXPORT  SPI0_IRQHandler                     [WEAK]
+                    EXPORT  SPI1_IRQHandler                     [WEAK]
+                    EXPORT  USART0_IRQHandler                   [WEAK]
+                    EXPORT  USART1_IRQHandler                   [WEAK]
+                    EXPORT  USART2_IRQHandler                   [WEAK]
+                    EXPORT  EXTI10_15_IRQHandler                [WEAK]
+                    EXPORT  RTC_Alarm_IRQHandler                [WEAK]
+                    EXPORT  USBD_WKUP_IRQHandler                [WEAK]
+                    EXPORT  TIMER7_BRK_TIMER11_IRQHandler       [WEAK]
+                    EXPORT  TIMER7_UP_TIMER12_IRQHandler        [WEAK]
+                    EXPORT  TIMER7_TRG_CMT_TIMER13_IRQHandler   [WEAK]
+                    EXPORT  TIMER7_Channel_IRQHandler           [WEAK]
+                    EXPORT  ADC2_IRQHandler                     [WEAK]
+                    EXPORT  EXMC_IRQHandler                     [WEAK]
+                    EXPORT  SDIO_IRQHandler                     [WEAK]
+                    EXPORT  TIMER4_IRQHandler                   [WEAK]
+                    EXPORT  SPI2_IRQHandler                     [WEAK]
+                    EXPORT  UART3_IRQHandler                    [WEAK]
+                    EXPORT  UART4_IRQHandler                    [WEAK]
+                    EXPORT  TIMER5_IRQHandler                   [WEAK]
+                    EXPORT  TIMER6_IRQHandler                   [WEAK]
+                    EXPORT  DMA1_Channel0_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel1_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel2_IRQHandler            [WEAK]
+                    EXPORT  DMA1_Channel3_4_IRQHandler          [WEAK]
+   
+
+;/* external interrupts handler */
+WWDGT_IRQHandler
+LVD_IRQHandler
+TAMPER_IRQHandler
+RTC_IRQHandler
+FMC_IRQHandler 
+RCU_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA0_Channel0_IRQHandler
+DMA0_Channel1_IRQHandler
+DMA0_Channel2_IRQHandler
+DMA0_Channel3_IRQHandler
+DMA0_Channel4_IRQHandler
+DMA0_Channel5_IRQHandler
+DMA0_Channel6_IRQHandler
+ADC0_1_IRQHandler
+USBD_HP_CAN0_TX_IRQHandler
+USBD_LP_CAN0_RX0_IRQHandler
+CAN0_RX1_IRQHandler
+CAN0_EWMC_IRQHandler
+EXTI5_9_IRQHandler
+TIMER0_BRK_TIMER8_IRQHandler
+TIMER0_UP_TIMER9_IRQHandler
+TIMER0_TRG_CMT_TIMER10_IRQHandler
+TIMER0_Channel_IRQHandler
+TIMER1_IRQHandler
+TIMER2_IRQHandler
+TIMER3_IRQHandler
+I2C0_EV_IRQHandler
+I2C0_ER_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+SPI0_IRQHandler
+SPI1_IRQHandler
+USART0_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+EXTI10_15_IRQHandler
+RTC_Alarm_IRQHandler
+USBD_WKUP_IRQHandler
+TIMER7_BRK_TIMER11_IRQHandler
+TIMER7_UP_TIMER12_IRQHandler
+TIMER7_TRG_CMT_TIMER13_IRQHandler
+TIMER7_Channel_IRQHandler
+ADC2_IRQHandler
+EXMC_IRQHandler
+SDIO_IRQHandler
+TIMER4_IRQHandler
+SPI2_IRQHandler
+UART3_IRQHandler
+UART4_IRQHandler
+TIMER5_IRQHandler
+TIMER6_IRQHandler
+DMA1_Channel0_IRQHandler
+DMA1_Channel1_IRQHandler
+DMA1_Channel2_IRQHandler
+DMA1_Channel3_4_IRQHandler
+
+
+
+                B       .
+                ENDP
+
+                ALIGN
+
+; user Initial Stack & Heap
+
+                 IF      :DEF:__MICROLIB
+                
+                 EXPORT  __initial_sp
+                 EXPORT  __heap_base
+                 EXPORT  __heap_limit
+                
+                 ELSE
+                
+                 IMPORT  __use_two_region_memory
+                 EXPORT  __user_initial_stackheap
+                 
+__user_initial_stackheap PROC
+                 LDR     R0, =  Heap_Mem
+                 LDR     R1, =(Stack_Mem + Stack_Size)
+                 LDR     R2, = (Heap_Mem +  Heap_Size)
+                 LDR     R3, = Stack_Mem
+                 BX      LR
+                 ENDP
+                     
+                 ALIGN
+
+                 ENDIF
+
+                 END

+ 155 - 0
User/gd32f10x_it.c

@@ -0,0 +1,155 @@
+/*!
+    \file    gd32f10x_it.c
+    \brief   interrupt service routines
+    
+    \version 2015-11-16, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x_it.h"
+#include "systick.h"
+
+/*!
+    \brief      this function handles NMI exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void NMI_Handler(void)
+{
+}
+
+/*!
+    \brief      this function handles HardFault exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void HardFault_Handler(void)
+{
+    /* if Hard Fault exception occurs, go to infinite loop */
+    while(1){
+    }
+}
+
+/*!
+    \brief      this function handles MemManage exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void MemManage_Handler(void)
+{
+    /* if Memory Manage exception occurs, go to infinite loop */
+    while(1){
+    }
+}
+
+/*!
+    \brief      this function handles BusFault exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void BusFault_Handler(void)
+{
+    /* if Bus Fault exception occurs, go to infinite loop */
+    while(1){
+    }
+}
+
+/*!
+    \brief      this function handles UsageFault exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void UsageFault_Handler(void)
+{
+    /* if Usage Fault exception occurs, go to infinite loop */
+    while(1){
+    }
+}
+
+/*!
+    \brief      this function handles SVC exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void SVC_Handler(void)
+{
+}
+
+/*!
+    \brief      this function handles DebugMon exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void DebugMon_Handler(void)
+{
+}
+
+/*!
+    \brief      this function handles PendSV exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void PendSV_Handler(void)
+{
+}
+
+/*!
+    \brief      this function handles SysTick exception
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+extern void fwdgt_feed(uint32_t tickt);
+volatile uint32_t g_tick = 0;
+void SysTick_Handler(void)
+{
+  //  volatile uint8_t flag = 0;
+    g_tick++;
+  //  delay_decrement();
+  //  if((flag %2) ==0) {
+ //       opt_output_pluse();
+  //      flag = 0;
+  //  }
+ //   flag++;
+	fwdgt_feed(g_tick);
+}
+uint32_t Get_SysTick(void)
+{
+    return g_tick;
+}

+ 111 - 0
User/gd32f10x_it.h

@@ -0,0 +1,111 @@
+/*!
+    \file    gd32f10x_it.h
+    \brief   the header file of the ISR
+    
+    \version 2015-11-16, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_IT_H
+#define GD32F10X_IT_H
+
+#include "gd32f10x.h"
+
+/* function declarations */
+/* this function handles NMI exception */
+void NMI_Handler(void);
+/* this function handles HardFault exception */
+void HardFault_Handler(void);
+/* this function handles MemManage exception */
+void MemManage_Handler(void);
+/* this function handles BusFault exception */
+void BusFault_Handler(void);
+/* this function handles UsageFault exception */
+void UsageFault_Handler(void);
+/* this function handles SVC exception */
+void SVC_Handler(void);
+/* this function handles DebugMon exception */
+void DebugMon_Handler(void);
+/* this function handles PendSV exception */
+void PendSV_Handler(void);
+/* this function handles SysTick exception */
+void SysTick_Handler(void);
+extern uint32_t Get_SysTick(void);
+
+
+
+//IO口操作宏定义
+#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
+#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
+#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
+//IO口地址映射
+#define GPIOA_ODR_Addr    (GPIOA+12) //0x4001080C
+#define GPIOB_ODR_Addr    (GPIOB+12) //0x40010C0C
+#define GPIOC_ODR_Addr    (GPIOC+12) //0x4001100C
+#define GPIOD_ODR_Addr    (GPIOD+12) //0x4001140C
+#define GPIOE_ODR_Addr    (GPIOE+12) //0x4001180C
+#define GPIOF_ODR_Addr    (GPIOF+12) //0x40011A0C
+#define GPIOG_ODR_Addr    (GPIOG+12) //0x40011E0C
+
+#define GPIOA_IDR_Addr    (GPIOA+8) //0x40010808
+#define GPIOB_IDR_Addr    (GPIOB+8) //0x40010C08
+#define GPIOC_IDR_Addr    (GPIOC+8) //0x40011008
+#define GPIOD_IDR_Addr    (GPIOD+8) //0x40011408
+#define GPIOE_IDR_Addr    (GPIOE+8) //0x40011808
+#define GPIOF_IDR_Addr    (GPIOF+8) //0x40011A08
+#define GPIOG_IDR_Addr    (GPIOG+8) //0x40011E08
+
+//IO口操作,只对单一的IO口
+//确保N的值小于16!
+#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //ê?3?
+#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //ê?è?
+
+#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //ê?3?
+#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //ê?è?
+
+#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //ê?3?
+#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //ê?è?
+
+#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //ê?3?
+#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //ê?è?
+
+#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //ê?3?
+#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //ê?è?
+
+#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //ê?3?
+#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //ê?è?
+
+#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //ê?3?
+#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //ê?è?
+
+
+
+#endif /* GD32F10X_IT_H */

+ 64 - 0
User/gd32f10x_libopt.h

@@ -0,0 +1,64 @@
+/*!
+    \file    gd32f10x_libopt.h
+    \brief   library optional for gd32f10x
+    
+    \version 2015-11-16, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef GD32F10X_LIBOPT_H
+#define GD32F10X_LIBOPT_H
+
+#include "gd32f10x_adc.h"
+#include "gd32f10x_bkp.h"
+#include "gd32f10x_can.h"
+#include "gd32f10x_crc.h"
+#include "gd32f10x_dac.h"
+#include "gd32f10x_dma.h"
+#include "gd32f10x_enet.h"
+#include "gd32f10x_exmc.h"
+#include "gd32f10x_exti.h"
+#include "gd32f10x_fmc.h"
+#include "gd32f10x_gpio.h"
+#include "gd32f10x_i2c.h"
+#include "gd32f10x_fwdgt.h"
+#include "gd32f10x_dbg.h"
+#include "gd32f10x_misc.h"
+#include "gd32f10x_pmu.h"
+#include "gd32f10x_rcu.h"
+#include "gd32f10x_rtc.h"
+#include "gd32f10x_sdio.h"
+#include "gd32f10x_spi.h"
+#include "gd32f10x_timer.h"
+#include "gd32f10x_usart.h"
+#include "gd32f10x_wwdgt.h"
+
+#endif /* GD32F10X_LIBOPT_H */

+ 83 - 0
User/main.c

@@ -0,0 +1,83 @@
+#include "../CMSIS/gd32f10x.h"
+#include "systick.h"
+#include "../Hardware/boardinit.h"
+#include "../App/xspDataOpt.h"
+#include "../App/taskOpt.h"
+#include "../App/masterslave.h"
+
+extern volatile uint32_t g_tick;
+int main(void)
+{
+ //   uint8_t j = 0;
+ //   uint8_t i = 0,j = 0;
+
+    systick_config();
+		
+    board_init();
+    //init_fwdgt_timer();
+    //init_dev_msg();
+
+
+    epprom_power_up_deal();
+    ota_power_up_read_update_status();
+    printf_dev_msg();
+    srand(g_devMsg.devSn);
+    init_xsp_run_data();
+    powerup_read_record_from_flash(g_xspReDa.data);
+    power_up_read_comm_min_time();
+
+    uart_init();
+
+    init_run_data();
+    init_test_coll_data_info(1);
+    while(1){
+        config_file_is_timeout(); // 检查配置文件是否过期
+        if(key_scan()){
+            printf("按键按下 按键=%x, 次数=%d\r\n",g_keyinfo.keyVal,g_keyinfo.count);
+            key_opteration();
+            g_keyinfo.count = 0;
+            g_keyinfo.keyVal = 0;
+        }
+        if((g_timeInfo.bRead == 1)&& (g_testCollDa.bTestCollDa == 0)){
+//            exti_interrupt_disable(g_extimsg.extiLine);
+
+
+//            for(j=0;j<g_timeInfo.count;j++){
+//                printf("count : %02d  ",j);
+//                for(i=0;i<29;i++){
+//                    printf("%02X ",g_timeInfo.testsrcDa[j][i]);
+//                }
+//                printf("\n");
+//            }
+
+            anay_7eg();
+            g_timeInfo.bRead = 0;
+//            gpio_bit_reset(g_extimsg.csGroup,g_extimsg.csPin);
+            delay_ms(50);
+            if((g_up7segData.bofflineTest == 1)){
+                if(timeout_isOut(&g_up7segData.upTime)){
+                    slave_send_data_0x2030(g_devMsg.devType,g_devMsg.devSn,&g_7egDa[1],(uint8_t*)&g_table1027.confFileNum[0],28);
+                    timeout_start(&g_up7segData.upTime);
+                }
+            }
+//            exti_interrupt_enable(g_extimsg.extiLine);
+        }
+        else {
+            if(g_testCollDa.bTestCollDa == 1){
+                if(g_devMsg.bHYdev == 0x00)deal_coll_data_com();
+                else if(g_devMsg.bHYdev == 0x01) deal_coll_data_HY();
+                else deal_coll_data_com();
+            }
+        }
+        analysis_485_rx_fifo(); // 读取485的接收fifo
+        if(WORK_UPDATE == g_devMsg.workMode){
+            ota_check_update_timer();
+            ota_offline_handle();//离线升级
+        }
+        ota_update_deal_upstatus();//处理升级的状态上报
+
+//        usart_tx_dma_send(USART1,"abcde",5);
+//        printf("rtc_timer = %010u\r\n",rtc_counter_get());
+//        delay_ms(2000);
+    }
+}

+ 44 - 0
User/main.h

@@ -0,0 +1,44 @@
+/*!
+    \file    main.h
+    \brief   the header file of main 
+    
+    \version 2014-12-26, V1.0.0, firmware for GD32F10x
+    \version 2017-06-20, V2.0.0, firmware for GD32F10x
+    \version 2018-07-31, V2.1.0, firmware for GD32F10x
+    \version 2020-09-30, V2.2.0, firmware for GD32F10x
+*/
+
+/*
+    Copyright (c) 2020, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef __MAIN_H
+#define __MAIN_H
+
+/* led spark function */
+void led_spark(void);
+
+#endif /* __MAIN_H */

+ 39 - 0
User/readme.txt

@@ -0,0 +1,39 @@
+/*!
+    \file    readme.txt
+    \brief   description of the GPIO_Running_Led example
+    
+    \version 2015-11-16, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+  This demo is based on the GD32103C-EVAL-V1.2 board, LED2 connected to PC0. LED3 
+connected to PC2. LED4 connected to PE0. LED5 connected to PE1. Then, four LEDs 
+can light cycles.

+ 87 - 0
User/systick.c

@@ -0,0 +1,87 @@
+/*!
+    \file    systick.c
+    \brief   the systick configuration file
+    
+    \version 2014-12-26, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#include "gd32f10x.h"
+#include "systick.h"
+
+volatile static uint32_t delay;
+
+/*!
+    \brief      configure systick
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void systick_config(void)
+{
+    /* setup systick timer for 1000Hz interrupts */
+    if (SysTick_Config(SystemCoreClock / 1000U)){
+        /* capture error */
+        while(1){
+        }
+    }
+    /* configure the systick handler priority */
+    NVIC_SetPriority(SysTick_IRQn, 0x00U);
+		//__ASM volatile("cpsie i");	
+		__set_PRIMASK(0);
+}
+
+/*!
+    \brief      delay a time in milliseconds
+    \param[in]  count: count in milliseconds
+    \param[out] none
+    \retval     none
+*/
+void delay_1ms(uint32_t count)
+{
+    delay = count;
+
+    while(0U != delay){
+    }
+}
+
+/*!
+    \brief      delay decrement
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void delay_decrement(void)
+{
+    if(0U != delay){
+        delay--;
+    }
+}

+ 53 - 0
User/systick.h

@@ -0,0 +1,53 @@
+/*!
+    \file    systick.h
+    \brief   the header file of systick
+    
+    \version 2014-12-26, V1.0.0, demo for GD32F10x
+    \version 2017-06-30, V2.0.0, demo for GD32F10x
+    \version 2021-04-30, V2.1.0, demo for GD32F10x
+*/
+
+/*
+    Copyright (c) 2021, GigaDevice Semiconductor Inc.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice, this 
+       list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice, 
+       this list of conditions and the following disclaimer in the documentation 
+       and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holder nor the names of its contributors 
+       may be used to endorse or promote products derived from this software without 
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+OF SUCH DAMAGE.
+*/
+
+#ifndef SYSTICK_H
+#define SYSTICK_H
+
+#include <stdint.h>
+
+/* configure systick */
+void systick_config(void);
+/* delay a time in milliseconds */
+void delay_1ms(uint32_t count);
+/* delay decrement */
+void delay_decrement(void);
+
+
+
+
+
+#endif /* SYSTICK_H */