Browse Source

fist commit

haitao 9 months ago
parent
commit
58b7bf90d0
100 changed files with 55713 additions and 0 deletions
  1. 1790 0
      app/CMSIS/include/core_cm4.h
  2. 697 0
      app/CMSIS/include/core_cm4_simd.h
  3. 616 0
      app/CMSIS/include/core_cmFunc.h
  4. 618 0
      app/CMSIS/include/core_cmInstr.h
  5. 356 0
      app/CMSIS/include/gd32f30x.h
  6. 58 0
      app/CMSIS/include/system_gd32f30x.h
  7. 385 0
      app/CMSIS/source/startup_gd32f30x_cl.s
  8. 365 0
      app/CMSIS/source/startup_gd32f30x_hd.s
  9. 365 0
      app/CMSIS/source/startup_gd32f30x_xd.s
  10. 987 0
      app/CMSIS/source/system_gd32f30x.c
  11. 395 0
      app/FreeRTOS-8.2.3/croutine.c
  12. 683 0
      app/FreeRTOS-8.2.3/event_groups.c
  13. 835 0
      app/FreeRTOS-8.2.3/include/FreeRTOS.h
  14. 171 0
      app/FreeRTOS-8.2.3/include/StackMacros.h
  15. 762 0
      app/FreeRTOS-8.2.3/include/croutine.h
  16. 321 0
      app/FreeRTOS-8.2.3/include/deprecated_definitions.h
  17. 730 0
      app/FreeRTOS-8.2.3/include/event_groups.h
  18. 453 0
      app/FreeRTOS-8.2.3/include/list.h
  19. 177 0
      app/FreeRTOS-8.2.3/include/mpu_wrappers.h
  20. 207 0
      app/FreeRTOS-8.2.3/include/portable.h
  21. 156 0
      app/FreeRTOS-8.2.3/include/projdefs.h
  22. 1691 0
      app/FreeRTOS-8.2.3/include/queue.h
  23. 844 0
      app/FreeRTOS-8.2.3/include/semphr.h
  24. 27 0
      app/FreeRTOS-8.2.3/include/stdint.readme
  25. 2037 0
      app/FreeRTOS-8.2.3/include/task.h
  26. 1146 0
      app/FreeRTOS-8.2.3/include/timers.h
  27. 240 0
      app/FreeRTOS-8.2.3/list.c
  28. 630 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/port.c
  29. 159 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/portasm.s
  30. 200 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/portmacro.h
  31. 658 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/port.c
  32. 185 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/portasm.s
  33. 213 0
      app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/portmacro.h
  34. 1 0
      app/FreeRTOS-8.2.3/portable/Keil/See-also-the-RVDS-directory.txt
  35. 174 0
      app/FreeRTOS-8.2.3/portable/MemMang/heap_1.c
  36. 303 0
      app/FreeRTOS-8.2.3/portable/MemMang/heap_2.c
  37. 135 0
      app/FreeRTOS-8.2.3/portable/MemMang/heap_3.c
  38. 474 0
      app/FreeRTOS-8.2.3/portable/MemMang/heap_4.c
  39. 523 0
      app/FreeRTOS-8.2.3/portable/MemMang/heap_5.c
  40. 729 0
      app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM3/port.c
  41. 193 0
      app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM3/portmacro.h
  42. 782 0
      app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM4F/port.c
  43. 256 0
      app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM4F/portmacro.h
  44. 19 0
      app/FreeRTOS-8.2.3/portable/readme.txt
  45. 2608 0
      app/FreeRTOS-8.2.3/queue.c
  46. 4477 0
      app/FreeRTOS-8.2.3/tasks.c
  47. 929 0
      app/FreeRTOS-8.2.3/timers.c
  48. 99 0
      app/HW/include/hd_eth.h
  49. 37 0
      app/HW/include/led.h
  50. 21 0
      app/HW/include/netconf.h
  51. 36 0
      app/HW/include/usart.h
  52. 191 0
      app/HW/source/hd_eth.c
  53. 68 0
      app/HW/source/led.c
  54. 300 0
      app/HW/source/netconf.c
  55. 113 0
      app/HW/source/usart.c
  56. 403 0
      app/LIB/Include/gd32f30x_adc.h
  57. 244 0
      app/LIB/Include/gd32f30x_bkp.h
  58. 749 0
      app/LIB/Include/gd32f30x_can.h
  59. 81 0
      app/LIB/Include/gd32f30x_crc.h
  60. 185 0
      app/LIB/Include/gd32f30x_ctc.h
  61. 250 0
      app/LIB/Include/gd32f30x_dac.h
  62. 149 0
      app/LIB/Include/gd32f30x_dbg.h
  63. 285 0
      app/LIB/Include/gd32f30x_dma.h
  64. 1702 0
      app/LIB/Include/gd32f30x_enet.h
  65. 446 0
      app/LIB/Include/gd32f30x_exmc.h
  66. 258 0
      app/LIB/Include/gd32f30x_exti.h
  67. 375 0
      app/LIB/Include/gd32f30x_fmc.h
  68. 114 0
      app/LIB/Include/gd32f30x_fwdgt.h
  69. 537 0
      app/LIB/Include/gd32f30x_gpio.h
  70. 357 0
      app/LIB/Include/gd32f30x_i2c.h
  71. 94 0
      app/LIB/Include/gd32f30x_misc.h
  72. 192 0
      app/LIB/Include/gd32f30x_pmu.h
  73. 1070 0
      app/LIB/Include/gd32f30x_rcu.h
  74. 138 0
      app/LIB/Include/gd32f30x_rtc.h
  75. 434 0
      app/LIB/Include/gd32f30x_sdio.h
  76. 368 0
      app/LIB/Include/gd32f30x_spi.h
  77. 752 0
      app/LIB/Include/gd32f30x_timer.h
  78. 444 0
      app/LIB/Include/gd32f30x_usart.h
  79. 95 0
      app/LIB/Include/gd32f30x_wwdgt.h
  80. 941 0
      app/LIB/Source/gd32f30x_adc.c
  81. 328 0
      app/LIB/Source/gd32f30x_bkp.c
  82. 1043 0
      app/LIB/Source/gd32f30x_can.c
  83. 130 0
      app/LIB/Source/gd32f30x_crc.c
  84. 391 0
      app/LIB/Source/gd32f30x_ctc.c
  85. 541 0
      app/LIB/Source/gd32f30x_dac.c
  86. 148 0
      app/LIB/Source/gd32f30x_dbg.c
  87. 735 0
      app/LIB/Source/gd32f30x_dma.c
  88. 3680 0
      app/LIB/Source/gd32f30x_enet.c
  89. 677 0
      app/LIB/Source/gd32f30x_exmc.c
  90. 252 0
      app/LIB/Source/gd32f30x_exti.c
  91. 1009 0
      app/LIB/Source/gd32f30x_fmc.c
  92. 223 0
      app/LIB/Source/gd32f30x_fwdgt.c
  93. 583 0
      app/LIB/Source/gd32f30x_gpio.c
  94. 738 0
      app/LIB/Source/gd32f30x_i2c.c
  95. 176 0
      app/LIB/Source/gd32f30x_misc.c
  96. 400 0
      app/LIB/Source/gd32f30x_pmu.c
  97. 1332 0
      app/LIB/Source/gd32f30x_rcu.c
  98. 230 0
      app/LIB/Source/gd32f30x_rtc.c
  99. 809 0
      app/LIB/Source/gd32f30x_sdio.c
  100. 0 0
      app/LIB/Source/gd32f30x_spi.c

File diff suppressed because it is too large
+ 1790 - 0
app/CMSIS/include/core_cm4.h


+ 697 - 0
app/CMSIS/include/core_cm4_simd.h

@@ -0,0 +1,697 @@
+/**************************************************************************//**
+ * @file     core_cm4_simd.h
+ * @brief    CMSIS Cortex-M4 SIMD 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
+
+#ifndef __CORE_CM4_SIMD_H
+#define __CORE_CM4_SIMD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/*******************************************************************************
+ *                Hardware Abstraction Layer
+ ******************************************************************************/
+
+
+/* ###################  Compiler specific Intrinsics  ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+  Access to dedicated SIMD instructions
+  @{
+*/
+
+#if   defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+#define __SADD8                           __sadd8
+#define __QADD8                           __qadd8
+#define __SHADD8                          __shadd8
+#define __UADD8                           __uadd8
+#define __UQADD8                          __uqadd8
+#define __UHADD8                          __uhadd8
+#define __SSUB8                           __ssub8
+#define __QSUB8                           __qsub8
+#define __SHSUB8                          __shsub8
+#define __USUB8                           __usub8
+#define __UQSUB8                          __uqsub8
+#define __UHSUB8                          __uhsub8
+#define __SADD16                          __sadd16
+#define __QADD16                          __qadd16
+#define __SHADD16                         __shadd16
+#define __UADD16                          __uadd16
+#define __UQADD16                         __uqadd16
+#define __UHADD16                         __uhadd16
+#define __SSUB16                          __ssub16
+#define __QSUB16                          __qsub16
+#define __SHSUB16                         __shsub16
+#define __USUB16                          __usub16
+#define __UQSUB16                         __uqsub16
+#define __UHSUB16                         __uhsub16
+#define __SASX                            __sasx
+#define __QASX                            __qasx
+#define __SHASX                           __shasx
+#define __UASX                            __uasx
+#define __UQASX                           __uqasx
+#define __UHASX                           __uhasx
+#define __SSAX                            __ssax
+#define __QSAX                            __qsax
+#define __SHSAX                           __shsax
+#define __USAX                            __usax
+#define __UQSAX                           __uqsax
+#define __UHSAX                           __uhsax
+#define __USAD8                           __usad8
+#define __USADA8                          __usada8
+#define __SSAT16                          __ssat16
+#define __USAT16                          __usat16
+#define __UXTB16                          __uxtb16
+#define __UXTAB16                         __uxtab16
+#define __SXTB16                          __sxtb16
+#define __SXTAB16                         __sxtab16
+#define __SMUAD                           __smuad
+#define __SMUADX                          __smuadx
+#define __SMLAD                           __smlad
+#define __SMLADX                          __smladx
+#define __SMLALD                          __smlald
+#define __SMLALDX                         __smlaldx
+#define __SMUSD                           __smusd
+#define __SMUSDX                          __smusdx
+#define __SMLSD                           __smlsd
+#define __SMLSDX                          __smlsdx
+#define __SMLSLD                          __smlsld
+#define __SMLSLDX                         __smlsldx
+#define __SEL                             __sel
+#define __QADD                            __qadd
+#define __QSUB                            __qsub
+
+#define __PKHBT(ARG1,ARG2,ARG3)          ( ((((uint32_t)(ARG1))          ) & 0x0000FFFFUL) |  \
+                                           ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL)  )
+
+#define __PKHTB(ARG1,ARG2,ARG3)          ( ((((uint32_t)(ARG1))          ) & 0xFFFF0000UL) |  \
+                                           ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL)  )
+
+#define __SMMLA(ARG1,ARG2,ARG3)          ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
+                                                      ((int64_t)(ARG3) << 32)      ) >> 32))
+
+
+#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
+{
+  uint32_t result;
+
+  __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+  return(result);
+}
+
+#define __SSAT16(ARG1,ARG2) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1); \
+  __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
+  __RES; \
+ })
+
+#define __USAT16(ARG1,ARG2) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1); \
+  __ASM ("usat16 %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
+  __RES; \
+ })
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
+{
+  uint32_t result;
+
+  __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
+{
+  uint32_t result;
+
+  __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD  (uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+  uint32_t result;
+
+  __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+  uint32_t result;
+
+  __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+  union llreg_u{
+    uint32_t w32[2];
+    uint64_t w64;
+  } llr;
+  llr.w64 = acc;
+
+#ifndef __ARMEB__   // Little endian
+  __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else               // Big endian
+  __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+  return(llr.w64);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+  union llreg_u{
+    uint32_t w32[2];
+    uint64_t w64;
+  } llr;
+  llr.w64 = acc;
+
+#ifndef __ARMEB__   // Little endian
+  __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else               // Big endian
+  __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+  return(llr.w64);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD  (uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+  uint32_t result;
+
+  __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+  uint32_t result;
+
+  __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+  union llreg_u{
+    uint32_t w32[2];
+    uint64_t w64;
+  } llr;
+  llr.w64 = acc;
+
+#ifndef __ARMEB__   // Little endian
+  __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else               // Big endian
+  __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+  return(llr.w64);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+  union llreg_u{
+    uint32_t w32[2];
+    uint64_t w64;
+  } llr;
+  llr.w64 = acc;
+
+#ifndef __ARMEB__   // Little endian
+  __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else               // Big endian
+  __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+  return(llr.w64);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL  (uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
+{
+  uint32_t result;
+
+  __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+  return(result);
+}
+
+#define __PKHBT(ARG1,ARG2,ARG3) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+  __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) :  "r" (__ARG1), "r" (__ARG2), "I" (ARG3)  ); \
+  __RES; \
+ })
+
+#define __PKHTB(ARG1,ARG2,ARG3) \
+({                          \
+  uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+  if (ARG3 == 0) \
+    __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) :  "r" (__ARG1), "r" (__ARG2)  ); \
+  else \
+    __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) :  "r" (__ARG1), "r" (__ARG2), "I" (ARG3)  ); \
+  __RES; \
+ })
+
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+{
+ int32_t result;
+
+ __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r"  (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+
+#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 */
+/* not yet supported */
+
+
+#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
+/* Cosmic specific functions */
+#include <cmsis_csm.h>
+
+#endif
+
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM4_SIMD_H */

+ 616 - 0
app/CMSIS/include/core_cmFunc.h

@@ -0,0 +1,616 @@
+/**************************************************************************//**
+ * @file     core_cmFunc.h
+ * @brief    CMSIS Cortex-M Core Function Access Header File
+ * @version  V3.01
+ * @date     06. March 2012
+ *
+ * @note
+ * Copyright (C) 2009-2012 ARM Limited. All rights reserved.
+ *
+ * @par
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M
+ * processor based microcontrollers.  This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * @par
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+#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 ( __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 ( __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");
+}
+
+
+/** \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");
+}
+
+
+/** \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) );
+}
+
+
+/** \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) );
+}
+
+
+/** \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) );
+}
+
+
+/** \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) );
+}
+
+
+#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");
+}
+
+
+/** \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");
+}
+
+
+/** \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) );
+}
+
+
+/** \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) );
+}
+
+#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;
+
+  __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
+  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)
+  __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) );
+#endif
+}
+
+#endif /* (__CORTEX_M == 0x04) */
+
+
+#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 instrinsics,
+ * Including the CMSIS ones.
+ */
+
+#endif
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+#endif /* __CORE_CMFUNC_H */

+ 618 - 0
app/CMSIS/include/core_cmInstr.h

@@ -0,0 +1,618 @@
+/**************************************************************************//**
+ * @file     core_cmInstr.h
+ * @brief    CMSIS Cortex-M Core Instruction Access Header File
+ * @version  V3.01
+ * @date     06. March 2012
+ *
+ * @note
+ * Copyright (C) 2009-2012 ARM Limited. All rights reserved.
+ *
+ * @par
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M
+ * processor based microcontrollers.  This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * @par
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+#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
+ */
+__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
+{
+  rev16 r0, r0
+  bx lr
+}
+
+
+/** \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__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
+{
+  revsh r0, r0
+  bx lr
+}
+
+
+/** \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
+
+
+#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 ( __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 ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+/** \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)
+{
+  uint32_t result;
+
+  __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
+  return(result);
+}
+
+
+/** \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" : "=r" (result) : "r" (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)
+{
+  uint32_t result;
+
+  __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
+  return(result);
+}
+
+
+/** \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)
+{
+
+  __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) );
+  return(op1);
+}
+
+
+#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)
+{
+    uint8_t result;
+
+   __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
+   return(result);
+}
+
+
+/** \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)
+{
+    uint16_t result;
+
+   __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
+   return(result);
+}
+
+
+/** \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) : "r" (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) : "r" (addr), "r" (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) : "r" (addr), "r" (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) : "r" (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");
+}
+
+
+/** \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)
+{
+  uint8_t result;
+
+  __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
+  return(result);
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+
+
+#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.
+ */
+
+#endif
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+#endif /* __CORE_CMINSTR_H */

+ 356 - 0
app/CMSIS/include/gd32f30x.h

@@ -0,0 +1,356 @@
+/*!
+    \file  gd32f30x.h
+    \brief general definitions for GD32F30x
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+*/
+
+/*
+    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.
+*/
+
+#ifndef GD32F30X_H
+#define GD32F30X_H
+
+#ifdef cplusplus
+ extern "C" {
+#endif 
+
+/* define GD32F30x */
+#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL)
+  /* #define GD32F30X_HD */
+  /* #define GD32F30X_XD */
+  /* #define GD32F30X_CL */
+#endif /* define GD32F30x */
+   
+#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL)
+ #error "Please select the target GD32F30x device in gd32f30x.h file"
+#endif /* undefine GD32F30x tip */
+
+/* define value of high speed crystal oscillator (HXTAL) in Hz */
+#if !defined  HXTAL_VALUE    
+#ifdef GD32F30X_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)0x0800)
+#endif /* high speed crystal oscillator startup timeout */
+
+/* define value of internal 48MHz RC oscillator (IRC48M) in Hz */
+#if !defined  (IRC48M_VALUE) 
+#define IRC48M_VALUE  ((uint32_t)48000000)
+#endif /* internal 48MHz RC oscillator value */
+
+/* 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 */
+
+/* GD32F30x firmware library version number V1.0 */
+#define __GD32F30x_STDPERIPH_VERSION_MAIN   (0x01) /*!< [31:24] main version     */
+#define __GD32F30x_STDPERIPH_VERSION_SUB1   (0x00) /*!< [23:16] sub1 version     */
+#define __GD32F30x_STDPERIPH_VERSION_SUB2   (0x00) /*!< [15:8]  sub2 version     */
+#define __GD32F30x_STDPERIPH_VERSION_RC     (0x00) /*!< [7:0]  release candidate */ 
+#define __GD32F30x_STDPERIPH_VERSION        ((__GD32F30x_STDPERIPH_VERSION_MAIN << 24)\
+                                            |(__GD32F30x_STDPERIPH_VERSION_SUB1 << 16)\
+                                            |(__GD32F30x_STDPERIPH_VERSION_SUB2 << 8)\
+                                            |(__GD32F30x_STDPERIPH_VERSION_RC))
+
+/* configuration of the Cortex-M4 processor and core peripherals */
+#define __CM4_REV                 0x0001   /*!< Core revision r0p1                                       */
+#define __MPU_PRESENT             1        /*!< GD32F30x do not provide MPU                              */
+#define __NVIC_PRIO_BITS          4        /*!< GD32F30x 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-M4 processor exceptions numbers */
+    NonMaskableInt_IRQn          = -14,    /*!< 2 non maskable interrupt                                 */
+    MemoryManagement_IRQn        = -12,    /*!< 4 Cortex-M4 memory management interrupt                  */
+    BusFault_IRQn                = -11,    /*!< 5 Cortex-M4 bus fault interrupt                          */
+    UsageFault_IRQn              = -10,    /*!< 6 Cortex-M4 usage fault interrupt                        */
+    SVCall_IRQn                  = -5,     /*!< 11 Cortex-M4 SV call interrupt                           */
+    DebugMonitor_IRQn            = -4,     /*!< 12 Cortex-M4 debug monitor interrupt                     */
+    PendSV_IRQn                  = -2,     /*!< 14 Cortex-M4 pend SV interrupt                           */
+    SysTick_IRQn                 = -1,     /*!< 15 Cortex-M4 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 GD32F30X_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 /* GD32F30X_HD */
+
+#ifdef GD32F30X_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 /* GD32F30X_XD */
+
+#ifdef GD32F30X_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_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                                      */
+    USBFS_WKUP_IRQn              = 42,     /*!< USBFS 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                */
+    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 /* GD32F30X_CL */
+
+} IRQn_Type;
+
+/* includes */
+#include "core_cm4.h"
+#include "system_gd32f30x.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 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                 */
+#define CTC_BASE              (APB1_BUS_BASE + 0x0000C800U)  /*!< CTC 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 "gd32f30x_libopt.h"
+#endif /* USE_STDPERIPH_DRIVER */
+
+#ifdef cplusplus
+}
+#endif
+#endif 

+ 58 - 0
app/CMSIS/include/system_gd32f30x.h

@@ -0,0 +1,58 @@
+/*!
+    \file  system_gd32f30x.h
+    \brief CMSIS Cortex-M4 Device Peripheral Access Layer Header File for
+           GD32F30x 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:
+   - 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.
+   ---------------------------------------------------------------------------*/
+
+/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
+
+#ifndef SYSTEM_GD32F30X_H
+#define SYSTEM_GD32F30X_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_GD32F30X_H */

+ 385 - 0
app/CMSIS/source/startup_gd32f30x_cl.s

@@ -0,0 +1,385 @@
+;/*!
+;    \file    startup_gd32f30x_cl.s
+;    \brief   start up file
+;
+;    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+;    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+;    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+;    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+;*/
+;
+;/*
+;    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.
+;*/
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size      EQU     0x00001000
+
+                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     0x00008000
+
+                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 through EXTI Line detect
+                DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                DCD     FMC_IRQHandler                    ; 20:FMC
+                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
+                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 Channel0
+                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
+                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
+                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
+                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
+                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
+                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
+                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:EXTI5 to EXTI9
+                DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8
+                DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9
+                DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
+                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:EXTI10 to EXTI15
+                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
+                DCD     USBFS_WKUP_IRQHandler             ; 58:USBFS Wakeup
+                DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break and TIMER11
+                DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update and TIMER12
+                DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
+                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  SystemInit
+                IMPORT  __main
+                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_CTC_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_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  USBFS_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  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_CTC_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_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             
+USBFS_WKUP_IRQHandler             
+TIMER7_BRK_TIMER11_IRQHandler   
+TIMER7_UP_TIMER12_IRQHandler  
+TIMER7_TRG_CMT_TIMER13_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

+ 365 - 0
app/CMSIS/source/startup_gd32f30x_hd.s

@@ -0,0 +1,365 @@
+;/*!
+;    \file    startup_gd32f30x_hd.s
+;    \brief   start up file
+;
+;    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+;    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+;    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+;    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+;*/
+;
+;/*
+;    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.
+;*/
+
+; <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     0x00000400
+
+                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 through EXTI Line detect
+                DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                DCD     FMC_IRQHandler                    ; 20:FMC
+                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
+                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 Channel0
+                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
+                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
+                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
+                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
+                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
+                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
+                DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD HP and CAN0 TX
+                DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD LP and CAN0 RX0
+                DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                DCD     EXTI5_9_IRQHandler                ; 39:EXTI5 to EXTI9
+                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:EXTI10 to EXTI15
+                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
+                DCD     USBD_WKUP_IRQHandler              ; 58:USBD Wakeup
+                DCD     TIMER7_BRK_IRQHandler             ; 59:TIMER7 Break 
+                DCD     TIMER7_UP_IRQHandler              ; 60:TIMER7 Update 
+                DCD     TIMER7_TRG_CMT_IRQHandler         ; 61:TIMER7 Trigger and Commutation
+                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  SystemInit
+                IMPORT  __main
+                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_CTC_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_CTC_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

+ 365 - 0
app/CMSIS/source/startup_gd32f30x_xd.s

@@ -0,0 +1,365 @@
+;/*!
+;    \file    startup_gd32f30x_xd.s
+;    \brief   start up file
+;
+;    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+;    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+;    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+;    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+;*/
+;
+;/*
+;    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.
+;*/
+
+; <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     0x00000400
+
+                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 through EXTI Line detect
+                DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
+                DCD     FMC_IRQHandler                    ; 20:FMC
+                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
+                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 Channel0
+                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
+                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
+                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
+                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
+                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
+                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
+                DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
+                DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD HP and CAN0 TX
+                DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD LP and CAN0 RX0
+                DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
+                DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
+                DCD     EXTI5_9_IRQHandler                ; 39:EXTI5 to EXTI9
+                DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8
+                DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9
+                DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
+                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:EXTI10 to EXTI15
+                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
+                DCD     USBD_WKUP_IRQHandler              ; 58:USBD Wakeup
+                DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break and TIMER11
+                DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update and TIMER12
+                DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
+                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  SystemInit
+                IMPORT  __main
+                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_CTC_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_CTC_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

+ 987 - 0
app/CMSIS/source/system_gd32f30x.c

@@ -0,0 +1,987 @@
+/*!
+    \file  system_gd32f30x.c
+    \brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for
+           GD32F30x 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:
+   - 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.
+   ---------------------------------------------------------------------------*/
+
+/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
+
+#include "gd32f30x.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 */
+
+/* select a system clock by uncommenting the following line */
+/* use IRC8M */
+//#define __SYSTEM_CLOCK_IRC8M                    (uint32_t)(__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)
+//#define __SYSTEM_CLOCK_120M_PLL_IRC8M           (uint32_t)(120000000)
+
+/* use HXTAL(XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */
+//#define __SYSTEM_CLOCK_HXTAL                    (uint32_t)(__HXTAL)
+//#define __SYSTEM_CLOCK_48M_PLL_HXTAL            (uint32_t)(48000000)
+//#define __SYSTEM_CLOCK_72M_PLL_HXTAL            (uint32_t)(72000000)
+//#define __SYSTEM_CLOCK_108M_PLL_HXTAL           (uint32_t)(108000000)
+#define __SYSTEM_CLOCK_120M_PLL_HXTAL           (uint32_t)(120000000)
+
+#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_IRC8M
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M;
+static void system_clock_8m_irc8m(void);
+#elif defined (__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_120M_PLL_IRC8M)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M;
+static void system_clock_120m_irc8m(void);
+
+#elif defined (__SYSTEM_CLOCK_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
+static void system_clock_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_72M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
+static void system_clock_72m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL;
+static void system_clock_108m_hxtal(void);
+#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
+uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL;
+static void system_clock_120m_hxtal(void);
+#endif /* __SYSTEM_CLOCK_IRC8M */
+
+/* configure the system clock */
+static void system_clock_config(void);
+
+/*!
+    \brief      setup the microcontroller system, initialize the system
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void SystemInit (void)
+{
+  /* FPU settings */
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
+#endif
+    /* reset the RCU clock configuration to the default reset state */
+    /* Set IRC8MEN bit */
+    RCU_CTL |= RCU_CTL_IRC8MEN;
+
+    /* Reset CFG0 and CFG1 registers */
+    RCU_CFG0 = 0x00000000U;
+    RCU_CFG1 = 0x00000000U;
+
+#if (defined(GD32F30X_HD) || defined(GD32F30X_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(GD32F30X_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
+
+    /* reset HXTALBPS bit */
+    RCU_CTL &= ~(RCU_CTL_HXTALBPS);
+
+    /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
+    system_clock_config();
+}
+/*!
+    \brief      configure the system clock
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_config(void)
+{
+#ifdef __SYSTEM_CLOCK_IRC8M
+    system_clock_8m_irc8m();
+#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();
+#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
+    system_clock_120m_irc8m();
+
+#elif defined (__SYSTEM_CLOCK_HXTAL)
+    system_clock_hxtal();
+#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
+    system_clock_48m_hxtal();
+#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
+    system_clock_72m_hxtal();
+#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
+    system_clock_108m_hxtal();
+#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
+    system_clock_120m_hxtal();
+#endif /* __SYSTEM_CLOCK_IRC8M */
+}
+
+#ifdef __SYSTEM_CLOCK_IRC8M
+/*!
+    \brief      configure the system clock to 8M by IRC8M
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_8m_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){
+        }
+    }
+    
+    /* 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 IRC8M as system clock */
+    RCU_CFG0 &= ~RCU_CFG0_SCS;
+    RCU_CFG0 |= RCU_CKSYSSRC_IRC8M;
+    
+    /* wait until IRC8M is selected as system clock */
+    while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){
+    }
+}
+
+#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){
+      }
+    }
+
+    /* LDO output voltage high mode */
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL12;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+    
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+    
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    } 
+    
+    /* 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){
+        }
+    }
+
+    /* LDO output voltage high mode */
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL18;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+    
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+    
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+    
+    /* 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){
+        }
+    }
+
+    /* LDO output voltage high mode */
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL27;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+    
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+    
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+    
+    /* 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_120M_PLL_IRC8M)
+/*!
+    \brief      configure the system clock to 120M by PLL which selects IRC8M as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_120m_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){
+        }
+    }
+
+    /* LDO output voltage high mode */
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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) * 30 = 120 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL30;
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+    
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+    
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+    
+    /* 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_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_48M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 48M by PLL which selects HXTAL(8M) 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){
+        }
+    }
+
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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(GD32F30X_HD) || defined(GD32F30X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL12;
+
+#elif defined(GD32F30X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL12);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | 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 /* GD32F30X_HD and GD32F30X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+
+    /* 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(8M) 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){
+        }
+    }
+
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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(GD32F30X_HD) || defined(GD32F30X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL18;
+
+#elif defined(GD32F30X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | 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 /* GD32F30X_HD and GD32F30X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+
+    /* 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(8M) 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){
+        }
+    }
+
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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(GD32F30X_HD) || defined(GD32F30X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL27;
+
+#elif defined(GD32F30X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL27);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | 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 /* GD32F30X_HD and GD32F30X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+
+    /* 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_120M_PLL_HXTAL)
+/*!
+    \brief      configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void system_clock_120m_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){
+        }
+    }
+
+    RCU_APB1EN |= RCU_APB1EN_PMUEN;
+    PMU_CTL |= PMU_CTL_LDOVS;
+
+    /* 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(GD32F30X_HD) || defined(GD32F30X_XD))
+    /* select HXTAL/2 as clock source */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
+
+    /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= RCU_PLL_MUL30;
+
+#elif defined(GD32F30X_CL)
+    /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ 
+    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
+    RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30);
+
+    /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ 
+    RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
+    RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | 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) == 0U){
+    }
+#endif /* GD32F30X_HD and GD32F30X_XD */
+
+    /* enable PLL */
+    RCU_CTL |= RCU_CTL_PLLEN;
+
+    /* wait until PLL is stable */
+    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
+    }
+
+    /* enable the high-drive to extend the clock frequency to 120 MHz */
+    PMU_CTL |= PMU_CTL_HDEN;
+    while(0U == (PMU_CS & PMU_CS_HDRF)){
+    }
+
+    /* select the high-drive mode */
+    PMU_CTL |= PMU_CTL_HDS;
+    while(0U == (PMU_CS & PMU_CS_HDSRF)){
+    }
+
+    /* 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 /* __SYSTEM_CLOCK_IRC8M */
+
+/*!
+    \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 sws;
+    uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src;
+#ifdef GD32F30X_CL
+    uint32_t predv0, predv1, pll1mf;
+#endif /* GD32F30X_CL */
+
+    sws = GET_BITS(RCU_CFG0, 2, 3);
+    switch(sws){
+    /* 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, IRC48M or IRC8M/2 */
+        pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
+
+        if (RCU_PLLSRC_HXTAL_IRC48M == pllsel) {
+            /* PLL clock source is HXTAL or IRC48M */
+            pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
+            
+            if(RCU_PLLPRESRC_HXTAL == pllpresel){
+                /* PLL clock source is HXTAL */
+                ck_src = HXTAL_VALUE;
+            }else{
+                /* PLL clock source is IRC48 */
+                ck_src = IRC48M_VALUE;
+            }
+
+#if (defined(GD32F30X_HD) || defined(GD32F30X_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(GD32F30X_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 /* GD32F30X_HD and GD32F30X_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((RCU_CFG0 & RCU_CFG0_PLLMF_5)){
+            pllmf |= 0x20U;
+        }
+
+        if( pllmf >= 15U){
+            pllmf += 1U;
+        }else{
+            pllmf += 2U;
+        }
+        if(pllmf > 61U){
+            pllmf = 63U;
+        }
+        SystemCoreClock = ck_src*pllmf;
+    #ifdef GD32F30X_CL
+        if(15U == pllmf){
+            SystemCoreClock = ck_src*6U + ck_src/2U;
+        }
+    #endif /* GD32F30X_CL */
+
+        break;
+    /* IRC8M is selected as CK_SYS */
+    default:
+        SystemCoreClock = IRC8M_VALUE;
+        break;
+    }
+
+}

+ 395 - 0
app/FreeRTOS-8.2.3/croutine.c

@@ -0,0 +1,395 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "croutine.h"
+
+/* Remove the whole file is co-routines are not being used. */
+#if( configUSE_CO_ROUTINES != 0 )
+
+/*
+ * Some kernel aware debuggers require data to be viewed to be global, rather
+ * than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+	#define static
+#endif
+
+
+/* Lists for ready and blocked co-routines. --------------------*/
+static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ];	/*< Prioritised ready co-routines. */
+static List_t xDelayedCoRoutineList1;									/*< Delayed co-routines. */
+static List_t xDelayedCoRoutineList2;									/*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
+static List_t * pxDelayedCoRoutineList;									/*< Points to the delayed co-routine list currently being used. */
+static List_t * pxOverflowDelayedCoRoutineList;							/*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
+static List_t xPendingReadyCoRoutineList;								/*< Holds co-routines that have been readied by an external event.  They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
+
+/* Other file private variables. --------------------------------*/
+CRCB_t * pxCurrentCoRoutine = NULL;
+static UBaseType_t uxTopCoRoutineReadyPriority = 0;
+static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
+
+/* The initial state of the co-routine when it is created. */
+#define corINITIAL_STATE	( 0 )
+
+/*
+ * Place the co-routine represented by pxCRCB into the appropriate ready queue
+ * for the priority.  It is inserted at the end of the list.
+ *
+ * This macro accesses the co-routine ready lists and therefore must not be
+ * used from within an ISR.
+ */
+#define prvAddCoRoutineToReadyQueue( pxCRCB )																		\
+{																													\
+	if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority )															\
+	{																												\
+		uxTopCoRoutineReadyPriority = pxCRCB->uxPriority;															\
+	}																												\
+	vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) );	\
+}
+
+/*
+ * Utility to ready all the lists used by the scheduler.  This is called
+ * automatically upon the creation of the first co-routine.
+ */
+static void prvInitialiseCoRoutineLists( void );
+
+/*
+ * Co-routines that are readied by an interrupt cannot be placed directly into
+ * the ready lists (there is no mutual exclusion).  Instead they are placed in
+ * in the pending ready list in order that they can later be moved to the ready
+ * list by the co-routine scheduler.
+ */
+static void prvCheckPendingReadyList( void );
+
+/*
+ * Macro that looks at the list of co-routines that are currently delayed to
+ * see if any require waking.
+ *
+ * Co-routines are stored in the queue in the order of their wake time -
+ * meaning once one co-routine has been found whose timer has not expired
+ * we need not look any further down the list.
+ */
+static void prvCheckDelayedList( void );
+
+/*-----------------------------------------------------------*/
+
+BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
+{
+BaseType_t xReturn;
+CRCB_t *pxCoRoutine;
+
+	/* Allocate the memory that will store the co-routine control block. */
+	pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
+	if( pxCoRoutine )
+	{
+		/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
+		be created and the co-routine data structures need initialising. */
+		if( pxCurrentCoRoutine == NULL )
+		{
+			pxCurrentCoRoutine = pxCoRoutine;
+			prvInitialiseCoRoutineLists();
+		}
+
+		/* Check the priority is within limits. */
+		if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
+		{
+			uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
+		}
+
+		/* Fill out the co-routine control block from the function parameters. */
+		pxCoRoutine->uxState = corINITIAL_STATE;
+		pxCoRoutine->uxPriority = uxPriority;
+		pxCoRoutine->uxIndex = uxIndex;
+		pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
+
+		/* Initialise all the other co-routine control block parameters. */
+		vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
+		vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
+
+		/* Set the co-routine control block as a link back from the ListItem_t.
+		This is so we can get back to the containing CRCB from a generic item
+		in a list. */
+		listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
+		listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
+
+		/* Event lists are always in priority order. */
+		listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
+
+		/* Now the co-routine has been initialised it can be added to the ready
+		list at the correct priority. */
+		prvAddCoRoutineToReadyQueue( pxCoRoutine );
+
+		xReturn = pdPASS;
+	}
+	else
+	{
+		xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+	}
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
+{
+TickType_t xTimeToWake;
+
+	/* Calculate the time to wake - this may overflow but this is
+	not a problem. */
+	xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
+
+	/* We must remove ourselves from the ready list before adding
+	ourselves to the blocked list as the same list item is used for
+	both lists. */
+	( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+
+	/* The list item will be inserted in wake time order. */
+	listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
+
+	if( xTimeToWake < xCoRoutineTickCount )
+	{
+		/* Wake time has overflowed.  Place this item in the
+		overflow list. */
+		vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+	}
+	else
+	{
+		/* The wake time has not overflowed, so we can use the
+		current block list. */
+		vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+	}
+
+	if( pxEventList )
+	{
+		/* Also add the co-routine to an event list.  If this is done then the
+		function must be called with interrupts disabled. */
+		vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckPendingReadyList( void )
+{
+	/* Are there any co-routines waiting to get moved to the ready list?  These
+	are co-routines that have been readied by an ISR.  The ISR cannot access
+	the	ready lists itself. */
+	while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
+	{
+		CRCB_t *pxUnblockedCRCB;
+
+		/* The pending ready list can be accessed by an ISR. */
+		portDISABLE_INTERRUPTS();
+		{
+			pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
+			( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
+		}
+		portENABLE_INTERRUPTS();
+
+		( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
+		prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckDelayedList( void )
+{
+CRCB_t *pxCRCB;
+
+	xPassedTicks = xTaskGetTickCount() - xLastTickCount;
+	while( xPassedTicks )
+	{
+		xCoRoutineTickCount++;
+		xPassedTicks--;
+
+		/* If the tick count has overflowed we need to swap the ready lists. */
+		if( xCoRoutineTickCount == 0 )
+		{
+			List_t * pxTemp;
+
+			/* Tick count has overflowed so we need to swap the delay lists.  If there are
+			any items in pxDelayedCoRoutineList here then there is an error! */
+			pxTemp = pxDelayedCoRoutineList;
+			pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
+			pxOverflowDelayedCoRoutineList = pxTemp;
+		}
+
+		/* See if this tick has made a timeout expire. */
+		while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
+		{
+			pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
+
+			if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
+			{
+				/* Timeout not yet expired. */
+				break;
+			}
+
+			portDISABLE_INTERRUPTS();
+			{
+				/* The event could have occurred just before this critical
+				section.  If this is the case then the generic list item will
+				have been moved to the pending ready list and the following
+				line is still valid.  Also the pvContainer parameter will have
+				been set to NULL so the following lines are also valid. */
+				( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
+
+				/* Is the co-routine waiting on an event also? */
+				if( pxCRCB->xEventListItem.pvContainer )
+				{
+					( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
+				}
+			}
+			portENABLE_INTERRUPTS();
+
+			prvAddCoRoutineToReadyQueue( pxCRCB );
+		}
+	}
+
+	xLastTickCount = xCoRoutineTickCount;
+}
+/*-----------------------------------------------------------*/
+
+void vCoRoutineSchedule( void )
+{
+	/* See if any co-routines readied by events need moving to the ready lists. */
+	prvCheckPendingReadyList();
+
+	/* See if any delayed co-routines have timed out. */
+	prvCheckDelayedList();
+
+	/* Find the highest priority queue that contains ready co-routines. */
+	while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
+	{
+		if( uxTopCoRoutineReadyPriority == 0 )
+		{
+			/* No more co-routines to check. */
+			return;
+		}
+		--uxTopCoRoutineReadyPriority;
+	}
+
+	/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
+	 of the	same priority get an equal share of the processor time. */
+	listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
+
+	/* Call the co-routine. */
+	( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
+
+	return;
+}
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseCoRoutineLists( void )
+{
+UBaseType_t uxPriority;
+
+	for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
+	{
+		vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
+	}
+
+	vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
+	vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
+	vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
+
+	/* Start with pxDelayedCoRoutineList using list1 and the
+	pxOverflowDelayedCoRoutineList using list2. */
+	pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
+	pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
+{
+CRCB_t *pxUnblockedCRCB;
+BaseType_t xReturn;
+
+	/* This function is called from within an interrupt.  It can only access
+	event lists and the pending ready list.  This function assumes that a
+	check has already been made to ensure pxEventList is not empty. */
+	pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
+	( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
+	vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
+
+	if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
+	{
+		xReturn = pdTRUE;
+	}
+	else
+	{
+		xReturn = pdFALSE;
+	}
+
+	return xReturn;
+}
+
+#endif /* configUSE_CO_ROUTINES == 0 */
+

+ 683 - 0
app/FreeRTOS-8.2.3/event_groups.c

@@ -0,0 +1,683 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/* Standard includes. */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "event_groups.h"
+
+/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
+MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
+header files above, but not in this file, in order to generate the correct
+privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
+
+#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 )
+	#error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available.
+#endif
+
+#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 )
+	#error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available.
+#endif
+
+/* The following bit fields convey control information in a task's event list
+item value.  It is important they don't clash with the
+taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
+#if configUSE_16_BIT_TICKS == 1
+	#define eventCLEAR_EVENTS_ON_EXIT_BIT	0x0100U
+	#define eventUNBLOCKED_DUE_TO_BIT_SET	0x0200U
+	#define eventWAIT_FOR_ALL_BITS			0x0400U
+	#define eventEVENT_BITS_CONTROL_BYTES	0xff00U
+#else
+	#define eventCLEAR_EVENTS_ON_EXIT_BIT	0x01000000UL
+	#define eventUNBLOCKED_DUE_TO_BIT_SET	0x02000000UL
+	#define eventWAIT_FOR_ALL_BITS			0x04000000UL
+	#define eventEVENT_BITS_CONTROL_BYTES	0xff000000UL
+#endif
+
+typedef struct xEventGroupDefinition
+{
+	EventBits_t uxEventBits;
+	List_t xTasksWaitingForBits;		/*< List of tasks waiting for a bit to be set. */
+
+	#if( configUSE_TRACE_FACILITY == 1 )
+		UBaseType_t uxEventGroupNumber;
+	#endif
+
+} EventGroup_t;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
+ * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is
+ * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
+ * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the
+ * wait condition is met if any of the bits set in uxBitsToWait for are also set
+ * in uxCurrentEventBits.
+ */
+static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits );
+
+/*-----------------------------------------------------------*/
+
+EventGroupHandle_t xEventGroupCreate( void )
+{
+EventGroup_t *pxEventBits;
+
+	pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
+	if( pxEventBits != NULL )
+	{
+		pxEventBits->uxEventBits = 0;
+		vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
+		traceEVENT_GROUP_CREATE( pxEventBits );
+	}
+	else
+	{
+		traceEVENT_GROUP_CREATE_FAILED();
+	}
+
+	return ( EventGroupHandle_t ) pxEventBits;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
+{
+EventBits_t uxOriginalBitValue, uxReturn;
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+BaseType_t xAlreadyYielded;
+BaseType_t xTimeoutOccurred = pdFALSE;
+
+	configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+	configASSERT( uxBitsToWaitFor != 0 );
+	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+	{
+		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+	}
+	#endif
+
+	vTaskSuspendAll();
+	{
+		uxOriginalBitValue = pxEventBits->uxEventBits;
+
+		( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
+
+		if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
+		{
+			/* All the rendezvous bits are now set - no need to block. */
+			uxReturn = ( uxOriginalBitValue | uxBitsToSet );
+
+			/* Rendezvous always clear the bits.  They will have been cleared
+			already unless this is the only task in the rendezvous. */
+			pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+
+			xTicksToWait = 0;
+		}
+		else
+		{
+			if( xTicksToWait != ( TickType_t ) 0 )
+			{
+				traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
+
+				/* Store the bits that the calling task is waiting for in the
+				task's event list item so the kernel knows when a match is
+				found.  Then enter the blocked state. */
+				vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
+
+				/* This assignment is obsolete as uxReturn will get set after
+				the task unblocks, but some compilers mistakenly generate a
+				warning about uxReturn being returned without being set if the
+				assignment is omitted. */
+				uxReturn = 0;
+			}
+			else
+			{
+				/* The rendezvous bits were not set, but no block time was
+				specified - just return the current event bit value. */
+				uxReturn = pxEventBits->uxEventBits;
+			}
+		}
+	}
+	xAlreadyYielded = xTaskResumeAll();
+
+	if( xTicksToWait != ( TickType_t ) 0 )
+	{
+		if( xAlreadyYielded == pdFALSE )
+		{
+			portYIELD_WITHIN_API();
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+
+		/* The task blocked to wait for its required bits to be set - at this
+		point either the required bits were set or the block time expired.  If
+		the required bits were set they will have been stored in the task's
+		event list item, and they should now be retrieved then cleared. */
+		uxReturn = uxTaskResetEventItemValue();
+
+		if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
+		{
+			/* The task timed out, just return the current event bit value. */
+			taskENTER_CRITICAL();
+			{
+				uxReturn = pxEventBits->uxEventBits;
+
+				/* Although the task got here because it timed out before the
+				bits it was waiting for were set, it is possible that since it
+				unblocked another task has set the bits.  If this is the case
+				then it needs to clear the bits before exiting. */
+				if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
+				{
+					pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			taskEXIT_CRITICAL();
+
+			xTimeoutOccurred = pdTRUE;
+		}
+		else
+		{
+			/* The task unblocked because the bits were set. */
+		}
+
+		/* Control bits might be set as the task had blocked should not be
+		returned. */
+		uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
+	}
+
+	traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
+{
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+EventBits_t uxReturn, uxControlBits = 0;
+BaseType_t xWaitConditionMet, xAlreadyYielded;
+BaseType_t xTimeoutOccurred = pdFALSE;
+
+	/* Check the user is not attempting to wait on the bits used by the kernel
+	itself, and that at least one bit is being requested. */
+	configASSERT( xEventGroup );
+	configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+	configASSERT( uxBitsToWaitFor != 0 );
+	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+	{
+		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+	}
+	#endif
+
+	vTaskSuspendAll();
+	{
+		const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
+
+		/* Check to see if the wait condition is already met or not. */
+		xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
+
+		if( xWaitConditionMet != pdFALSE )
+		{
+			/* The wait condition has already been met so there is no need to
+			block. */
+			uxReturn = uxCurrentEventBits;
+			xTicksToWait = ( TickType_t ) 0;
+
+			/* Clear the wait bits if requested to do so. */
+			if( xClearOnExit != pdFALSE )
+			{
+				pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else if( xTicksToWait == ( TickType_t ) 0 )
+		{
+			/* The wait condition has not been met, but no block time was
+			specified, so just return the current value. */
+			uxReturn = uxCurrentEventBits;
+		}
+		else
+		{
+			/* The task is going to block to wait for its required bits to be
+			set.  uxControlBits are used to remember the specified behaviour of
+			this call to xEventGroupWaitBits() - for use when the event bits
+			unblock the task. */
+			if( xClearOnExit != pdFALSE )
+			{
+				uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+
+			if( xWaitForAllBits != pdFALSE )
+			{
+				uxControlBits |= eventWAIT_FOR_ALL_BITS;
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+
+			/* Store the bits that the calling task is waiting for in the
+			task's event list item so the kernel knows when a match is
+			found.  Then enter the blocked state. */
+			vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
+
+			/* This is obsolete as it will get set after the task unblocks, but
+			some compilers mistakenly generate a warning about the variable
+			being returned without being set if it is not done. */
+			uxReturn = 0;
+
+			traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
+		}
+	}
+	xAlreadyYielded = xTaskResumeAll();
+
+	if( xTicksToWait != ( TickType_t ) 0 )
+	{
+		if( xAlreadyYielded == pdFALSE )
+		{
+			portYIELD_WITHIN_API();
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+
+		/* The task blocked to wait for its required bits to be set - at this
+		point either the required bits were set or the block time expired.  If
+		the required bits were set they will have been stored in the task's
+		event list item, and they should now be retrieved then cleared. */
+		uxReturn = uxTaskResetEventItemValue();
+
+		if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
+		{
+			taskENTER_CRITICAL();
+			{
+				/* The task timed out, just return the current event bit value. */
+				uxReturn = pxEventBits->uxEventBits;
+
+				/* It is possible that the event bits were updated between this
+				task leaving the Blocked state and running again. */
+				if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
+				{
+					if( xClearOnExit != pdFALSE )
+					{
+						pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			taskEXIT_CRITICAL();
+
+			/* Prevent compiler warnings when trace macros are not used. */
+			xTimeoutOccurred = pdFALSE;
+		}
+		else
+		{
+			/* The task unblocked because the bits were set. */
+		}
+
+		/* The task blocked so control bits may have been set. */
+		uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
+	}
+	traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
+{
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+EventBits_t uxReturn;
+
+	/* Check the user is not attempting to clear the bits used by the kernel
+	itself. */
+	configASSERT( xEventGroup );
+	configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+
+	taskENTER_CRITICAL();
+	{
+		traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
+
+		/* The value returned is the event group value prior to the bits being
+		cleared. */
+		uxReturn = pxEventBits->uxEventBits;
+
+		/* Clear the bits. */
+		pxEventBits->uxEventBits &= ~uxBitsToClear;
+	}
+	taskEXIT_CRITICAL();
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
+	{
+		BaseType_t xReturn;
+
+		traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
+		xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
+
+		return xReturn;
+	}
+
+#endif
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
+{
+UBaseType_t uxSavedInterruptStatus;
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+EventBits_t uxReturn;
+
+	uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		uxReturn = pxEventBits->uxEventBits;
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
+{
+ListItem_t *pxListItem, *pxNext;
+ListItem_t const *pxListEnd;
+List_t *pxList;
+EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+BaseType_t xMatchFound = pdFALSE;
+
+	/* Check the user is not attempting to set the bits used by the kernel
+	itself. */
+	configASSERT( xEventGroup );
+	configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+
+	pxList = &( pxEventBits->xTasksWaitingForBits );
+	pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
+	vTaskSuspendAll();
+	{
+		traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
+
+		pxListItem = listGET_HEAD_ENTRY( pxList );
+
+		/* Set the bits. */
+		pxEventBits->uxEventBits |= uxBitsToSet;
+
+		/* See if the new bit value should unblock any tasks. */
+		while( pxListItem != pxListEnd )
+		{
+			pxNext = listGET_NEXT( pxListItem );
+			uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
+			xMatchFound = pdFALSE;
+
+			/* Split the bits waited for from the control bits. */
+			uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
+			uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
+
+			if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
+			{
+				/* Just looking for single bit being set. */
+				if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
+				{
+					xMatchFound = pdTRUE;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
+			{
+				/* All bits are set. */
+				xMatchFound = pdTRUE;
+			}
+			else
+			{
+				/* Need all bits to be set, but not all the bits were set. */
+			}
+
+			if( xMatchFound != pdFALSE )
+			{
+				/* The bits match.  Should the bits be cleared on exit? */
+				if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
+				{
+					uxBitsToClear |= uxBitsWaitedFor;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+
+				/* Store the actual event flag value in the task's event list
+				item before removing the task from the event list.  The
+				eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
+				that is was unblocked due to its required bits matching, rather
+				than because it timed out. */
+				( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
+			}
+
+			/* Move onto the next list item.  Note pxListItem->pxNext is not
+			used here as the list item may have been removed from the event list
+			and inserted into the ready/pending reading list. */
+			pxListItem = pxNext;
+		}
+
+		/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
+		bit was set in the control word. */
+		pxEventBits->uxEventBits &= ~uxBitsToClear;
+	}
+	( void ) xTaskResumeAll();
+
+	return pxEventBits->uxEventBits;
+}
+/*-----------------------------------------------------------*/
+
+void vEventGroupDelete( EventGroupHandle_t xEventGroup )
+{
+EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
+
+	vTaskSuspendAll();
+	{
+		traceEVENT_GROUP_DELETE( xEventGroup );
+
+		while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
+		{
+			/* Unblock the task, returning 0 as the event list is being deleted
+			and	cannot therefore have any bits set. */
+			configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
+			( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
+		}
+
+		vPortFree( pxEventBits );
+	}
+	( void ) xTaskResumeAll();
+}
+/*-----------------------------------------------------------*/
+
+/* For internal use only - execute a 'set bits' command that was pended from
+an interrupt. */
+void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
+{
+	( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
+}
+/*-----------------------------------------------------------*/
+
+/* For internal use only - execute a 'clear bits' command that was pended from
+an interrupt. */
+void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
+{
+	( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
+{
+BaseType_t xWaitConditionMet = pdFALSE;
+
+	if( xWaitForAllBits == pdFALSE )
+	{
+		/* Task only has to wait for one bit within uxBitsToWaitFor to be
+		set.  Is one already set? */
+		if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
+		{
+			xWaitConditionMet = pdTRUE;
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	else
+	{
+		/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
+		Are they set already? */
+		if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
+		{
+			xWaitConditionMet = pdTRUE;
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+
+	return xWaitConditionMet;
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
+	{
+	BaseType_t xReturn;
+
+		traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
+		xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
+
+		return xReturn;
+	}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if (configUSE_TRACE_FACILITY == 1)
+
+	UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
+	{
+	UBaseType_t xReturn;
+	EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
+
+		if( xEventGroup == NULL )
+		{
+			xReturn = 0;
+		}
+		else
+		{
+			xReturn = pxEventBits->uxEventGroupNumber;
+		}
+
+		return xReturn;
+	}
+
+#endif
+

+ 835 - 0
app/FreeRTOS-8.2.3/include/FreeRTOS.h

@@ -0,0 +1,835 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef INC_FREERTOS_H
+#define INC_FREERTOS_H
+
+/*
+ * Include the generic headers required for the FreeRTOS port being used.
+ */
+#include <stddef.h>
+
+/*
+ * If stdint.h cannot be located then:
+ *   + If using GCC ensure the -nostdint options is *not* being used.
+ *   + Ensure the project's include path includes the directory in which your
+ *     compiler stores stdint.h.
+ *   + Set any compiler options necessary for it to support C99, as technically
+ *     stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any
+ *     other way).
+ *   + The FreeRTOS download includes a simple stdint.h definition that can be
+ *     used in cases where none is provided by the compiler.  The files only
+ *     contains the typedefs required to build FreeRTOS.  Read the instructions
+ *     in FreeRTOS/source/stdint.readme for more information.
+ */
+#include <stdint.h> /* READ COMMENT ABOVE. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Application specific configuration options. */
+#include "FreeRTOSConfig.h"
+
+/* Basic FreeRTOS definitions. */
+#include "projdefs.h"
+
+/* Definitions specific to the port being used. */
+#include "portable.h"
+
+/*
+ * Check all the required application specific macros have been defined.
+ * These macros are application specific and (as downloaded) are defined
+ * within FreeRTOSConfig.h.
+ */
+
+#ifndef configMINIMAL_STACK_SIZE
+	#error Missing definition:  configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h.  configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task.  Refer to the demo project provided for your port for a suitable value.
+#endif
+
+#ifndef configMAX_PRIORITIES
+	#error Missing definition:  configMAX_PRIORITIES must be defined in FreeRTOSConfig.h.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_PREEMPTION
+	#error Missing definition:  configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_IDLE_HOOK
+	#error Missing definition:  configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_TICK_HOOK
+	#error Missing definition:  configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskPrioritySet
+	#error Missing definition:  INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_uxTaskPriorityGet
+	#error Missing definition:  INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelete
+	#error Missing definition:  INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskSuspend
+	#error Missing definition:  INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelayUntil
+	#error Missing definition:  INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelay
+	#error Missing definition:  INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_16_BIT_TICKS
+	#error Missing definition:  configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configMAX_PRIORITIES
+	#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
+#endif
+
+#ifndef configUSE_CO_ROUTINES
+	#define configUSE_CO_ROUTINES 0
+#endif
+
+#if configUSE_CO_ROUTINES != 0
+	#ifndef configMAX_CO_ROUTINE_PRIORITIES
+		#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
+	#endif
+#endif
+
+#ifndef INCLUDE_xTaskGetIdleTaskHandle
+	#define INCLUDE_xTaskGetIdleTaskHandle 0
+#endif
+
+#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
+	#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#endif
+
+#ifndef INCLUDE_xQueueGetMutexHolder
+	#define INCLUDE_xQueueGetMutexHolder 0
+#endif
+
+#ifndef INCLUDE_xSemaphoreGetMutexHolder
+	#define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
+#endif
+
+#ifndef INCLUDE_pcTaskGetTaskName
+	#define INCLUDE_pcTaskGetTaskName 1
+#endif
+
+#ifndef configUSE_APPLICATION_TASK_TAG
+	#define configUSE_APPLICATION_TASK_TAG 0
+#endif
+
+#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
+	#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
+#endif
+
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark
+	#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#endif
+
+#ifndef INCLUDE_eTaskGetState
+	#define INCLUDE_eTaskGetState 0
+#endif
+
+#ifndef configUSE_RECURSIVE_MUTEXES
+	#define configUSE_RECURSIVE_MUTEXES 0
+#endif
+
+#ifndef configUSE_MUTEXES
+	#define configUSE_MUTEXES 0
+#endif
+
+#ifndef configUSE_TIMERS
+	#define configUSE_TIMERS 0
+#endif
+
+#ifndef configUSE_COUNTING_SEMAPHORES
+	#define configUSE_COUNTING_SEMAPHORES 0
+#endif
+
+#ifndef configUSE_ALTERNATIVE_API
+	#define configUSE_ALTERNATIVE_API 0
+#endif
+
+#ifndef portCRITICAL_NESTING_IN_TCB
+	#define portCRITICAL_NESTING_IN_TCB 0
+#endif
+
+#ifndef configMAX_TASK_NAME_LEN
+	#define configMAX_TASK_NAME_LEN 16
+#endif
+
+#ifndef configIDLE_SHOULD_YIELD
+	#define configIDLE_SHOULD_YIELD		1
+#endif
+
+#if configMAX_TASK_NAME_LEN < 1
+	#error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
+#endif
+
+#ifndef INCLUDE_xTaskResumeFromISR
+	#define INCLUDE_xTaskResumeFromISR 1
+#endif
+
+#ifndef INCLUDE_xEventGroupSetBitFromISR
+	#define INCLUDE_xEventGroupSetBitFromISR 0
+#endif
+
+#ifndef INCLUDE_xTimerPendFunctionCall
+	#define INCLUDE_xTimerPendFunctionCall 0
+#endif
+
+#ifndef configASSERT
+	#define configASSERT( x )
+	#define configASSERT_DEFINED 0
+#else
+	#define configASSERT_DEFINED 1
+#endif
+
+/* The timers module relies on xTaskGetSchedulerState(). */
+#if configUSE_TIMERS == 1
+
+	#ifndef configTIMER_TASK_PRIORITY
+		#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined.
+	#endif /* configTIMER_TASK_PRIORITY */
+
+	#ifndef configTIMER_QUEUE_LENGTH
+		#error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined.
+	#endif /* configTIMER_QUEUE_LENGTH */
+
+	#ifndef configTIMER_TASK_STACK_DEPTH
+		#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined.
+	#endif /* configTIMER_TASK_STACK_DEPTH */
+
+#endif /* configUSE_TIMERS */
+
+#ifndef INCLUDE_xTaskGetSchedulerState
+	#define INCLUDE_xTaskGetSchedulerState 0
+#endif
+
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+	#define INCLUDE_xTaskGetCurrentTaskHandle 0
+#endif
+
+
+#ifndef portSET_INTERRUPT_MASK_FROM_ISR
+	#define portSET_INTERRUPT_MASK_FROM_ISR() 0
+#endif
+
+#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR
+	#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
+#endif
+
+#ifndef portCLEAN_UP_TCB
+	#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
+#endif
+
+#ifndef portPRE_TASK_DELETE_HOOK
+	#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
+#endif
+
+#ifndef portSETUP_TCB
+	#define portSETUP_TCB( pxTCB ) ( void ) pxTCB
+#endif
+
+#ifndef configQUEUE_REGISTRY_SIZE
+	#define configQUEUE_REGISTRY_SIZE 0U
+#endif
+
+#if ( configQUEUE_REGISTRY_SIZE < 1 )
+	#define vQueueAddToRegistry( xQueue, pcName )
+	#define vQueueUnregisterQueue( xQueue )
+#endif
+
+#ifndef portPOINTER_SIZE_TYPE
+	#define portPOINTER_SIZE_TYPE uint32_t
+#endif
+
+/* Remove any unused trace macros. */
+#ifndef traceSTART
+	/* Used to perform any necessary initialisation - for example, open a file
+	into which trace is to be written. */
+	#define traceSTART()
+#endif
+
+#ifndef traceEND
+	/* Use to close a trace, for example close a file into which trace has been
+	written. */
+	#define traceEND()
+#endif
+
+#ifndef traceTASK_SWITCHED_IN
+	/* Called after a task has been selected to run.  pxCurrentTCB holds a pointer
+	to the task control block of the selected task. */
+	#define traceTASK_SWITCHED_IN()
+#endif
+
+#ifndef traceINCREASE_TICK_COUNT
+	/* Called before stepping the tick count after waking from tickless idle
+	sleep. */
+	#define traceINCREASE_TICK_COUNT( x )
+#endif
+
+#ifndef traceLOW_POWER_IDLE_BEGIN
+	/* Called immediately before entering tickless idle. */
+	#define traceLOW_POWER_IDLE_BEGIN()
+#endif
+
+#ifndef	traceLOW_POWER_IDLE_END
+	/* Called when returning to the Idle task after a tickless idle. */
+	#define traceLOW_POWER_IDLE_END()
+#endif
+
+#ifndef traceTASK_SWITCHED_OUT
+	/* Called before a task has been selected to run.  pxCurrentTCB holds a pointer
+	to the task control block of the task being switched out. */
+	#define traceTASK_SWITCHED_OUT()
+#endif
+
+#ifndef traceTASK_PRIORITY_INHERIT
+	/* Called when a task attempts to take a mutex that is already held by a
+	lower priority task.  pxTCBOfMutexHolder is a pointer to the TCB of the task
+	that holds the mutex.  uxInheritedPriority is the priority the mutex holder
+	will inherit (the priority of the task that is attempting to obtain the
+	muted. */
+	#define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority )
+#endif
+
+#ifndef traceTASK_PRIORITY_DISINHERIT
+	/* Called when a task releases a mutex, the holding of which had resulted in
+	the task inheriting the priority of a higher priority task.
+	pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the
+	mutex.  uxOriginalPriority is the task's configured (base) priority. */
+	#define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_RECEIVE
+	/* Task is about to block because it cannot read from a
+	queue/mutex/semaphore.  pxQueue is a pointer to the queue/mutex/semaphore
+	upon which the read was attempted.  pxCurrentTCB points to the TCB of the
+	task that attempted the read. */
+	#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_SEND
+	/* Task is about to block because it cannot write to a
+	queue/mutex/semaphore.  pxQueue is a pointer to the queue/mutex/semaphore
+	upon which the write was attempted.  pxCurrentTCB points to the TCB of the
+	task that attempted the write. */
+	#define traceBLOCKING_ON_QUEUE_SEND( pxQueue )
+#endif
+
+#ifndef configCHECK_FOR_STACK_OVERFLOW
+	#define configCHECK_FOR_STACK_OVERFLOW 0
+#endif
+
+/* The following event macros are embedded in the kernel API calls. */
+
+#ifndef traceMOVED_TASK_TO_READY_STATE
+	#define traceMOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
+#ifndef traceQUEUE_CREATE
+	#define traceQUEUE_CREATE( pxNewQueue )
+#endif
+
+#ifndef traceQUEUE_CREATE_FAILED
+	#define traceQUEUE_CREATE_FAILED( ucQueueType )
+#endif
+
+#ifndef traceCREATE_MUTEX
+	#define traceCREATE_MUTEX( pxNewQueue )
+#endif
+
+#ifndef traceCREATE_MUTEX_FAILED
+	#define traceCREATE_MUTEX_FAILED()
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE
+	#define traceGIVE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED
+	#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE
+	#define traceTAKE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED
+	#define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE
+	#define traceCREATE_COUNTING_SEMAPHORE()
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED
+	#define traceCREATE_COUNTING_SEMAPHORE_FAILED()
+#endif
+
+#ifndef traceQUEUE_SEND
+	#define traceQUEUE_SEND( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FAILED
+	#define traceQUEUE_SEND_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE
+	#define traceQUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK
+	#define traceQUEUE_PEEK( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR
+	#define traceQUEUE_PEEK_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FAILED
+	#define traceQUEUE_RECEIVE_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR
+	#define traceQUEUE_SEND_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR_FAILED
+	#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR
+	#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED
+	#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED
+	#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_DELETE
+	#define traceQUEUE_DELETE( pxQueue )
+#endif
+
+#ifndef traceTASK_CREATE
+	#define traceTASK_CREATE( pxNewTCB )
+#endif
+
+#ifndef traceTASK_CREATE_FAILED
+	#define traceTASK_CREATE_FAILED()
+#endif
+
+#ifndef traceTASK_DELETE
+	#define traceTASK_DELETE( pxTaskToDelete )
+#endif
+
+#ifndef traceTASK_DELAY_UNTIL
+	#define traceTASK_DELAY_UNTIL()
+#endif
+
+#ifndef traceTASK_DELAY
+	#define traceTASK_DELAY()
+#endif
+
+#ifndef traceTASK_PRIORITY_SET
+	#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority )
+#endif
+
+#ifndef traceTASK_SUSPEND
+	#define traceTASK_SUSPEND( pxTaskToSuspend )
+#endif
+
+#ifndef traceTASK_RESUME
+	#define traceTASK_RESUME( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_RESUME_FROM_ISR
+	#define traceTASK_RESUME_FROM_ISR( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_INCREMENT_TICK
+	#define traceTASK_INCREMENT_TICK( xTickCount )
+#endif
+
+#ifndef traceTIMER_CREATE
+	#define traceTIMER_CREATE( pxNewTimer )
+#endif
+
+#ifndef traceTIMER_CREATE_FAILED
+	#define traceTIMER_CREATE_FAILED()
+#endif
+
+#ifndef traceTIMER_COMMAND_SEND
+	#define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn )
+#endif
+
+#ifndef traceTIMER_EXPIRED
+	#define traceTIMER_EXPIRED( pxTimer )
+#endif
+
+#ifndef traceTIMER_COMMAND_RECEIVED
+	#define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue )
+#endif
+
+#ifndef traceMALLOC
+    #define traceMALLOC( pvAddress, uiSize )
+#endif
+
+#ifndef traceFREE
+    #define traceFREE( pvAddress, uiSize )
+#endif
+
+#ifndef traceEVENT_GROUP_CREATE
+	#define traceEVENT_GROUP_CREATE( xEventGroup )
+#endif
+
+#ifndef traceEVENT_GROUP_CREATE_FAILED
+	#define traceEVENT_GROUP_CREATE_FAILED()
+#endif
+
+#ifndef traceEVENT_GROUP_SYNC_BLOCK
+	#define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor )
+#endif
+
+#ifndef traceEVENT_GROUP_SYNC_END
+	#define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
+#endif
+
+#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK
+	#define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor )
+#endif
+
+#ifndef traceEVENT_GROUP_WAIT_BITS_END
+	#define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
+#endif
+
+#ifndef traceEVENT_GROUP_CLEAR_BITS
+	#define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )
+#endif
+
+#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
+	#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear )
+#endif
+
+#ifndef traceEVENT_GROUP_SET_BITS
+	#define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )
+#endif
+
+#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR
+	#define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet )
+#endif
+
+#ifndef traceEVENT_GROUP_DELETE
+	#define traceEVENT_GROUP_DELETE( xEventGroup )
+#endif
+
+#ifndef tracePEND_FUNC_CALL
+	#define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret)
+#endif
+
+#ifndef tracePEND_FUNC_CALL_FROM_ISR
+	#define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret)
+#endif
+
+#ifndef traceQUEUE_REGISTRY_ADD
+	#define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName)
+#endif
+
+#ifndef traceTASK_NOTIFY_TAKE_BLOCK
+	#define traceTASK_NOTIFY_TAKE_BLOCK()
+#endif
+
+#ifndef traceTASK_NOTIFY_TAKE
+	#define traceTASK_NOTIFY_TAKE()
+#endif
+
+#ifndef traceTASK_NOTIFY_WAIT_BLOCK
+	#define traceTASK_NOTIFY_WAIT_BLOCK()
+#endif
+
+#ifndef traceTASK_NOTIFY_WAIT
+	#define traceTASK_NOTIFY_WAIT()
+#endif
+
+#ifndef traceTASK_NOTIFY
+	#define traceTASK_NOTIFY()
+#endif
+
+#ifndef traceTASK_NOTIFY_FROM_ISR
+	#define traceTASK_NOTIFY_FROM_ISR()
+#endif
+
+#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR
+	#define traceTASK_NOTIFY_GIVE_FROM_ISR()
+#endif
+
+#ifndef configGENERATE_RUN_TIME_STATS
+	#define configGENERATE_RUN_TIME_STATS 0
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+	#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+		#error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined.  portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
+	#endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */
+
+	#ifndef portGET_RUN_TIME_COUNTER_VALUE
+		#ifndef portALT_GET_RUN_TIME_COUNTER_VALUE
+			#error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined.  See the examples provided and the FreeRTOS web site for more information.
+		#endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */
+	#endif /* portGET_RUN_TIME_COUNTER_VALUE */
+
+#endif /* configGENERATE_RUN_TIME_STATS */
+
+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+	#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#endif
+
+#ifndef configUSE_MALLOC_FAILED_HOOK
+	#define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+
+#ifndef portPRIVILEGE_BIT
+	#define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 )
+#endif
+
+#ifndef portYIELD_WITHIN_API
+	#define portYIELD_WITHIN_API portYIELD
+#endif
+
+#ifndef pvPortMallocAligned
+	#define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) )
+#endif
+
+#ifndef vPortFreeAligned
+	#define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
+#endif
+
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
+#endif
+
+#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
+	#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
+#endif
+
+#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2
+	#error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2
+#endif
+
+#ifndef configUSE_TICKLESS_IDLE
+	#define configUSE_TICKLESS_IDLE 0
+#endif
+
+#ifndef configPRE_SLEEP_PROCESSING
+	#define configPRE_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configPOST_SLEEP_PROCESSING
+	#define configPOST_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configUSE_QUEUE_SETS
+	#define configUSE_QUEUE_SETS 0
+#endif
+
+#ifndef portTASK_USES_FLOATING_POINT
+	#define portTASK_USES_FLOATING_POINT()
+#endif
+
+#ifndef configUSE_TIME_SLICING
+	#define configUSE_TIME_SLICING 1
+#endif
+
+#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS
+	#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
+#endif
+
+#ifndef configUSE_NEWLIB_REENTRANT
+	#define configUSE_NEWLIB_REENTRANT 0
+#endif
+
+#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
+	#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+#endif
+
+#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID
+	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
+#ifndef configUSE_TRACE_FACILITY
+	#define configUSE_TRACE_FACILITY 0
+#endif
+
+#ifndef mtCOVERAGE_TEST_MARKER
+	#define mtCOVERAGE_TEST_MARKER()
+#endif
+
+#ifndef mtCOVERAGE_TEST_DELAY
+	#define mtCOVERAGE_TEST_DELAY()
+#endif
+
+#ifndef portASSERT_IF_IN_ISR
+	#define portASSERT_IF_IN_ISR()
+#endif
+
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#endif
+
+#ifndef configAPPLICATION_ALLOCATED_HEAP
+	#define configAPPLICATION_ALLOCATED_HEAP 0
+#endif
+
+#ifndef configUSE_TASK_NOTIFICATIONS
+	#define configUSE_TASK_NOTIFICATIONS 1
+#endif
+
+#ifndef portTICK_TYPE_IS_ATOMIC
+	#define portTICK_TYPE_IS_ATOMIC 0
+#endif
+
+#if( portTICK_TYPE_IS_ATOMIC == 0 )
+	/* Either variables of tick type cannot be read atomically, or
+	portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
+	the tick count is returned to the standard critical section macros. */
+	#define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL()
+	#define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL()
+	#define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
+	#define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) )
+#else
+	/* The tick type can be read atomically, so critical sections used when the
+	tick count is returned can be defined away. */
+	#define portTICK_TYPE_ENTER_CRITICAL()
+	#define portTICK_TYPE_EXIT_CRITICAL()
+	#define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0
+	#define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x
+#endif
+
+/* Definitions to allow backward compatibility with FreeRTOS versions prior to
+V8 if desired. */
+#ifndef configENABLE_BACKWARD_COMPATIBILITY
+	#define configENABLE_BACKWARD_COMPATIBILITY 1
+#endif
+
+#if configENABLE_BACKWARD_COMPATIBILITY == 1
+	#define eTaskStateGet eTaskGetState
+	#define portTickType TickType_t
+	#define xTaskHandle TaskHandle_t
+	#define xQueueHandle QueueHandle_t
+	#define xSemaphoreHandle SemaphoreHandle_t
+	#define xQueueSetHandle QueueSetHandle_t
+	#define xQueueSetMemberHandle QueueSetMemberHandle_t
+	#define xTimeOutType TimeOut_t
+	#define xMemoryRegion MemoryRegion_t
+	#define xTaskParameters TaskParameters_t
+	#define xTaskStatusType	TaskStatus_t
+	#define xTimerHandle TimerHandle_t
+	#define xCoRoutineHandle CoRoutineHandle_t
+	#define pdTASK_HOOK_CODE TaskHookFunction_t
+	#define portTICK_RATE_MS portTICK_PERIOD_MS
+
+	/* Backward compatibility within the scheduler code only - these definitions
+	are not really required but are included for completeness. */
+	#define tmrTIMER_CALLBACK TimerCallbackFunction_t
+	#define pdTASK_CODE TaskFunction_t
+	#define xListItem ListItem_t
+	#define xList List_t
+#endif /* configENABLE_BACKWARD_COMPATIBILITY */
+
+/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even
+if floating point hardware is otherwise supported by the FreeRTOS port in use.
+This constant is not supported by all FreeRTOS ports that include floating 
+point support. */
+#ifndef configUSE_TASK_FPU_SUPPORT
+	#define configUSE_TASK_FPU_SUPPORT 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INC_FREERTOS_H */
+

+ 171 - 0
app/FreeRTOS-8.2.3/include/StackMacros.h

@@ -0,0 +1,171 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef STACK_MACROS_H
+#define STACK_MACROS_H
+
+/*
+ * Call the stack overflow hook function if the stack of the task being swapped
+ * out is currently overflowed, or looks like it might have overflowed in the
+ * past.
+ *
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
+ * the current stack state only - comparing the current top of stack value to
+ * the stack limit.  Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
+ * will also cause the last few stack bytes to be checked to ensure the value
+ * to which the bytes were set when the task was created have not been
+ * overwritten.  Note this second test does not guarantee that an overflowed
+ * stack will always be recognised.
+ */
+
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+	/* Only the current stack state is to be checked. */
+	#define taskCHECK_FOR_STACK_OVERFLOW()																\
+	{																									\
+		/* Is the currently saved stack pointer within the stack limit? */								\
+		if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack )										\
+		{																								\
+			vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName );	\
+		}																								\
+	}
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+	/* Only the current stack state is to be checked. */
+	#define taskCHECK_FOR_STACK_OVERFLOW()																\
+	{																									\
+																										\
+		/* Is the currently saved stack pointer within the stack limit? */								\
+		if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack )									\
+		{																								\
+			vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName );	\
+		}																								\
+	}
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+	#define taskCHECK_FOR_STACK_OVERFLOW()																\
+	{																									\
+		const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack;							\
+		const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5;											\
+																										\
+		if( ( pulStack[ 0 ] != ulCheckValue ) ||												\
+			( pulStack[ 1 ] != ulCheckValue ) ||												\
+			( pulStack[ 2 ] != ulCheckValue ) ||												\
+			( pulStack[ 3 ] != ulCheckValue ) )												\
+		{																								\
+			vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName );	\
+		}																								\
+	}
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+	#define taskCHECK_FOR_STACK_OVERFLOW()																								\
+	{																																	\
+	int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack;																		\
+	static const uint8_t ucExpectedStackBytes[] = {	tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+													tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+													tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+													tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+													tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE };	\
+																																		\
+																																		\
+		pcEndOfStack -= sizeof( ucExpectedStackBytes );																					\
+																																		\
+		/* Has the extremity of the task stack ever been written over? */																\
+		if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 )					\
+		{																																\
+			vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName );									\
+		}																																\
+	}
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+/* Remove stack overflow macro if not being used. */
+#ifndef taskCHECK_FOR_STACK_OVERFLOW
+	#define taskCHECK_FOR_STACK_OVERFLOW()
+#endif
+
+
+
+#endif /* STACK_MACROS_H */
+

+ 762 - 0
app/FreeRTOS-8.2.3/include/croutine.h

@@ -0,0 +1,762 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef CO_ROUTINE_H
+#define CO_ROUTINE_H
+
+#ifndef INC_FREERTOS_H
+	#error "include FreeRTOS.h must appear in source files before include croutine.h"
+#endif
+
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Used to hide the implementation of the co-routine control block.  The
+control block structure however has to be included in the header due to
+the macro implementation of the co-routine functionality. */
+typedef void * CoRoutineHandle_t;
+
+/* Defines the prototype to which co-routine functions must conform. */
+typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
+
+typedef struct corCoRoutineControlBlock
+{
+	crCOROUTINE_CODE 	pxCoRoutineFunction;
+	ListItem_t			xGenericListItem;	/*< List item used to place the CRCB in ready and blocked queues. */
+	ListItem_t			xEventListItem;		/*< List item used to place the CRCB in event lists. */
+	UBaseType_t 		uxPriority;			/*< The priority of the co-routine in relation to other co-routines. */
+	UBaseType_t 		uxIndex;			/*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
+	uint16_t 			uxState;			/*< Used internally by the co-routine implementation. */
+} CRCB_t; /* Co-routine control block.  Note must be identical in size down to uxPriority with TCB_t. */
+
+/**
+ * croutine. h
+ *<pre>
+ BaseType_t xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 UBaseType_t uxPriority,
+                                 UBaseType_t uxIndex
+                               );</pre>
+ *
+ * Create a new co-routine and add it to the list of co-routines that are
+ * ready to run.
+ *
+ * @param pxCoRoutineCode Pointer to the co-routine function.  Co-routine
+ * functions require special syntax - see the co-routine section of the WEB
+ * documentation for more information.
+ *
+ * @param uxPriority The priority with respect to other co-routines at which
+ *  the co-routine will run.
+ *
+ * @param uxIndex Used to distinguish between different co-routines that
+ * execute the same function.  See the example below and the co-routine section
+ * of the WEB documentation for further information.
+ *
+ * @return pdPASS if the co-routine was successfully created and added to a ready
+ * list, otherwise an error code defined with ProjDefs.h.
+ *
+ * Example usage:
+   <pre>
+ // Co-routine to be created.
+ void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how int32_t to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ uint8_t ucParameterToPass;
+ TaskHandle_t xHandle;
+
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   </pre>
+ * \defgroup xCoRoutineCreate xCoRoutineCreate
+ * \ingroup Tasks
+ */
+BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
+
+
+/**
+ * croutine. h
+ *<pre>
+ void vCoRoutineSchedule( void );</pre>
+ *
+ * Run a co-routine.
+ *
+ * vCoRoutineSchedule() executes the highest priority co-routine that is able
+ * to run.  The co-routine will execute until it either blocks, yields or is
+ * preempted by a task.  Co-routines execute cooperatively so one
+ * co-routine cannot be preempted by another, but can be preempted by a task.
+ *
+ * If an application comprises of both tasks and co-routines then
+ * vCoRoutineSchedule should be called from the idle task (in an idle task
+ * hook).
+ *
+ * Example usage:
+   <pre>
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ </pre>
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule
+ * \ingroup Tasks
+ */
+void vCoRoutineSchedule( void );
+
+/**
+ * croutine. h
+ * <pre>
+ crSTART( CoRoutineHandle_t xHandle );</pre>
+ *
+ * This macro MUST always be called at the start of a co-routine function.
+ *
+ * Example usage:
+   <pre>
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }</pre>
+ * \defgroup crSTART crSTART
+ * \ingroup Tasks
+ */
+#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
+
+/**
+ * croutine. h
+ * <pre>
+ crEND();</pre>
+ *
+ * This macro MUST always be called at the end of a co-routine function.
+ *
+ * Example usage:
+   <pre>
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }</pre>
+ * \defgroup crSTART crSTART
+ * \ingroup Tasks
+ */
+#define crEND() }
+
+/*
+ * These macros are intended for internal use by the co-routine implementation
+ * only.  The macros should not be used directly by application writers.
+ */
+#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
+#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
+
+/**
+ * croutine. h
+ *<pre>
+ crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
+ *
+ * Delay a co-routine for a fixed period of time.
+ *
+ * crDELAY can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function.  This is because
+ * co-routines do not maintain their own stack.
+ *
+ * @param xHandle The handle of the co-routine to delay.  This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should delay
+ * for.  The actual amount of time this equates to is defined by
+ * configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant portTICK_PERIOD_MS
+ * can be used to convert ticks to milliseconds.
+ *
+ * Example usage:
+   <pre>
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }</pre>
+ * \defgroup crDELAY crDELAY
+ * \ingroup Tasks
+ */
+#define crDELAY( xHandle, xTicksToDelay )												\
+	if( ( xTicksToDelay ) > 0 )															\
+	{																					\
+		vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL );							\
+	}																					\
+	crSET_STATE0( ( xHandle ) );
+
+/**
+ * <pre>
+ crQUEUE_SEND(
+                  CoRoutineHandle_t xHandle,
+                  QueueHandle_t pxQueue,
+                  void *pvItemToQueue,
+                  TickType_t xTicksToWait,
+                  BaseType_t *pxResult
+             )</pre>
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_SEND can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function.  This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine.  This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue on which the data will be posted.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvItemToQueue A pointer to the data being posted onto the queue.
+ * The number of bytes of each queued item is specified when the queue is
+ * created.  This number of bytes is copied from pvItemToQueue into the queue
+ * itself.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for space to become available on the queue, should space not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant
+ * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
+ * below).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully posted onto the queue, otherwise it will be set to an
+ * error defined within ProjDefs.h.
+ *
+ * Example usage:
+   <pre>
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xNumberToPost = 0;
+ static BaseType_t xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }</pre>
+ * \defgroup crQUEUE_SEND crQUEUE_SEND
+ * \ingroup Tasks
+ */
+#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult )			\
+{																						\
+	*( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) );	\
+	if( *( pxResult ) == errQUEUE_BLOCKED )												\
+	{																					\
+		crSET_STATE0( ( xHandle ) );													\
+		*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 );					\
+	}																					\
+	if( *pxResult == errQUEUE_YIELD )													\
+	{																					\
+		crSET_STATE1( ( xHandle ) );													\
+		*pxResult = pdPASS;																\
+	}																					\
+}
+
+/**
+ * croutine. h
+ * <pre>
+  crQUEUE_RECEIVE(
+                     CoRoutineHandle_t xHandle,
+                     QueueHandle_t pxQueue,
+                     void *pvBuffer,
+                     TickType_t xTicksToWait,
+                     BaseType_t *pxResult
+                 )</pre>
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_RECEIVE can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function.  This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine.  This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue from which the data will be received.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvBuffer The buffer into which the received item is to be copied.
+ * The number of bytes of each queued item is specified when the queue is
+ * created.  This number of bytes is copied into pvBuffer.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for data to become available from the queue, should data not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant
+ * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
+ * crQUEUE_SEND example).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully retrieved from the queue, otherwise it will be set to
+ * an error code as defined within ProjDefs.h.
+ *
+ * Example usage:
+ <pre>
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xResult;
+ static UBaseType_t uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }</pre>
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
+ * \ingroup Tasks
+ */
+#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult )			\
+{																						\
+	*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) );		\
+	if( *( pxResult ) == errQUEUE_BLOCKED ) 											\
+	{																					\
+		crSET_STATE0( ( xHandle ) );													\
+		*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 );				\
+	}																					\
+	if( *( pxResult ) == errQUEUE_YIELD )												\
+	{																					\
+		crSET_STATE1( ( xHandle ) );													\
+		*( pxResult ) = pdPASS;															\
+	}																					\
+}
+
+/**
+ * croutine. h
+ * <pre>
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvItemToQueue,
+                            BaseType_t xCoRoutinePreviouslyWoken
+                       )</pre>
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
+ * that is being used from within a co-routine.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue.  The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
+ * the same queue multiple times from a single interrupt.  The first call
+ * should always pass in pdFALSE.  Subsequent calls should pass in
+ * the value returned from the previous call.
+ *
+ * @return pdTRUE if a co-routine was woken by posting onto the queue.  This is
+ * used by the ISR to determine if a context switch may be required following
+ * the ISR.
+ *
+ * Example usage:
+ <pre>
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ char cRxedChar;
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }</pre>
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
+ * \ingroup Tasks
+ */
+#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
+
+
+/**
+ * croutine. h
+ * <pre>
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvBuffer,
+                            BaseType_t * pxCoRoutineWoken
+                       )</pre>
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
+ * from a queue that is being used from within a co-routine (a co-routine
+ * posted to the queue).
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvBuffer A pointer to a buffer into which the received item will be
+ * placed.  The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from the queue into
+ * pvBuffer.
+ *
+ * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
+ * available on the queue.  If crQUEUE_RECEIVE_FROM_ISR causes such a
+ * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
+ * *pxCoRoutineWoken will remain unchanged.
+ *
+ * @return pdTRUE an item was successfully received from the queue, otherwise
+ * pdFALSE.
+ *
+ * Example usage:
+ <pre>
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }</pre>
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
+ * \ingroup Tasks
+ */
+#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
+
+/*
+ * This function is intended for internal use by the co-routine macros only.
+ * The macro nature of the co-routine implementation requires that the
+ * prototype appears here.  The function should not be used by application
+ * writers.
+ *
+ * Removes the current co-routine from its ready list and places it in the
+ * appropriate delayed list.
+ */
+void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
+
+/*
+ * This function is intended for internal use by the queue implementation only.
+ * The function should not be used by application writers.
+ *
+ * Removes the highest priority co-routine from the event list and places it in
+ * the pending ready list.
+ */
+BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CO_ROUTINE_H */

+ 321 - 0
app/FreeRTOS-8.2.3/include/deprecated_definitions.h

@@ -0,0 +1,321 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef DEPRECATED_DEFINITIONS_H
+#define DEPRECATED_DEFINITIONS_H
+
+
+/* Each FreeRTOS port has a unique portmacro.h header file.  Originally a
+pre-processor definition was used to ensure the pre-processor found the correct
+portmacro.h file for the port being used.  That scheme was deprecated in favour
+of setting the compiler's include path such that it found the correct
+portmacro.h file - removing the need for the constant and allowing the
+portmacro.h file to be located anywhere in relation to the port being used.  The
+definitions below remain in the code for backward compatibility only.  New
+projects should not use them. */
+
+#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
+	#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
+	typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
+	#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
+	typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef GCC_MEGA_AVR
+	#include "../portable/GCC/ATMega323/portmacro.h"
+#endif
+
+#ifdef IAR_MEGA_AVR
+	#include "../portable/IAR/ATMega323/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC24_PORT
+	#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_DSPIC_PORT
+	#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC18F_PORT
+	#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC32MX_PORT
+	#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
+#endif
+
+#ifdef _FEDPICC
+	#include "libFreeRTOS/Include/portmacro.h"
+#endif
+
+#ifdef SDCC_CYGNAL
+	#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7
+	#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7_ECLIPSE
+	#include "portmacro.h"
+#endif
+
+#ifdef ROWLEY_LPC23xx
+	#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
+#endif
+
+#ifdef IAR_MSP430
+	#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
+#endif
+
+#ifdef GCC_MSP430
+	#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ROWLEY_MSP430
+	#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ARM7_LPC21xx_KEIL_RVDS
+	#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
+#endif
+
+#ifdef SAM7_GCC
+	#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
+#endif
+
+#ifdef SAM7_IAR
+	#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
+#endif
+
+#ifdef SAM9XE_IAR
+	#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
+#endif
+
+#ifdef LPC2000_IAR
+	#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
+#endif
+
+#ifdef STR71X_IAR
+	#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
+#endif
+
+#ifdef STR75X_IAR
+	#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
+#endif
+
+#ifdef STR75X_GCC
+	#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
+#endif
+
+#ifdef STR91X_IAR
+	#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
+#endif
+
+#ifdef GCC_H8S
+	#include "../../Source/portable/GCC/H8S2329/portmacro.h"
+#endif
+
+#ifdef GCC_AT91FR40008
+	#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
+#endif
+
+#ifdef RVDS_ARMCM3_LM3S102
+	#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3_LM3S102
+	#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3
+	#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARM_CM3
+	#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARMCM3_LM
+	#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef HCS12_CODE_WARRIOR
+	#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
+#endif
+
+#ifdef MICROBLAZE_GCC
+	#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
+#endif
+
+#ifdef TERN_EE
+	#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
+#endif
+
+#ifdef GCC_HCS12
+	#include "../../Source/portable/GCC/HCS12/portmacro.h"
+#endif
+
+#ifdef GCC_MCF5235
+    #include "../../Source/portable/GCC/MCF5235/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_GCC
+	#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_CODEWARRIOR
+	#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef GCC_PPC405
+	#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
+#endif
+
+#ifdef GCC_PPC440
+	#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
+#endif
+
+#ifdef _16FX_SOFTUNE
+	#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
+#endif
+
+#ifdef BCC_INDUSTRIAL_PC_PORT
+	/* A short file name has to be used in place of the normal
+	FreeRTOSConfig.h when using the Borland compiler. */
+	#include "frconfig.h"
+	#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
+    typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef BCC_FLASH_LITE_186_PORT
+	/* A short file name has to be used in place of the normal
+	FreeRTOSConfig.h when using the Borland compiler. */
+	#include "frconfig.h"
+	#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
+    typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef __GNUC__
+   #ifdef __AVR32_AVR32A__
+	   #include "portmacro.h"
+   #endif
+#endif
+
+#ifdef __ICCAVR32__
+   #ifdef __CORE__
+      #if __CORE__ == __AVR32A__
+	      #include "portmacro.h"
+      #endif
+   #endif
+#endif
+
+#ifdef __91467D
+	#include "portmacro.h"
+#endif
+
+#ifdef __96340
+	#include "portmacro.h"
+#endif
+
+
+#ifdef __IAR_V850ES_Fx3__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3_L__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx2__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Hx2__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3__
+	#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3L__
+	#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#endif /* DEPRECATED_DEFINITIONS_H */
+

+ 730 - 0
app/FreeRTOS-8.2.3/include/event_groups.h

@@ -0,0 +1,730 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef EVENT_GROUPS_H
+#define EVENT_GROUPS_H
+
+#ifndef INC_FREERTOS_H
+	#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
+#endif
+
+#include "timers.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An event group is a collection of bits to which an application can assign a
+ * meaning.  For example, an application may create an event group to convey
+ * the status of various CAN bus related events in which bit 0 might mean "A CAN
+ * message has been received and is ready for processing", bit 1 might mean "The
+ * application has queued a message that is ready for sending onto the CAN
+ * network", and bit 2 might mean "It is time to send a SYNC message onto the
+ * CAN network" etc.  A task can then test the bit values to see which events
+ * are active, and optionally enter the Blocked state to wait for a specified
+ * bit or a group of specified bits to be active.  To continue the CAN bus
+ * example, a CAN controlling task can enter the Blocked state (and therefore
+ * not consume any processing time) until either bit 0, bit 1 or bit 2 are
+ * active, at which time the bit that was actually active would inform the task
+ * which action it had to take (process a received message, send a message, or
+ * send a SYNC).
+ *
+ * The event groups implementation contains intelligence to avoid race
+ * conditions that would otherwise occur were an application to use a simple
+ * variable for the same purpose.  This is particularly important with respect
+ * to when a bit within an event group is to be cleared, and when bits have to
+ * be set and then tested atomically - as is the case where event groups are
+ * used to create a synchronisation point between multiple tasks (a
+ * 'rendezvous').
+ *
+ * \defgroup EventGroup
+ */
+
+
+
+/**
+ * event_groups.h
+ *
+ * Type by which event groups are referenced.  For example, a call to
+ * xEventGroupCreate() returns an EventGroupHandle_t variable that can then
+ * be used as a parameter to other event group functions.
+ *
+ * \defgroup EventGroupHandle_t EventGroupHandle_t
+ * \ingroup EventGroup
+ */
+typedef void * EventGroupHandle_t;
+
+/* 
+ * The type that holds event bits always matches TickType_t - therefore the
+ * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
+ * 32 bits if set to 0. 
+ *
+ * \defgroup EventBits_t EventBits_t
+ * \ingroup EventGroup
+ */
+typedef TickType_t EventBits_t;
+
+/**
+ * event_groups.h
+ *<pre>
+ EventGroupHandle_t xEventGroupCreate( void );
+ </pre>
+ *
+ * Create a new event group.  This function cannot be called from an interrupt.
+ *
+ * Although event groups are not related to ticks, for internal implementation
+ * reasons the number of bits available for use in an event group is dependent
+ * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h.  If
+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
+ * 0 to bit 7).  If configUSE_16_BIT_TICKS is set to 0 then each event group has
+ * 24 usable bits (bit 0 to bit 23).  The EventBits_t type is used to store
+ * event bits within an event group.
+ *
+ * @return If the event group was created then a handle to the event group is
+ * returned.  If there was insufficient FreeRTOS heap available to create the
+ * event group then NULL is returned.  See http://www.freertos.org/a00111.html
+ *
+ * Example usage:
+   <pre>
+	// Declare a variable to hold the created event group.
+	EventGroupHandle_t xCreatedEventGroup;
+
+	// Attempt to create the event group.
+	xCreatedEventGroup = xEventGroupCreate();
+
+	// Was the event group created successfully?
+	if( xCreatedEventGroup == NULL )
+	{
+		// The event group was not created because there was insufficient
+		// FreeRTOS heap available.
+	}
+	else
+	{
+		// The event group was created.
+	}
+   </pre>
+ * \defgroup xEventGroupCreate xEventGroupCreate
+ * \ingroup EventGroup
+ */
+EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
+										const EventBits_t uxBitsToWaitFor,
+										const BaseType_t xClearOnExit,
+										const BaseType_t xWaitForAllBits,
+										const TickType_t xTicksToWait );
+ </pre>
+ *
+ * [Potentially] block to wait for one or more bits to be set within a
+ * previously created event group.
+ *
+ * This function cannot be called from an interrupt.
+ *
+ * @param xEventGroup The event group in which the bits are being tested.  The
+ * event group must have previously been created using a call to
+ * xEventGroupCreate().
+ *
+ * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group.  For example, to wait for bit 0 and/or bit 2 set
+ * uxBitsToWaitFor to 0x05.  To wait for bits 0 and/or bit 1 and/or bit 2 set
+ * uxBitsToWaitFor to 0x07.  Etc.
+ *
+ * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
+ * uxBitsToWaitFor that are set within the event group will be cleared before
+ * xEventGroupWaitBits() returns if the wait condition was met (if the function
+ * returns for a reason other than a timeout).  If xClearOnExit is set to
+ * pdFALSE then the bits set in the event group are not altered when the call to
+ * xEventGroupWaitBits() returns.
+ *
+ * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
+ * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
+ * are set or the specified block time expires.  If xWaitForAllBits is set to
+ * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
+ * in uxBitsToWaitFor is set or the specified block time expires.  The block
+ * time is specified by the xTicksToWait parameter.
+ *
+ * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
+ * for one/all (depending on the xWaitForAllBits value) of the bits specified by
+ * uxBitsToWaitFor to become set.
+ *
+ * @return The value of the event group at the time either the bits being waited
+ * for became set, or the block time expired.  Test the return value to know
+ * which bits were set.  If xEventGroupWaitBits() returned because its timeout
+ * expired then not all the bits being waited for will be set.  If
+ * xEventGroupWaitBits() returned because the bits it was waiting for were set
+ * then the returned value is the event group value before any bits were
+ * automatically cleared in the case that xClearOnExit parameter was set to
+ * pdTRUE.
+ *
+ * Example usage:
+   <pre>
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+		// the event group.  Clear the bits before exiting.
+		uxBits = xEventGroupWaitBits(
+					xEventGroup,	// The event group being tested.
+					BIT_0 | BIT_4,	// The bits within the event group to wait for.
+					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
+					pdFALSE,		// Don't wait for both bits, either bit will do.
+					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// xEventGroupWaitBits() returned because both bits were set.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_0 was set.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_4 was set.
+		}
+		else
+		{
+			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
+			// without either BIT_0 or BIT_4 becoming set.
+		}
+   }
+   </pre>
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ </pre>
+ *
+ * Clear bits within an event group.  This function cannot be called from an
+ * interrupt.
+ *
+ * @param xEventGroup The event group in which the bits are to be cleared.
+ *
+ * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
+ * in the event group.  For example, to clear bit 3 only, set uxBitsToClear to
+ * 0x08.  To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
+ *
+ * @return The value of the event group before the specified bits were cleared.
+ *
+ * Example usage:
+   <pre>
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Clear bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupClearBits(
+								xEventGroup,	// The event group being updated.
+								BIT_0 | BIT_4 );// The bits being cleared.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+			// called.  Both will now be clear (not set).
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 were set in the first place.
+		}
+   }
+   </pre>
+ * \defgroup xEventGroupClearBits xEventGroupClearBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ *<pre>
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ </pre>
+ *
+ * A version of xEventGroupClearBits() that can be called from an interrupt.
+ *
+ * Setting bits in an event group is not a deterministic operation because there
+ * are an unknown number of tasks that may be waiting for the bit or bits being
+ * set.  FreeRTOS does not allow nondeterministic operations to be performed
+ * while interrupts are disabled, so protects event groups that are accessed
+ * from tasks by suspending the scheduler rather than disabling interrupts.  As
+ * a result event groups cannot be accessed directly from an interrupt service
+ * routine.  Therefore xEventGroupClearBitsFromISR() sends a message to the 
+ * timer task to have the clear operation performed in the context of the timer 
+ * task.
+ *
+ * @param xEventGroup The event group in which the bits are to be cleared.
+ *
+ * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
+ * For example, to clear bit 3 only, set uxBitsToClear to 0x08.  To clear bit 3
+ * and bit 0 set uxBitsToClear to 0x09.
+ *
+ * @return If the request to execute the function was posted successfully then 
+ * pdPASS is returned, otherwise pdFALSE is returned.  pdFALSE will be returned 
+ * if the timer service queue was full.
+ *
+ * Example usage:
+   <pre>
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+		// Clear bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupClearBitsFromISR(
+							xEventGroup,	 // The event group being updated.
+							BIT_0 | BIT_4 ); // The bits being set.
+
+		if( xResult == pdPASS )
+		{
+			// The message was posted successfully.
+		}
+  }
+   </pre>
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
+ * \ingroup EventGroup
+ */
+#if( configUSE_TRACE_FACILITY == 1 )
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
+#else
+	#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
+#endif
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ </pre>
+ *
+ * Set bits within an event group.
+ * This function cannot be called from an interrupt.  xEventGroupSetBitsFromISR()
+ * is a version that can be called from an interrupt.
+ *
+ * Setting bits in an event group will automatically unblock tasks that are
+ * blocked waiting for the bits.
+ *
+ * @param xEventGroup The event group in which the bits are to be set.
+ *
+ * @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
+ * For example, to set bit 3 only, set uxBitsToSet to 0x08.  To set bit 3
+ * and bit 0 set uxBitsToSet to 0x09.
+ *
+ * @return The value of the event group at the time the call to
+ * xEventGroupSetBits() returns.  There are two reasons why the returned value
+ * might have the bits specified by the uxBitsToSet parameter cleared.  First,
+ * if setting a bit results in a task that was waiting for the bit leaving the
+ * blocked state then it is possible the bit will be cleared automatically
+ * (see the xClearBitOnExit parameter of xEventGroupWaitBits()).  Second, any
+ * unblocked (or otherwise Ready state) task that has a priority above that of
+ * the task that called xEventGroupSetBits() will execute and may change the
+ * event group value before the call to xEventGroupSetBits() returns.
+ *
+ * Example usage:
+   <pre>
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupSetBits(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4 );// The bits being set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 remained set when the function returned.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 remained set when the function returned, but bit 4 was
+			// cleared.  It might be that bit 4 was cleared automatically as a
+			// task that was waiting for bit 4 was removed from the Blocked
+			// state.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 remained set when the function returned, but bit 0 was
+			// cleared.  It might be that bit 0 was cleared automatically as a
+			// task that was waiting for bit 0 was removed from the Blocked
+			// state.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 remained set.  It might be that a task
+			// was waiting for both of the bits to be set, and the bits were
+			// cleared as the task left the Blocked state.
+		}
+   }
+   </pre>
+ * \defgroup xEventGroupSetBits xEventGroupSetBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ *<pre>
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ </pre>
+ *
+ * A version of xEventGroupSetBits() that can be called from an interrupt.
+ *
+ * Setting bits in an event group is not a deterministic operation because there
+ * are an unknown number of tasks that may be waiting for the bit or bits being
+ * set.  FreeRTOS does not allow nondeterministic operations to be performed in
+ * interrupts or from critical sections.  Therefore xEventGroupSetBitFromISR()
+ * sends a message to the timer task to have the set operation performed in the
+ * context of the timer task - where a scheduler lock is used in place of a
+ * critical section.
+ *
+ * @param xEventGroup The event group in which the bits are to be set.
+ *
+ * @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
+ * For example, to set bit 3 only, set uxBitsToSet to 0x08.  To set bit 3
+ * and bit 0 set uxBitsToSet to 0x09.
+ *
+ * @param pxHigherPriorityTaskWoken As mentioned above, calling this function
+ * will result in a message being sent to the timer daemon task.  If the
+ * priority of the timer daemon task is higher than the priority of the
+ * currently running task (the task the interrupt interrupted) then
+ * *pxHigherPriorityTaskWoken will be set to pdTRUE by
+ * xEventGroupSetBitsFromISR(), indicating that a context switch should be
+ * requested before the interrupt exits.  For that reason
+ * *pxHigherPriorityTaskWoken must be initialised to pdFALSE.  See the
+ * example code below.
+ *
+ * @return If the request to execute the function was posted successfully then 
+ * pdPASS is returned, otherwise pdFALSE is returned.  pdFALSE will be returned 
+ * if the timer service queue was full.
+ *
+ * Example usage:
+   <pre>
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+   BaseType_t xHigherPriorityTaskWoken, xResult;
+
+		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupSetBitsFromISR(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4   // The bits being set.
+							&xHigherPriorityTaskWoken );
+
+		// Was the message posted successfully?
+		if( xResult == pdPASS )
+		{
+			// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+			// switch should be requested.  The macro used is port specific and 
+			// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
+			// refer to the documentation page for the port being used.
+			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+		}
+  }
+   </pre>
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
+ * \ingroup EventGroup
+ */
+#if( configUSE_TRACE_FACILITY == 1 )
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+#else
+	#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
+#endif
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
+									const EventBits_t uxBitsToSet,
+									const EventBits_t uxBitsToWaitFor,
+									TickType_t xTicksToWait );
+ </pre>
+ *
+ * Atomically set bits within an event group, then wait for a combination of
+ * bits to be set within the same event group.  This functionality is typically
+ * used to synchronise multiple tasks, where each task has to wait for the other
+ * tasks to reach a synchronisation point before proceeding.
+ *
+ * This function cannot be used from an interrupt.
+ *
+ * The function will return before its block time expires if the bits specified
+ * by the uxBitsToWait parameter are set, or become set within that time.  In
+ * this case all the bits specified by uxBitsToWait will be automatically
+ * cleared before the function returns.
+ *
+ * @param xEventGroup The event group in which the bits are being tested.  The
+ * event group must have previously been created using a call to
+ * xEventGroupCreate().
+ *
+ * @param uxBitsToSet The bits to set in the event group before determining
+ * if, and possibly waiting for, all the bits specified by the uxBitsToWait
+ * parameter are set.
+ *
+ * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group.  For example, to wait for bit 0 and bit 2 set
+ * uxBitsToWaitFor to 0x05.  To wait for bits 0 and bit 1 and bit 2 set
+ * uxBitsToWaitFor to 0x07.  Etc.
+ *
+ * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
+ * for all of the bits specified by uxBitsToWaitFor to become set.
+ *
+ * @return The value of the event group at the time either the bits being waited
+ * for became set, or the block time expired.  Test the return value to know
+ * which bits were set.  If xEventGroupSync() returned because its timeout
+ * expired then not all the bits being waited for will be set.  If
+ * xEventGroupSync() returned because all the bits it was waiting for were
+ * set then the returned value is the event group value before any bits were
+ * automatically cleared.
+ *
+ * Example usage:
+ <pre>
+ // Bits used by the three tasks.
+ #define TASK_0_BIT		( 1 << 0 )
+ #define TASK_1_BIT		( 1 << 1 )
+ #define TASK_2_BIT		( 1 << 2 )
+
+ #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+
+ // Use an event group to synchronise three tasks.  It is assumed this event
+ // group has already been created elsewhere.
+ EventGroupHandle_t xEventBits;
+
+ void vTask0( void *pvParameters )
+ {
+ EventBits_t uxReturn;
+ TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 0 in the event flag to note this task has reached the
+		// sync point.  The other two tasks will set the other two bits defined
+		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
+		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
+		// for this to happen.
+		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+
+		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+		{
+			// All three tasks reached the synchronisation point before the call
+			// to xEventGroupSync() timed out.
+		}
+	}
+ }
+
+ void vTask1( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 1 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	 }
+ }
+
+ void vTask2( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 2 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	}
+ }
+
+ </pre>
+ * \defgroup xEventGroupSync xEventGroupSync
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ </pre>
+ *
+ * Returns the current value of the bits in an event group.  This function
+ * cannot be used from an interrupt.
+ *
+ * @param xEventGroup The event group being queried.
+ *
+ * @return The event group bits at the time xEventGroupGetBits() was called.
+ *
+ * \defgroup xEventGroupGetBits xEventGroupGetBits
+ * \ingroup EventGroup
+ */
+#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
+
+/**
+ * event_groups.h
+ *<pre>
+	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ </pre>
+ *
+ * A version of xEventGroupGetBits() that can be called from an ISR.
+ *
+ * @param xEventGroup The event group being queried.
+ *
+ * @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
+ *
+ * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ *<pre>
+	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ </pre>
+ *
+ * Delete an event group that was previously created by a call to
+ * xEventGroupCreate().  Tasks that are blocked on the event group will be
+ * unblocked and obtain 0 as the event group's value.
+ *
+ * @param xEventGroup The event group being deleted.
+ */
+void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
+
+/* For internal use only. */
+void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
+void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
+
+#if (configUSE_TRACE_FACILITY == 1)
+	UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EVENT_GROUPS_H */
+
+

+ 453 - 0
app/FreeRTOS-8.2.3/include/list.h

@@ -0,0 +1,453 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*
+ * This is the list implementation used by the scheduler.  While it is tailored
+ * heavily for the schedulers needs, it is also available for use by
+ * application code.
+ *
+ * list_ts can only store pointers to list_item_ts.  Each ListItem_t contains a
+ * numeric value (xItemValue).  Most of the time the lists are sorted in
+ * descending item value order.
+ *
+ * Lists are created already containing one list item.  The value of this
+ * item is the maximum possible that can be stored, it is therefore always at
+ * the end of the list and acts as a marker.  The list member pxHead always
+ * points to this marker - even though it is at the tail of the list.  This
+ * is because the tail contains a wrap back pointer to the true head of
+ * the list.
+ *
+ * In addition to it's value, each list item contains a pointer to the next
+ * item in the list (pxNext), a pointer to the list it is in (pxContainer)
+ * and a pointer to back to the object that contains it.  These later two
+ * pointers are included for efficiency of list manipulation.  There is
+ * effectively a two way link between the object containing the list item and
+ * the list item itself.
+ *
+ *
+ * \page ListIntroduction List Implementation
+ * \ingroup FreeRTOSIntro
+ */
+
+#ifndef INC_FREERTOS_H
+	#error FreeRTOS.h must be included before list.h
+#endif
+
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * The list structure members are modified from within interrupts, and therefore
+ * by rights should be declared volatile.  However, they are only modified in a
+ * functionally atomic way (within critical sections of with the scheduler
+ * suspended) and are either passed by reference into a function or indexed via
+ * a volatile variable.  Therefore, in all use cases tested so far, the volatile
+ * qualifier can be omitted in order to provide a moderate performance
+ * improvement without adversely affecting functional behaviour.  The assembly
+ * instructions generated by the IAR, ARM and GCC compilers when the respective
+ * compiler's options were set for maximum optimisation has been inspected and
+ * deemed to be as intended.  That said, as compiler technology advances, and
+ * especially if aggressive cross module optimisation is used (a use case that
+ * has not been exercised to any great extend) then it is feasible that the
+ * volatile qualifier will be needed for correct optimisation.  It is expected
+ * that a compiler removing essential code because, without the volatile
+ * qualifier on the list structure members and with aggressive cross module
+ * optimisation, the compiler deemed the code unnecessary will result in
+ * complete and obvious failure of the scheduler.  If this is ever experienced
+ * then the volatile qualifier can be inserted in the relevant places within the
+ * list structures by simply defining configLIST_VOLATILE to volatile in
+ * FreeRTOSConfig.h (as per the example at the bottom of this comment block).
+ * If configLIST_VOLATILE is not defined then the preprocessor directives below
+ * will simply #define configLIST_VOLATILE away completely.
+ *
+ * To use volatile list structure members then add the following line to
+ * FreeRTOSConfig.h (without the quotes):
+ * "#define configLIST_VOLATILE volatile"
+ */
+#ifndef configLIST_VOLATILE
+	#define configLIST_VOLATILE
+#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Macros that can be used to place known values within the list structures,
+then check that the known values do not get corrupted during the execution of
+the application.   These may catch the list data structures being overwritten in
+memory.  They will not catch data errors caused by incorrect configuration or
+use of FreeRTOS.*/
+#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
+	/* Define the macros to do nothing. */
+	#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
+	#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
+	#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
+	#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
+	#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
+	#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
+	#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
+	#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
+	#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
+	#define listTEST_LIST_INTEGRITY( pxList )
+#else
+	/* Define macros that add new members into the list structures. */
+	#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE				TickType_t xListItemIntegrityValue1;
+	#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE				TickType_t xListItemIntegrityValue2;
+	#define listFIRST_LIST_INTEGRITY_CHECK_VALUE					TickType_t xListIntegrityValue1;
+	#define listSECOND_LIST_INTEGRITY_CHECK_VALUE					TickType_t xListIntegrityValue2;
+
+	/* Define macros that set the new structure members to known values. */
+	#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )		( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
+	#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )	( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
+	#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )		( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
+	#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )		( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
+
+	/* Define macros that will assert if one of the structure members does not
+	contain its expected value. */
+	#define listTEST_LIST_ITEM_INTEGRITY( pxItem )		configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
+	#define listTEST_LIST_INTEGRITY( pxList )			configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
+#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
+
+
+/*
+ * Definition of the only type of object that a list can contain.
+ */
+struct xLIST_ITEM
+{
+	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+	configLIST_VOLATILE TickType_t xItemValue;			/*< The value being listed.  In most cases this is used to sort the list in descending order. */
+	struct xLIST_ITEM * configLIST_VOLATILE pxNext;		/*< Pointer to the next ListItem_t in the list. */
+	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;	/*< Pointer to the previous ListItem_t in the list. */
+	void * pvOwner;										/*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
+	void * configLIST_VOLATILE pvContainer;				/*< Pointer to the list in which this list item is placed (if any). */
+	listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+};
+typedef struct xLIST_ITEM ListItem_t;					/* For some reason lint wants this as two separate definitions. */
+
+struct xMINI_LIST_ITEM
+{
+	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+	configLIST_VOLATILE TickType_t xItemValue;
+	struct xLIST_ITEM * configLIST_VOLATILE pxNext;
+	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
+};
+typedef struct xMINI_LIST_ITEM MiniListItem_t;
+
+/*
+ * Definition of the type of queue used by the scheduler.
+ */
+typedef struct xLIST
+{
+	listFIRST_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+	configLIST_VOLATILE UBaseType_t uxNumberOfItems;
+	ListItem_t * configLIST_VOLATILE pxIndex;			/*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
+	MiniListItem_t xListEnd;							/*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
+	listSECOND_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+} List_t;
+
+/*
+ * Access macro to set the owner of a list item.  The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )		( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
+
+/*
+ * Access macro to get the owner of a list item.  The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_OWNER( pxListItem )	( ( pxListItem )->pvOwner )
+
+/*
+ * Access macro to set the value of the list item.  In most cases the value is
+ * used to sort the list in descending order.
+ *
+ * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )	( ( pxListItem )->xItemValue = ( xValue ) )
+
+/*
+ * Access macro to retrieve the value of the list item.  The value can
+ * represent anything - for example the priority of a task, or the time at
+ * which a task should be unblocked.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_VALUE( pxListItem )	( ( pxListItem )->xItemValue )
+
+/*
+ * Access macro to retrieve the value of the list item at the head of a given
+ * list.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext->xItemValue )
+
+/*
+ * Return the list item at the head of the list.
+ *
+ * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext )
+
+/*
+ * Return the list item at the head of the list.
+ *
+ * \page listGET_NEXT listGET_NEXT
+ * \ingroup LinkedList
+ */
+#define listGET_NEXT( pxListItem )	( ( pxListItem )->pxNext )
+
+/*
+ * Return the list item that marks the end of the list
+ *
+ * \page listGET_END_MARKER listGET_END_MARKER
+ * \ingroup LinkedList
+ */
+#define listGET_END_MARKER( pxList )	( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
+
+/*
+ * Access macro to determine if a list contains any items.  The macro will
+ * only have the value true if the list is empty.
+ *
+ * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
+ * \ingroup LinkedList
+ */
+#define listLIST_IS_EMPTY( pxList )	( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
+
+/*
+ * Access macro to return the number of items in the list.
+ */
+#define listCURRENT_LIST_LENGTH( pxList )	( ( pxList )->uxNumberOfItems )
+
+/*
+ * Access function to obtain the owner of the next entry in a list.
+ *
+ * The list member pxIndex is used to walk through a list.  Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
+ * and returns that entry's pxOwner parameter.  Using multiple calls to this
+ * function it is therefore possible to move through every item contained in
+ * a list.
+ *
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item.  In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxTCB pxTCB is set to the address of the owner of the next list item.
+ * @param pxList The list from which the next item owner is to be returned.
+ *
+ * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )										\
+{																							\
+List_t * const pxConstList = ( pxList );													\
+	/* Increment the index to the next item and return the item, ensuring */				\
+	/* we don't return the marker used at the end of the list.  */							\
+	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;							\
+	if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )	\
+	{																						\
+		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\
+	}																						\
+	( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;											\
+}
+
+
+/*
+ * Access function to obtain the owner of the first entry in a list.  Lists
+ * are normally sorted in ascending item value order.
+ *
+ * This function returns the pxOwner member of the first item in the list.
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item.  In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxList The list from which the owner of the head item is to be
+ * returned.
+ *
+ * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
+
+/*
+ * Check to see if a list item is within a list.  The list item maintains a
+ * "container" pointer that points to the list it is in.  All this macro does
+ * is check to see if the container and the list match.
+ *
+ * @param pxList The list we want to know if the list item is within.
+ * @param pxListItem The list item we want to know if is in the list.
+ * @return pdTRUE if the list item is in the list, otherwise pdFALSE.
+ */
+#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
+
+/*
+ * Return the list a list item is contained within (referenced from).
+ *
+ * @param pxListItem The list item being queried.
+ * @return A pointer to the List_t object that references the pxListItem
+ */
+#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
+
+/*
+ * This provides a crude means of knowing if a list has been initialised, as
+ * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
+ * function.
+ */
+#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
+
+/*
+ * Must be called before a list is used!  This initialises all the members
+ * of the list structure and inserts the xListEnd item into the list as a
+ * marker to the back of the list.
+ *
+ * @param pxList Pointer to the list being initialised.
+ *
+ * \page vListInitialise vListInitialise
+ * \ingroup LinkedList
+ */
+void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
+
+/*
+ * Must be called before a list item is used.  This sets the list container to
+ * null so the item does not think that it is already contained in a list.
+ *
+ * @param pxItem Pointer to the list item being initialised.
+ *
+ * \page vListInitialiseItem vListInitialiseItem
+ * \ingroup LinkedList
+ */
+void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert a list item into a list.  The item will be inserted into the list in
+ * a position determined by its item value (descending item value order).
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The item that is to be placed in the list.
+ *
+ * \page vListInsert vListInsert
+ * \ingroup LinkedList
+ */
+void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert a list item into a list.  The item will be inserted in a position
+ * such that it will be the last item within the list returned by multiple
+ * calls to listGET_OWNER_OF_NEXT_ENTRY.
+ *
+ * The list member pvIndex is used to walk through a list.  Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list.
+ * Placing an item in a list using vListInsertEnd effectively places the item
+ * in the list position pointed to by pvIndex.  This means that every other
+ * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+ * the pvIndex parameter again points to the item being inserted.
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The list item to be inserted into the list.
+ *
+ * \page vListInsertEnd vListInsertEnd
+ * \ingroup LinkedList
+ */
+void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Remove an item from a list.  The list item has a pointer to the list that
+ * it is in, so only the list item need be passed into the function.
+ *
+ * @param uxListRemove The item to be removed.  The item will remove itself from
+ * the list pointed to by it's pxContainer parameter.
+ *
+ * @return The number of items that remain in the list after the list item has
+ * been removed.
+ *
+ * \page uxListRemove uxListRemove
+ * \ingroup LinkedList
+ */
+UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 177 - 0
app/FreeRTOS-8.2.3/include/mpu_wrappers.h

@@ -0,0 +1,177 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef MPU_WRAPPERS_H
+#define MPU_WRAPPERS_H
+
+/* This file redefines API functions to be called through a wrapper macro, but
+only for ports that are using the MPU. */
+#ifdef portUSING_MPU_WRAPPERS
+
+	/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
+	included from queue.c or task.c to prevent it from having an effect within
+	those files. */
+	#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+		#define xTaskGenericCreate				MPU_xTaskGenericCreate
+		#define vTaskAllocateMPURegions			MPU_vTaskAllocateMPURegions
+		#define vTaskDelete						MPU_vTaskDelete
+		#define vTaskDelayUntil					MPU_vTaskDelayUntil
+		#define vTaskDelay						MPU_vTaskDelay
+		#define uxTaskPriorityGet				MPU_uxTaskPriorityGet
+		#define vTaskPrioritySet				MPU_vTaskPrioritySet
+		#define eTaskGetState					MPU_eTaskGetState
+		#define vTaskSuspend					MPU_vTaskSuspend
+		#define vTaskResume						MPU_vTaskResume
+		#define vTaskSuspendAll					MPU_vTaskSuspendAll
+		#define xTaskResumeAll					MPU_xTaskResumeAll
+		#define xTaskGetTickCount				MPU_xTaskGetTickCount
+		#define uxTaskGetNumberOfTasks			MPU_uxTaskGetNumberOfTasks
+		#define vTaskList						MPU_vTaskList
+		#define vTaskGetRunTimeStats			MPU_vTaskGetRunTimeStats
+		#define vTaskSetApplicationTaskTag		MPU_vTaskSetApplicationTaskTag
+		#define xTaskGetApplicationTaskTag		MPU_xTaskGetApplicationTaskTag
+		#define xTaskCallApplicationTaskHook	MPU_xTaskCallApplicationTaskHook
+		#define uxTaskGetStackHighWaterMark		MPU_uxTaskGetStackHighWaterMark
+		#define xTaskGetCurrentTaskHandle		MPU_xTaskGetCurrentTaskHandle
+		#define xTaskGetSchedulerState			MPU_xTaskGetSchedulerState
+		#define xTaskGetIdleTaskHandle			MPU_xTaskGetIdleTaskHandle
+		#define uxTaskGetSystemState			MPU_uxTaskGetSystemState
+		#define xTaskGenericNotify				MPU_xTaskGenericNotify
+		#define xTaskNotifyWait					MPU_xTaskNotifyWait
+		#define ulTaskNotifyTake				MPU_ulTaskNotifyTake
+
+		#define xQueueGenericCreate				MPU_xQueueGenericCreate
+		#define xQueueCreateMutex				MPU_xQueueCreateMutex
+		#define xQueueGiveMutexRecursive		MPU_xQueueGiveMutexRecursive
+		#define xQueueTakeMutexRecursive		MPU_xQueueTakeMutexRecursive
+		#define xQueueCreateCountingSemaphore	MPU_xQueueCreateCountingSemaphore
+		#define xQueueGenericSend				MPU_xQueueGenericSend
+		#define xQueueAltGenericSend			MPU_xQueueAltGenericSend
+		#define xQueueAltGenericReceive			MPU_xQueueAltGenericReceive
+		#define xQueueGenericReceive			MPU_xQueueGenericReceive
+		#define uxQueueMessagesWaiting			MPU_uxQueueMessagesWaiting
+		#define vQueueDelete					MPU_vQueueDelete
+		#define xQueueGenericReset				MPU_xQueueGenericReset
+		#define xQueueCreateSet					MPU_xQueueCreateSet
+		#define xQueueSelectFromSet				MPU_xQueueSelectFromSet
+		#define xQueueAddToSet					MPU_xQueueAddToSet
+		#define xQueueRemoveFromSet				MPU_xQueueRemoveFromSet
+		#define xQueueGetMutexHolder			MPU_xQueueGetMutexHolder
+		#define xQueueGetMutexHolder			MPU_xQueueGetMutexHolder
+
+		#define pvPortMalloc					MPU_pvPortMalloc
+		#define vPortFree						MPU_vPortFree
+		#define xPortGetFreeHeapSize			MPU_xPortGetFreeHeapSize
+		#define vPortInitialiseBlocks			MPU_vPortInitialiseBlocks
+		#define xPortGetMinimumEverFreeHeapSize	MPU_xPortGetMinimumEverFreeHeapSize
+
+		#if configQUEUE_REGISTRY_SIZE > 0
+			#define vQueueAddToRegistry				MPU_vQueueAddToRegistry
+			#define vQueueUnregisterQueue			MPU_vQueueUnregisterQueue
+		#endif
+
+		#define xTimerCreate					MPU_xTimerCreate
+		#define pvTimerGetTimerID				MPU_pvTimerGetTimerID
+		#define vTimerSetTimerID				MPU_vTimerSetTimerID
+		#define xTimerIsTimerActive				MPU_xTimerIsTimerActive
+		#define xTimerGetTimerDaemonTaskHandle	MPU_xTimerGetTimerDaemonTaskHandle
+		#define xTimerPendFunctionCall			MPU_xTimerPendFunctionCall
+		#define pcTimerGetTimerName				MPU_pcTimerGetTimerName
+		#define xTimerGenericCommand			MPU_xTimerGenericCommand
+
+		#define xEventGroupCreate				MPU_xEventGroupCreate
+		#define xEventGroupWaitBits				MPU_xEventGroupWaitBits
+		#define xEventGroupClearBits			MPU_xEventGroupClearBits
+		#define xEventGroupSetBits				MPU_xEventGroupSetBits
+		#define xEventGroupSync					MPU_xEventGroupSync
+		#define vEventGroupDelete				MPU_vEventGroupDelete
+
+		/* Remove the privileged function macro. */
+		#define PRIVILEGED_FUNCTION
+
+	#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+		/* Ensure API functions go in the privileged execution section. */
+		#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
+		#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
+
+	#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+#else /* portUSING_MPU_WRAPPERS */
+
+	#define PRIVILEGED_FUNCTION
+	#define PRIVILEGED_DATA
+	#define portUSING_MPU_WRAPPERS 0
+
+#endif /* portUSING_MPU_WRAPPERS */
+
+
+#endif /* MPU_WRAPPERS_H */
+

+ 207 - 0
app/FreeRTOS-8.2.3/include/portable.h

@@ -0,0 +1,207 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Portable layer API.  Each function must be defined for each port.
+ *----------------------------------------------------------*/
+
+#ifndef PORTABLE_H
+#define PORTABLE_H
+
+/* Each FreeRTOS port has a unique portmacro.h header file.  Originally a
+pre-processor definition was used to ensure the pre-processor found the correct
+portmacro.h file for the port being used.  That scheme was deprecated in favour
+of setting the compiler's include path such that it found the correct
+portmacro.h file - removing the need for the constant and allowing the
+portmacro.h file to be located anywhere in relation to the port being used.
+Purely for reasons of backward compatibility the old method is still valid, but
+to make it clear that new projects should not use it, support for the port
+specific constants has been moved into the deprecated_definitions.h header
+file. */
+#include "deprecated_definitions.h"
+
+/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
+did not result in a portmacro.h header file being included - and it should be
+included here.  In this case the path to the correct portmacro.h header file
+must be set in the compiler's include path. */
+#ifndef portENTER_CRITICAL
+	#include "portmacro.h"
+#endif
+
+#if portBYTE_ALIGNMENT == 32
+	#define portBYTE_ALIGNMENT_MASK ( 0x001f )
+#endif
+
+#if portBYTE_ALIGNMENT == 16
+	#define portBYTE_ALIGNMENT_MASK ( 0x000f )
+#endif
+
+#if portBYTE_ALIGNMENT == 8
+	#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
+#endif
+
+#if portBYTE_ALIGNMENT == 4
+	#define portBYTE_ALIGNMENT_MASK	( 0x0003 )
+#endif
+
+#if portBYTE_ALIGNMENT == 2
+	#define portBYTE_ALIGNMENT_MASK	( 0x0001 )
+#endif
+
+#if portBYTE_ALIGNMENT == 1
+	#define portBYTE_ALIGNMENT_MASK	( 0x0000 )
+#endif
+
+#ifndef portBYTE_ALIGNMENT_MASK
+	#error "Invalid portBYTE_ALIGNMENT definition"
+#endif
+
+#ifndef portNUM_CONFIGURABLE_REGIONS
+	#define portNUM_CONFIGURABLE_REGIONS 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mpu_wrappers.h"
+
+/*
+ * Setup the stack of a new task so it is ready to be placed under the
+ * scheduler control.  The registers have to be placed on the stack in
+ * the order that the port expects to find them.
+ *
+ */
+#if( portUSING_MPU_WRAPPERS == 1 )
+	StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
+#else
+	StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
+#endif
+
+/* Used by heap_5.c. */
+typedef struct HeapRegion
+{
+	uint8_t *pucStartAddress;
+	size_t xSizeInBytes;
+} HeapRegion_t;
+
+/*
+ * Used to define multiple heap regions for use by heap_5.c.  This function
+ * must be called before any calls to pvPortMalloc() - not creating a task,
+ * queue, semaphore, mutex, software timer, event group, etc. will result in
+ * pvPortMalloc being called.
+ *
+ * pxHeapRegions passes in an array of HeapRegion_t structures - each of which
+ * defines a region of memory that can be used as the heap.  The array is
+ * terminated by a HeapRegions_t structure that has a size of 0.  The region
+ * with the lowest start address must appear first in the array.
+ */
+void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
+
+
+/*
+ * Map to the memory management routines required for the port.
+ */
+void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
+void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
+void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
+size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
+size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Setup the hardware ready for the scheduler to take control.  This generally
+ * sets up a tick interrupt and sets timers for the correct tick frequency.
+ */
+BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
+ * the hardware is left in its original condition after the scheduler stops
+ * executing.
+ */
+void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The structures and methods of manipulating the MPU are contained within the
+ * port layer.
+ *
+ * Fills the xMPUSettings structure with the memory region information
+ * contained in xRegions.
+ */
+#if( portUSING_MPU_WRAPPERS == 1 )
+	struct xMEMORY_REGION;
+	void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) PRIVILEGED_FUNCTION;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTABLE_H */
+

+ 156 - 0
app/FreeRTOS-8.2.3/include/projdefs.h

@@ -0,0 +1,156 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef PROJDEFS_H
+#define PROJDEFS_H
+
+/*
+ * Defines the prototype to which task functions must conform.  Defined in this
+ * file to ensure the type is known before portable.h is included.
+ */
+typedef void (*TaskFunction_t)( void * );
+
+/* Converts a time in milliseconds to a time in ticks. */
+#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
+
+#define pdFALSE			( ( BaseType_t ) 0 )
+#define pdTRUE			( ( BaseType_t ) 1 )
+
+#define pdPASS			( pdTRUE )
+#define pdFAIL			( pdFALSE )
+#define errQUEUE_EMPTY	( ( BaseType_t ) 0 )
+#define errQUEUE_FULL	( ( BaseType_t ) 0 )
+
+/* FreeRTOS error definitions. */
+#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY	( -1 )
+#define errQUEUE_BLOCKED						( -4 )
+#define errQUEUE_YIELD							( -5 )
+
+/* Macros used for basic data corruption checks. */
+#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
+	#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
+#endif
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	#define pdINTEGRITY_CHECK_VALUE 0x5a5a
+#else
+	#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
+#endif
+
+/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
+itself. */
+#define pdFREERTOS_ERRNO_NONE			0	/* No errors */
+#define	pdFREERTOS_ERRNO_ENOENT			2	/* No such file or directory */
+#define	pdFREERTOS_ERRNO_EIO			5	/* I/O error */
+#define	pdFREERTOS_ERRNO_ENXIO			6	/* No such device or address */
+#define	pdFREERTOS_ERRNO_EBADF			9	/* Bad file number */
+#define	pdFREERTOS_ERRNO_EAGAIN			11	/* No more processes */
+#define	pdFREERTOS_ERRNO_EWOULDBLOCK	11	/* Operation would block */
+#define	pdFREERTOS_ERRNO_ENOMEM			12	/* Not enough memory */
+#define	pdFREERTOS_ERRNO_EACCES			13	/* Permission denied */
+#define	pdFREERTOS_ERRNO_EFAULT			14	/* Bad address */
+#define	pdFREERTOS_ERRNO_EBUSY			16	/* Mount device busy */
+#define	pdFREERTOS_ERRNO_EEXIST			17	/* File exists */
+#define	pdFREERTOS_ERRNO_EXDEV			18	/* Cross-device link */
+#define	pdFREERTOS_ERRNO_ENODEV			19	/* No such device */
+#define	pdFREERTOS_ERRNO_ENOTDIR		20	/* Not a directory */
+#define	pdFREERTOS_ERRNO_EISDIR			21	/* Is a directory */
+#define	pdFREERTOS_ERRNO_EINVAL			22	/* Invalid argument */
+#define	pdFREERTOS_ERRNO_ENOSPC			28	/* No space left on device */
+#define	pdFREERTOS_ERRNO_ESPIPE			29	/* Illegal seek */
+#define	pdFREERTOS_ERRNO_EROFS			30	/* Read only file system */
+#define	pdFREERTOS_ERRNO_EUNATCH		42	/* Protocol driver not attached */
+#define	pdFREERTOS_ERRNO_EBADE			50	/* Invalid exchange */
+#define	pdFREERTOS_ERRNO_EFTYPE			79	/* Inappropriate file type or format */
+#define	pdFREERTOS_ERRNO_ENMFILE		89	/* No more files */
+#define	pdFREERTOS_ERRNO_ENOTEMPTY		90	/* Directory not empty */
+#define	pdFREERTOS_ERRNO_ENAMETOOLONG 	91	/* File or path name too long */
+#define	pdFREERTOS_ERRNO_EOPNOTSUPP		95	/* Operation not supported on transport endpoint */
+#define	pdFREERTOS_ERRNO_ENOBUFS		105	/* No buffer space available */
+#define	pdFREERTOS_ERRNO_ENOPROTOOPT	109	/* Protocol not available */
+#define	pdFREERTOS_ERRNO_EADDRINUSE		112	/* Address already in use */
+#define	pdFREERTOS_ERRNO_ETIMEDOUT		116	/* Connection timed out */
+#define	pdFREERTOS_ERRNO_EINPROGRESS	119	/* Connection already in progress */
+#define	pdFREERTOS_ERRNO_EALREADY		120	/* Socket already connected */
+#define	pdFREERTOS_ERRNO_EADDRNOTAVAIL 	125	/* Address not available */
+#define	pdFREERTOS_ERRNO_EISCONN		127	/* Socket is already connected */
+#define	pdFREERTOS_ERRNO_ENOTCONN		128	/* Socket is not connected */
+#define	pdFREERTOS_ERRNO_ENOMEDIUM		135	/* No medium inserted */
+#define	pdFREERTOS_ERRNO_EILSEQ			138	/* An invalid UTF-16 sequence was encountered. */
+#define	pdFREERTOS_ERRNO_ECANCELED		140	/* Operation canceled. */
+
+/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
+itself. */
+#define pdFREERTOS_LITTLE_ENDIAN	0
+#define pdFREERTOS_BIG_ENDIAN		1
+
+#endif /* PROJDEFS_H */
+
+
+

File diff suppressed because it is too large
+ 1691 - 0
app/FreeRTOS-8.2.3/include/queue.h


+ 844 - 0
app/FreeRTOS-8.2.3/include/semphr.h

@@ -0,0 +1,844 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef SEMAPHORE_H
+#define SEMAPHORE_H
+
+#ifndef INC_FREERTOS_H
+	#error "include FreeRTOS.h" must appear in source files before "include semphr.h"
+#endif
+
+#include "queue.h"
+
+typedef QueueHandle_t SemaphoreHandle_t;
+
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH	( ( uint8_t ) 1U )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH		( ( uint8_t ) 0U )
+#define semGIVE_BLOCK_TIME					( ( TickType_t ) 0U )
+
+
+/**
+ * semphr. h
+ * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre>
+ *
+ * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the
+ * xSemaphoreCreateBinary() function.  Note that binary semaphores created using
+ * the vSemaphoreCreateBinary() macro are created in a state such that the
+ * first call to 'take' the semaphore would pass, whereas binary semaphores
+ * created using xSemaphoreCreateBinary() are created in a state such that the
+ * the semaphore must first be 'given' before it can be 'taken'.
+ *
+ * <i>Macro</i> that implements a semaphore by using the existing queue mechanism.
+ * The queue length is 1 as this is a binary semaphore.  The data size is 0
+ * as we don't want to actually store any data - we just want to know if the
+ * queue is empty or full.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task.  The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore.  For this reason this type of
+ * semaphore does not use a priority inheritance mechanism.  For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param xSemaphore Handle to the created semaphore.  Should be of type SemaphoreHandle_t.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#define vSemaphoreCreateBinary( xSemaphore )																							\
+	{																																	\
+		( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );	\
+		if( ( xSemaphore ) != NULL )																									\
+		{																																\
+			( void ) xSemaphoreGive( ( xSemaphore ) );																					\
+		}																																\
+	}
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
+ *
+ * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
+ * xSemaphoreCreateBinary() function.  Note that binary semaphores created using
+ * the vSemaphoreCreateBinary() macro are created in a state such that the
+ * first call to 'take' the semaphore would pass, whereas binary semaphores
+ * created using xSemaphoreCreateBinary() are created in a state such that the
+ * the semaphore must first be 'given' before it can be 'taken'.
+ *
+ * Function that creates a semaphore by using the existing queue mechanism.
+ * The queue length is 1 as this is a binary semaphore.  The data size is 0
+ * as nothing is actually stored - all that is important is whether the queue is
+ * empty or full (the binary semaphore is available or not).
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task.  The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore.  For this reason this type of
+ * semaphore does not use a priority inheritance mechanism.  For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @return Handle to the created semaphore.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
+ *               )</pre>
+ *
+ * <i>Macro</i> to obtain a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting().
+ *
+ * @param xSemaphore A handle to the semaphore being taken - obtained when
+ * the semaphore was created.
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available.  The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time.  A block time of zero can be used to poll the semaphore.  A block
+ * time of portMAX_DELAY can be used to block indefinitely (provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
+ *
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE
+ * if xBlockTime expired without the semaphore becoming available.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreTake xSemaphoreTake
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTake( xSemaphore, xBlockTime )		xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+
+/**
+ * semphr. h
+ * xSemaphoreTakeRecursive(
+ *                          SemaphoreHandle_t xMutex,
+ *                          TickType_t xBlockTime
+ *                        )
+ *
+ * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being obtained.  This is the
+ * handle returned by xSemaphoreCreateRecursiveMutex();
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available.  The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time.  A block time of zero can be used to poll the semaphore.  If
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will
+ * return immediately no matter what the value of xBlockTime.
+ *
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime
+ * expired without the semaphore becoming available.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime )	xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
+
+
+/*
+ * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler	because it executes everything from within a critical section.
+ * This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too.  The fully featured API has more
+ * complex	code that takes longer to execute, but makes much less use of
+ * critical sections.  Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltTake( xSemaphore, xBlockTime )		xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</pre>
+ *
+ * <i>Macro</i> to release a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
+ *
+ * This macro must not be used from an ISR.  See xSemaphoreGiveFromISR () for
+ * an alternative which can be used from an ISR.
+ *
+ * This macro must also not be used on semaphores created using
+ * xSemaphoreCreateRecursiveMutex().
+ *
+ * @param xSemaphore A handle to the semaphore being released.  This is the
+ * handle returned when the semaphore was created.
+ *
+ * @return pdTRUE if the semaphore was released.  pdFALSE if an error occurred.
+ * Semaphores are implemented using queues.  An error can occur if there is
+ * no space on the queue to post a message - indicating that the
+ * semaphore was not first obtained correctly.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGive xSemaphoreGive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )</pre>
+ *
+ * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being released, or 'given'.  This is the
+ * handle returned by xSemaphoreCreateMutex();
+ *
+ * @return pdTRUE if the semaphore was given.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveRecursive( xMutex )	xQueueGiveMutexRecursive( ( xMutex ) )
+
+/*
+ * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler	because it executes everything from within a critical section.
+ * This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too.  The fully featured API has more
+ * complex	code that takes longer to execute, but makes much less use of
+ * critical sections.  Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltGive( xSemaphore )		xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * <pre>
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )</pre>
+ *
+ * <i>Macro</i> to  release a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR.
+ *
+ * @param xSemaphore A handle to the semaphore being released.  This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task.  If xSemaphoreGiveFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ <pre>
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )	xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * semphr. h
+ * <pre>
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )</pre>
+ *
+ * <i>Macro</i> to  take a semaphore from an ISR.  The semaphore must have
+ * previously been created with a call to vSemaphoreCreateBinary() or
+ * xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR, however taking a semaphore from an ISR
+ * is not a common operation.  It is likely to only be useful when taking a
+ * counting semaphore when an interrupt is obtaining an object from a resource
+ * pool (when the semaphore count indicates the number of resources available).
+ *
+ * @param xSemaphore A handle to the semaphore being taken.  This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task.  If xSemaphoreTakeFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully taken, otherwise
+ * pdFALSE
+ */
+#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )	xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre>
+ *
+ * <i>Macro</i> that implements a mutex semaphore by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros.  The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros should not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore.  Should be of type
+ *		SemaphoreHandle_t.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre>
+ *
+ * <i>Macro</i> that implements a recursive mutex by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros.  The
+ * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore.  Should be of type
+ *		SemaphoreHandle_t.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre>
+ *
+ * <i>Macro</i> that creates a counting semaphore by using the existing
+ * queue mechanism.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ *    In this usage scenario an event handler will 'give' a semaphore each time
+ *    an event occurs (incrementing the semaphore count value), and a handler
+ *    task will 'take' a semaphore each time it processes an event
+ *    (decrementing the semaphore count value).  The count value is therefore
+ *    the difference between the number of events that have occurred and the
+ *    number that have been processed.  In this case it is desirable for the
+ *    initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ *    In this usage scenario the count value indicates the number of resources
+ *    available.  To obtain control of a resource a task must first obtain a
+ *    semaphore - decrementing the semaphore count value.  When the count value
+ *    reaches zero there are no free resources.  When a task finishes with the
+ *    resource it 'gives' the semaphore back - incrementing the semaphore count
+ *    value.  In this case it is desirable for the initial count value to be
+ *    equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached.  When the
+ *        semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ *        created.
+ *
+ * @return Handle to the created semaphore.  Null if the semaphore could not be
+ *         created.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+
+/**
+ * semphr. h
+ * <pre>void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );</pre>
+ *
+ * Delete a semaphore.  This function must be used with care.  For example,
+ * do not delete a mutex type semaphore if the mutex is held by a task.
+ *
+ * @param xSemaphore A handle to the semaphore to be deleted.
+ *
+ * \defgroup vSemaphoreDelete vSemaphoreDelete
+ * \ingroup Semaphores
+ */
+#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * <pre>TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );</pre>
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ * Note: This is a good way of determining if the calling task is the mutex
+ * holder, but not a good way of determining the identity of the mutex holder as
+ * the holder may change between the function exiting and the returned value
+ * being tested.
+ */
+#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
+
+#endif /* SEMAPHORE_H */
+
+

+ 27 - 0
app/FreeRTOS-8.2.3/include/stdint.readme

@@ -0,0 +1,27 @@
+
+#ifndef FREERTOS_STDINT
+#define FREERTOS_STDINT
+
+/*******************************************************************************
+ * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
+ * necessary to build the FreeRTOS code.  It is provided to allow FreeRTOS to be
+ * built using compilers that do not provide their own stdint.h definition.
+ *
+ * To use this file:
+ *
+ *    1) Copy this file into the directory that contains your FreeRTOSConfig.h
+ *       header file, as that directory will already be in the compilers include
+ *       path.
+ *
+ *    2) Rename the copied file stdint.h.
+ *
+ */
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef long int32_t;
+typedef unsigned long uint32_t;
+
+#endif /* FREERTOS_STDINT */

File diff suppressed because it is too large
+ 2037 - 0
app/FreeRTOS-8.2.3/include/task.h


File diff suppressed because it is too large
+ 1146 - 0
app/FreeRTOS-8.2.3/include/timers.h


+ 240 - 0
app/FreeRTOS-8.2.3/list.c

@@ -0,0 +1,240 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+#include <stdlib.h>
+#include "FreeRTOS.h"
+#include "list.h"
+
+/*-----------------------------------------------------------
+ * PUBLIC LIST API documented in list.h
+ *----------------------------------------------------------*/
+
+void vListInitialise( List_t * const pxList )
+{
+	/* The list structure contains a list item which is used to mark the
+	end of the list.  To initialise the list the list end is inserted
+	as the only list entry. */
+	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
+
+	/* The list end value is the highest possible value in the list to
+	ensure it remains at the end of the list. */
+	pxList->xListEnd.xItemValue = portMAX_DELAY;
+
+	/* The list end next and previous pointers point to itself so we know
+	when the list is empty. */
+	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
+	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
+
+	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
+
+	/* Write known values into the list if
+	configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+	listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
+	listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
+}
+/*-----------------------------------------------------------*/
+
+void vListInitialiseItem( ListItem_t * const pxItem )
+{
+	/* Make sure the list item is not recorded as being on a list. */
+	pxItem->pvContainer = NULL;
+
+	/* Write known values into the list item if
+	configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+	listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
+	listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
+}
+/*-----------------------------------------------------------*/
+
+void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
+{
+ListItem_t * const pxIndex = pxList->pxIndex;
+
+	/* Only effective when configASSERT() is also defined, these tests may catch
+	the list data structures being overwritten in memory.  They will not catch
+	data errors caused by incorrect configuration or use of FreeRTOS. */
+	listTEST_LIST_INTEGRITY( pxList );
+	listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
+
+	/* Insert a new list item into pxList, but rather than sort the list,
+	makes the new list item the last item to be removed by a call to
+	listGET_OWNER_OF_NEXT_ENTRY(). */
+	pxNewListItem->pxNext = pxIndex;
+	pxNewListItem->pxPrevious = pxIndex->pxPrevious;
+
+	/* Only used during decision coverage testing. */
+	mtCOVERAGE_TEST_DELAY();
+
+	pxIndex->pxPrevious->pxNext = pxNewListItem;
+	pxIndex->pxPrevious = pxNewListItem;
+
+	/* Remember which list the item is in. */
+	pxNewListItem->pvContainer = ( void * ) pxList;
+
+	( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
+{
+ListItem_t *pxIterator;
+const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
+
+	/* Only effective when configASSERT() is also defined, these tests may catch
+	the list data structures being overwritten in memory.  They will not catch
+	data errors caused by incorrect configuration or use of FreeRTOS. */
+	listTEST_LIST_INTEGRITY( pxList );
+	listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
+
+	/* Insert the new list item into the list, sorted in xItemValue order.
+
+	If the list already contains a list item with the same item value then the
+	new list item should be placed after it.  This ensures that TCB's which are
+	stored in ready lists (all of which have the same xItemValue value) get a
+	share of the CPU.  However, if the xItemValue is the same as the back marker
+	the iteration loop below will not end.  Therefore the value is checked
+	first, and the algorithm slightly modified if necessary. */
+	if( xValueOfInsertion == portMAX_DELAY )
+	{
+		pxIterator = pxList->xListEnd.pxPrevious;
+	}
+	else
+	{
+		/* *** NOTE ***********************************************************
+		If you find your application is crashing here then likely causes are
+		listed below.  In addition see http://www.freertos.org/FAQHelp.html for
+		more tips, and ensure configASSERT() is defined!
+		http://www.freertos.org/a00110.html#configASSERT
+
+			1) Stack overflow -
+			   see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
+			2) Incorrect interrupt priority assignment, especially on Cortex-M
+			   parts where numerically high priority values denote low actual
+			   interrupt priorities, which can seem counter intuitive.  See
+			   http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
+			   of configMAX_SYSCALL_INTERRUPT_PRIORITY on
+			   http://www.freertos.org/a00110.html
+			3) Calling an API function from within a critical section or when
+			   the scheduler is suspended, or calling an API function that does
+			   not end in "FromISR" from an interrupt.
+			4) Using a queue or semaphore before it has been initialised or
+			   before the scheduler has been started (are interrupts firing
+			   before vTaskStartScheduler() has been called?).
+		**********************************************************************/
+
+		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
+		{
+			/* There is nothing to do here, just iterating to the wanted
+			insertion position. */
+		}
+	}
+
+	pxNewListItem->pxNext = pxIterator->pxNext;
+	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
+	pxNewListItem->pxPrevious = pxIterator;
+	pxIterator->pxNext = pxNewListItem;
+
+	/* Remember which list the item is in.  This allows fast removal of the
+	item later. */
+	pxNewListItem->pvContainer = ( void * ) pxList;
+
+	( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
+{
+/* The list item knows which list it is in.  Obtain the list from the list
+item. */
+List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
+
+	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
+	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
+
+	/* Only used during decision coverage testing. */
+	mtCOVERAGE_TEST_DELAY();
+
+	/* Make sure the index is left pointing to a valid item. */
+	if( pxList->pxIndex == pxItemToRemove )
+	{
+		pxList->pxIndex = pxItemToRemove->pxPrevious;
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	pxItemToRemove->pvContainer = NULL;
+	( pxList->uxNumberOfItems )--;
+
+	return pxList->uxNumberOfItems;
+}
+/*-----------------------------------------------------------*/
+

+ 630 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/port.c

@@ -0,0 +1,630 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM3 port.
+ *----------------------------------------------------------*/
+
+/* IAR includes. */
+#include <intrinsics.h>
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+	#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
+#endif
+
+#ifndef configSYSTICK_CLOCK_HZ
+	#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+	/* Ensure the SysTick is clocked at the same frequency as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL )
+#else
+	/* The way the SysTick is clocked is not modified in case it is not the same
+	as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 0 )
+#endif
+
+/* Constants required to manipulate the core.  Registers first... */
+#define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG	( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSPRI2_REG				( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
+/* ...then bits in the registers. */
+#define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT		( 1UL << 16UL )
+#define portNVIC_PENDSVCLEAR_BIT 			( 1UL << 27UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT		( 1UL << 25UL )
+
+#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
+#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+
+/* Constants required to check the validity of an interrupt priority. */
+#define portFIRST_USER_INTERRUPT_NUMBER		( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 )
+#define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
+#define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff )
+#define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 )
+#define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 )
+#define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL )
+#define portPRIGROUP_SHIFT					( 8UL )
+
+/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
+#define portVECTACTIVE_MASK					( 0xFFUL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR					( 0x01000000 )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER				( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+occurred while the SysTick counter is stopped during tickless idle
+calculations. */
+#define portMISSED_COUNTS_FACTOR			( 45UL )
+
+/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
+defined.  The value 255 should also ensure backward compatibility.
+FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
+#ifndef configKERNEL_INTERRUPT_PRIORITY
+	#define configKERNEL_INTERRUPT_PRIORITY 255
+#endif
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.  The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortSysTickHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+extern void vPortStartFirstTask( void );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+	 static uint8_t ucMaxSysCallPriority = 0;
+	 static uint32_t ulMaxPRIGROUPValue = 0;
+	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+{
+	/* Simulate the stack frame as it would be created by a context switch
+	interrupt. */
+	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) pxCode;	/* PC */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */
+	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
+	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
+	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+	/* A function that implements a task must not exit or attempt to return to
+	its caller as there is nothing to return to.  If a task wants to exit it
+	should instead call vTaskDelete( NULL ).
+
+	Artificially force an assert() to be triggered if configASSERT() is
+	defined, then stop here so application writers can catch the error. */
+	configASSERT( uxCriticalNesting == ~0UL );
+	portDISABLE_INTERRUPTS();
+	for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+	#if( configASSERT_DEFINED == 1 )
+	{
+		volatile uint32_t ulOriginalPriority;
+		volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+		volatile uint8_t ucMaxPriorityValue;
+
+		/* Determine the maximum priority from which ISR safe FreeRTOS API
+		functions can be called.  ISR safe functions are those that end in
+		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to
+		ensure interrupt entry is as fast and simple as possible.
+
+		Save the interrupt priority value that is about to be clobbered. */
+		ulOriginalPriority = *pucFirstUserPriorityRegister;
+
+		/* Determine the number of priority bits available.  First write to all
+		possible bits. */
+		*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
+
+		/* Read the value back to see how many bits stuck. */
+		ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+
+		/* Use the same mask on the maximum system call priority. */
+		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+		/* Calculate the maximum acceptable priority group value for the number
+		of bits read back. */
+		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
+		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+		{
+			ulMaxPRIGROUPValue--;
+			ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+		}
+
+		/* Shift the priority group value back to its position within the AIRCR
+		register. */
+		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+
+		/* Restore the clobbered interrupt priority register to its original
+		value. */
+		*pucFirstUserPriorityRegister = ulOriginalPriority;
+	}
+	#endif /* conifgASSERT_DEFINED */
+
+	/* Make PendSV and SysTick the lowest priority interrupts. */
+	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
+	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	vPortSetupTimerInterrupt();
+
+	/* Initialise the critical nesting count ready for the first task. */
+	uxCriticalNesting = 0;
+
+	/* Start the first task. */
+	vPortStartFirstTask();
+
+	/* Should not get here! */
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+	/* Not implemented in ports where there is nothing to return to.
+	Artificially force an assert. */
+	configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+	/* Set a PendSV to request a context switch. */
+	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+
+	/* Barriers are normally not required but do ensure the code is completely
+	within the specified behaviour for the architecture. */
+	__DSB();
+	__ISB();
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+	portDISABLE_INTERRUPTS();
+	uxCriticalNesting++;
+	__DSB();
+	__ISB();
+
+	/* This is not the interrupt safe version of the enter critical function so
+	assert() if it is being called from an interrupt context.  Only API
+	functions that end in "FromISR" can be used in an interrupt.  Only assert if
+	the critical nesting count is 1 to protect against recursive calls if the
+	assert function also uses a critical section. */
+	if( uxCriticalNesting == 1 )
+	{
+		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+	configASSERT( uxCriticalNesting );
+	uxCriticalNesting--;
+	if( uxCriticalNesting == 0 )
+	{
+		portENABLE_INTERRUPTS();
+	}
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
+	executes all interrupts must be unmasked.  There is therefore no need to
+	save and then restore the interrupt mask value as its value is already
+	known. */
+	( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* Increment the RTOS tick. */
+		if( xTaskIncrementTick() != pdFALSE )
+		{
+			/* A context switch is required.  Context switching is performed in
+			the PendSV interrupt.  Pend the PendSV interrupt. */
+			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TICKLESS_IDLE == 1
+
+	__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+	{
+	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+	TickType_t xModifiableIdleTime;
+
+		/* Make sure the SysTick reload value does not overflow the counter. */
+		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+		{
+			xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+		}
+
+		/* Stop the SysTick momentarily.  The time the SysTick is stopped for
+		is accounted for as best it can be, but using the tickless mode will
+		inevitably result in some tiny drift of the time maintained by the
+		kernel with respect to calendar time. */
+		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+		/* Calculate the reload value required to wait xExpectedIdleTime
+		tick periods.  -1 is used because this code will execute part way
+		through one of the tick periods. */
+		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+		if( ulReloadValue > ulStoppedTimerCompensation )
+		{
+			ulReloadValue -= ulStoppedTimerCompensation;
+		}
+
+		/* Enter a critical section but don't use the taskENTER_CRITICAL()
+		method as that will mask interrupts that should exit sleep mode. */
+		__disable_interrupt();
+
+		/* If a context switch is pending or a task is waiting for the scheduler
+		to be unsuspended then abandon the low power entry. */
+		if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+		{
+			/* Restart from whatever is left in the count register to complete
+			this tick period. */
+			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Reset the reload register to the value required for normal tick
+			periods. */
+			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+			/* Re-enable interrupts - see comments above __disable_interrupt()
+			call above. */
+			__enable_interrupt();
+		}
+		else
+		{
+			/* Set the new reload value. */
+			portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+			/* Clear the SysTick count flag and set the count value back to
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
+			set its parameter to 0 to indicate that its implementation contains
+			its own wait for interrupt or wait for event instruction, and so wfi
+			should not be executed again.  However, the original expected idle
+			time variable must remain unmodified, so a copy is taken. */
+			xModifiableIdleTime = xExpectedIdleTime;
+			configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+			if( xModifiableIdleTime > 0 )
+			{
+				__DSB();
+				__WFI();
+				__ISB();
+			}
+			configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+			/* Stop SysTick.  Again, the time the SysTick is stopped for is
+			accounted for as best it can be, but using the tickless mode will
+			inevitably result in some tiny drift of the time maintained by the
+			kernel with respect to calendar time. */
+			ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
+			portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
+
+			/* Re-enable interrupts - see comments above __disable_interrupt()
+			call above. */
+			__enable_interrupt();
+
+			if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+			{
+				uint32_t ulCalculatedLoadValue;
+
+				/* The tick interrupt has already executed, and the SysTick
+				count reloaded with ulReloadValue.  Reset the
+				portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+				period. */
+				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+				/* Don't allow a tiny value, or values that have somehow
+				underflowed because the post sleep hook did something
+				that took too long. */
+				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+				{
+					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+				}
+
+				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+				/* The tick interrupt handler will already have pended the tick
+				processing in the kernel.  As the pending tick will be
+				processed as soon as this function exits, the tick value
+				maintained by the tick is stepped forward by one less than the
+				time spent waiting. */
+				ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+			}
+			else
+			{
+				/* Something other than the tick interrupt ended the sleep.
+				Work out how long the sleep lasted rounded to complete tick
+				periods (not the ulReload value which accounted for part
+				ticks). */
+				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+				/* How many complete tick periods passed while the processor
+				was waiting? */
+				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+				/* The reload value is set to whatever fraction of a single tick
+				period remains. */
+				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+			}
+
+			/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+			again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+			value.  The critical section is used to ensure the tick interrupt
+			can only execute once in the case that the reload register is near
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+			portENTER_CRITICAL();
+			{
+				portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+				vTaskStepTick( ulCompleteTickPeriods );
+				portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+			}
+			portEXIT_CRITICAL();
+		}
+	}
+
+#endif /* #if configUSE_TICKLESS_IDLE */
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+__weak void vPortSetupTimerInterrupt( void )
+{
+	/* Calculate the constants required to configure the tick interrupt. */
+	#if configUSE_TICKLESS_IDLE == 1
+	{
+		ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+		xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+		ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+	}
+	#endif /* configUSE_TICKLESS_IDLE */
+
+	/* Configure SysTick to interrupt at the requested rate. */
+	portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+	portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+	void vPortValidateInterruptPriority( void )
+	{
+	uint32_t ulCurrentInterrupt;
+	uint8_t ucCurrentPriority;
+
+		/* Obtain the number of the currently executing interrupt. */
+		__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+		/* Is the interrupt number a user defined interrupt? */
+		if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+		{
+			/* Look up the interrupt's priority. */
+			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+			/* The following assertion will fail if a service routine (ISR) for
+			an interrupt that has been assigned a priority above
+			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+			function.  ISR safe FreeRTOS API functions must *only* be called
+			from interrupts that have been assigned a priority at or below
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Numerically low interrupt priority numbers represent logically high
+			interrupt priorities, therefore the priority of the interrupt must
+			be set to a value equal to or numerically *higher* than
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Interrupts that	use the FreeRTOS API must not be left at their
+			default priority of	zero as that is the highest possible priority,
+			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+			and	therefore also guaranteed to be invalid.
+
+			FreeRTOS maintains separate thread and ISR API functions to ensure
+			interrupt entry is as fast and simple as possible.
+
+			The following links provide detailed information:
+			http://www.freertos.org/RTOS-Cortex-M3-M4.html
+			http://www.freertos.org/FAQHelp.html */
+			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+		}
+
+		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
+		that define each interrupt's priority to be split between bits that
+		define the interrupt's pre-emption priority bits and bits that define
+		the interrupt's sub-priority.  For simplicity all bits must be defined
+		to be pre-emption priority bits.  The following assertion will fail if
+		this is not the case (if some bits represent a sub-priority).
+
+		If the application only uses CMSIS libraries for interrupt
+		configuration then the correct setting can be achieved on all Cortex-M
+		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+		scheduler.  Note however that some vendor specific peripheral libraries
+		assume a non-zero priority group setting, in which cases using a value
+		of zero will result in unpredicable behaviour. */
+		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
+	}
+
+#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 159 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/portasm.s

@@ -0,0 +1,159 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#include <FreeRTOSConfig.h>
+
+	RSEG    CODE:CODE(2)
+	thumb
+
+	EXTERN pxCurrentTCB
+	EXTERN vTaskSwitchContext
+
+	PUBLIC xPortPendSVHandler
+	PUBLIC ulPortSetInterruptMask
+	PUBLIC vPortClearInterruptMask
+	PUBLIC vPortSVCHandler
+	PUBLIC vPortStartFirstTask
+
+
+
+/*-----------------------------------------------------------*/
+
+xPortPendSVHandler:
+	mrs r0, psp
+	isb
+	ldr	r3, =pxCurrentTCB			/* Get the location of the current TCB. */
+	ldr	r2, [r3]
+
+	stmdb r0!, {r4-r11}				/* Save the remaining registers. */
+	str r0, [r2]					/* Save the new top of stack into the first member of the TCB. */
+
+	stmdb sp!, {r3, r14}
+	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r0
+	bl vTaskSwitchContext
+	mov r0, #0
+	msr basepri, r0
+	ldmia sp!, {r3, r14}
+
+	ldr r1, [r3]
+	ldr r0, [r1]					/* The first item in pxCurrentTCB is the task top of stack. */
+	ldmia r0!, {r4-r11}				/* Pop the registers. */
+	msr psp, r0
+	isb
+	bx r14
+
+
+/*-----------------------------------------------------------*/
+
+ulPortSetInterruptMask:
+	mrs r0, basepri
+	mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r1
+	bx r14
+
+/*-----------------------------------------------------------*/
+
+vPortClearInterruptMask:
+	msr basepri, r0
+	bx r14
+
+/*-----------------------------------------------------------*/
+
+vPortSVCHandler:
+	/* Get the location of the current TCB. */
+	ldr	r3, =pxCurrentTCB
+	ldr r1, [r3]
+	ldr r0, [r1]
+	/* Pop the core registers. */
+	ldmia r0!, {r4-r11}
+	msr psp, r0
+	isb
+	mov r0, #0
+	msr	basepri, r0
+	orr r14, r14, #13
+	bx r14
+
+/*-----------------------------------------------------------*/
+
+vPortStartFirstTask
+	/* Use the NVIC offset register to locate the stack. */
+	ldr r0, =0xE000ED08
+	ldr r0, [r0]
+	ldr r0, [r0]
+	/* Set the msp back to the start of the stack. */
+	msr msp, r0
+	/* Call SVC to start the first task, ensuring interrupts are enabled. */
+	cpsie i
+	cpsie f
+	dsb
+	isb
+	svc 0
+
+	END

+ 200 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM3/portmacro.h

@@ -0,0 +1,200 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR		char
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		long
+#define portSHORT		short
+#define portSTACK_TYPE	uint32_t
+#define portBASE_TYPE	long
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef uint16_t TickType_t;
+	#define portMAX_DELAY 0xffff
+#else
+	typedef uint32_t TickType_t;
+	#define portMAX_DELAY 0xffffffffUL
+
+	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+	not need to be guarded with a critical section. */
+	#define portTICK_TYPE_IS_ATOMIC 1
+#endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+extern void vPortYield( void );
+#define portNVIC_INT_CTRL_REG		( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
+#define portNVIC_PENDSVSET_BIT		( 1UL << 28UL )
+#define portYIELD()					vPortYield()
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+/* Architecture specific optimisations. */
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#endif
+
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+
+	/* Check the configuration. */
+	#if( configMAX_PRIORITIES > 32 )
+		#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
+	#endif
+
+	/* Store/clear the ready priorities in a bit map. */
+	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) )
+	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) )
+
+	/*-----------------------------------------------------------*/
+
+	#include <intrinsics.h>
+	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
+
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+extern uint32_t ulPortSetInterruptMask( void );
+extern void vPortClearInterruptMask( uint32_t ulNewMask );
+
+#define portDISABLE_INTERRUPTS()				ulPortSetInterruptMask()
+#define portENABLE_INTERRUPTS()					vPortClearInterruptMask( 0 )
+#define portENTER_CRITICAL()					vPortEnterCritical()
+#define portEXIT_CRITICAL()						vPortExitCritical()
+#define portSET_INTERRUPT_MASK_FROM_ISR()		ulPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortClearInterruptMask( x )
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+	extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
+#endif
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are
+not necessary for to use this port.  They are defined so the common demo files
+(which build with all the ports) will build. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+/*-----------------------------------------------------------*/
+
+#ifdef configASSERT
+	void vPortValidateInterruptPriority( void );
+	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() 	vPortValidateInterruptPriority()
+#endif
+
+/* portNOP() is not required by this port. */
+#define portNOP()
+
+/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
+the source code because to do so would cause other compilers to generate
+warnings. */
+#pragma diag_suppress=Pe191
+#pragma diag_suppress=Pa082
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+

+ 658 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/port.c

@@ -0,0 +1,658 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM4F port.
+ *----------------------------------------------------------*/
+
+/* Compiler includes. */
+#include <intrinsics.h>
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+#ifndef __ARMVFP__
+	#error This port can only be used when the project options are configured to enable hardware floating point support.
+#endif
+
+#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+	#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
+#endif
+
+#ifndef configSYSTICK_CLOCK_HZ
+	#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+	/* Ensure the SysTick is clocked at the same frequency as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL )
+#else
+	/* The way the SysTick is clocked is not modified in case it is not the same
+	as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 0 )
+#endif
+
+/* Constants required to manipulate the core.  Registers first... */
+#define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG	( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSPRI2_REG				( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
+/* ...then bits in the registers. */
+#define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT		( 1UL << 16UL )
+#define portNVIC_PENDSVCLEAR_BIT 			( 1UL << 27UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT		( 1UL << 25UL )
+
+/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
+r0p1 port. */
+#define portCPUID							( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
+#define portCORTEX_M7_r0p1_ID				( 0x410FC271UL )
+#define portCORTEX_M7_r0p0_ID				( 0x410FC270UL )
+
+#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
+#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+
+/* Constants required to check the validity of an interrupt priority. */
+#define portFIRST_USER_INTERRUPT_NUMBER		( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 )
+#define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
+#define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff )
+#define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 )
+#define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 )
+#define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL )
+#define portPRIGROUP_SHIFT					( 8UL )
+
+/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
+#define portVECTACTIVE_MASK					( 0xFFUL )
+
+/* Constants required to manipulate the VFP. */
+#define portFPCCR							( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
+#define portASPEN_AND_LSPEN_BITS			( 0x3UL << 30UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR					( 0x01000000 )
+#define portINITIAL_EXEC_RETURN				( 0xfffffffd )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER				( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+occurred while the SysTick counter is stopped during tickless idle
+calculations. */
+#define portMISSED_COUNTS_FACTOR			( 45UL )
+
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.  The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortSysTickHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+extern void vPortStartFirstTask( void );
+
+/*
+ * Turn the VFP on.
+ */
+extern void vPortEnableVFP( void );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+	 static uint8_t ucMaxSysCallPriority = 0;
+	 static uint32_t ulMaxPRIGROUPValue = 0;
+	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+{
+	/* Simulate the stack frame as it would be created by a context switch
+	interrupt. */
+
+	/* Offset added to account for the way the MCU uses the stack on entry/exit
+	of interrupts, and to ensure alignment. */
+	pxTopOfStack--;
+
+	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) pxCode;	/* PC */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */
+
+	/* Save code space by skipping register initialisation. */
+	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
+	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
+
+	/* A save method is being used that requires each task to maintain its
+	own exec return value. */
+	pxTopOfStack--;
+	*pxTopOfStack = portINITIAL_EXEC_RETURN;
+
+	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+	/* A function that implements a task must not exit or attempt to return to
+	its caller as there is nothing to return to.  If a task wants to exit it
+	should instead call vTaskDelete( NULL ).
+
+	Artificially force an assert() to be triggered if configASSERT() is
+	defined, then stop here so application writers can catch the error. */
+	configASSERT( uxCriticalNesting == ~0UL );
+	portDISABLE_INTERRUPTS();
+	for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+	/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
+	See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+	configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+
+	/* This port can be used on all revisions of the Cortex-M7 core other than
+	the r0p1 parts.  r0p1 parts should use the port from the
+	/source/portable/GCC/ARM_CM7/r0p1 directory. */
+	configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
+	configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
+
+	#if( configASSERT_DEFINED == 1 )
+	{
+		volatile uint32_t ulOriginalPriority;
+		volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+		volatile uint8_t ucMaxPriorityValue;
+
+		/* Determine the maximum priority from which ISR safe FreeRTOS API
+		functions can be called.  ISR safe functions are those that end in
+		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to
+		ensure interrupt entry is as fast and simple as possible.
+
+		Save the interrupt priority value that is about to be clobbered. */
+		ulOriginalPriority = *pucFirstUserPriorityRegister;
+
+		/* Determine the number of priority bits available.  First write to all
+		possible bits. */
+		*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
+
+		/* Read the value back to see how many bits stuck. */
+		ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+
+		/* Use the same mask on the maximum system call priority. */
+		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+		/* Calculate the maximum acceptable priority group value for the number
+		of bits read back. */
+		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
+		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+		{
+			ulMaxPRIGROUPValue--;
+			ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+		}
+
+		/* Shift the priority group value back to its position within the AIRCR
+		register. */
+		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+
+		/* Restore the clobbered interrupt priority register to its original
+		value. */
+		*pucFirstUserPriorityRegister = ulOriginalPriority;
+	}
+	#endif /* conifgASSERT_DEFINED */
+
+	/* Make PendSV and SysTick the lowest priority interrupts. */
+	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
+	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	vPortSetupTimerInterrupt();
+
+	/* Initialise the critical nesting count ready for the first task. */
+	uxCriticalNesting = 0;
+
+	/* Ensure the VFP is enabled - it should be anyway. */
+	vPortEnableVFP();
+
+	/* Lazy save always. */
+	*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
+
+	/* Start the first task. */
+	vPortStartFirstTask();
+
+	/* Should not get here! */
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+	/* Not implemented in ports where there is nothing to return to.
+	Artificially force an assert. */
+	configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+	portDISABLE_INTERRUPTS();
+	uxCriticalNesting++;
+
+	/* This is not the interrupt safe version of the enter critical function so
+	assert() if it is being called from an interrupt context.  Only API
+	functions that end in "FromISR" can be used in an interrupt.  Only assert if
+	the critical nesting count is 1 to protect against recursive calls if the
+	assert function also uses a critical section. */
+	if( uxCriticalNesting == 1 )
+	{
+		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+	configASSERT( uxCriticalNesting );
+	uxCriticalNesting--;
+	if( uxCriticalNesting == 0 )
+	{
+		portENABLE_INTERRUPTS();
+	}
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
+	executes all interrupts must be unmasked.  There is therefore no need to
+	save and then restore the interrupt mask value as its value is already
+	known. */
+	( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* Increment the RTOS tick. */
+		if( xTaskIncrementTick() != pdFALSE )
+		{
+			/* A context switch is required.  Context switching is performed in
+			the PendSV interrupt.  Pend the PendSV interrupt. */
+			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TICKLESS_IDLE == 1
+
+	__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+	{
+	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+	TickType_t xModifiableIdleTime;
+
+		/* Make sure the SysTick reload value does not overflow the counter. */
+		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+		{
+			xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+		}
+
+		/* Stop the SysTick momentarily.  The time the SysTick is stopped for
+		is accounted for as best it can be, but using the tickless mode will
+		inevitably result in some tiny drift of the time maintained by the
+		kernel with respect to calendar time. */
+		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+		/* Calculate the reload value required to wait xExpectedIdleTime
+		tick periods.  -1 is used because this code will execute part way
+		through one of the tick periods. */
+		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+		if( ulReloadValue > ulStoppedTimerCompensation )
+		{
+			ulReloadValue -= ulStoppedTimerCompensation;
+		}
+
+		/* Enter a critical section but don't use the taskENTER_CRITICAL()
+		method as that will mask interrupts that should exit sleep mode. */
+		__disable_interrupt();
+
+		/* If a context switch is pending or a task is waiting for the scheduler
+		to be unsuspended then abandon the low power entry. */
+		if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+		{
+			/* Restart from whatever is left in the count register to complete
+			this tick period. */
+			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Reset the reload register to the value required for normal tick
+			periods. */
+			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+			/* Re-enable interrupts - see comments above __disable_interrupt()
+			call above. */
+			__enable_interrupt();
+		}
+		else
+		{
+			/* Set the new reload value. */
+			portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+			/* Clear the SysTick count flag and set the count value back to
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
+			set its parameter to 0 to indicate that its implementation contains
+			its own wait for interrupt or wait for event instruction, and so wfi
+			should not be executed again.  However, the original expected idle
+			time variable must remain unmodified, so a copy is taken. */
+			xModifiableIdleTime = xExpectedIdleTime;
+			configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+			if( xModifiableIdleTime > 0 )
+			{
+				__DSB();
+				__WFI();
+				__ISB();
+			}
+			configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+			/* Stop SysTick.  Again, the time the SysTick is stopped for is
+			accounted for as best it can be, but using the tickless mode will
+			inevitably result in some tiny drift of the time maintained by the
+			kernel with respect to calendar time. */
+			ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
+			portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
+
+			/* Re-enable interrupts - see comments above __disable_interrupt()
+			call above. */
+			__enable_interrupt();
+
+			if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+			{
+				uint32_t ulCalculatedLoadValue;
+
+				/* The tick interrupt has already executed, and the SysTick
+				count reloaded with ulReloadValue.  Reset the
+				portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+				period. */
+				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+				/* Don't allow a tiny value, or values that have somehow
+				underflowed because the post sleep hook did something
+				that took too long. */
+				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+				{
+					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+				}
+
+				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+				/* The tick interrupt handler will already have pended the tick
+				processing in the kernel.  As the pending tick will be
+				processed as soon as this function exits, the tick value
+				maintained by the tick is stepped forward by one less than the
+				time spent waiting. */
+				ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+			}
+			else
+			{
+				/* Something other than the tick interrupt ended the sleep.
+				Work out how long the sleep lasted rounded to complete tick
+				periods (not the ulReload value which accounted for part
+				ticks). */
+				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+				/* How many complete tick periods passed while the processor
+				was waiting? */
+				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+				/* The reload value is set to whatever fraction of a single tick
+				period remains. */
+				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+			}
+
+			/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+			again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+			value.  The critical section is used to ensure the tick interrupt
+			can only execute once in the case that the reload register is near
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+			portENTER_CRITICAL();
+			{
+				portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+				vTaskStepTick( ulCompleteTickPeriods );
+				portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+			}
+			portEXIT_CRITICAL();
+		}
+	}
+
+#endif /* #if configUSE_TICKLESS_IDLE */
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+__weak void vPortSetupTimerInterrupt( void )
+{
+	/* Calculate the constants required to configure the tick interrupt. */
+	#if( configUSE_TICKLESS_IDLE == 1 )
+	{
+		ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+		xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+		ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+	}
+	#endif /* configUSE_TICKLESS_IDLE */
+
+	/* Configure SysTick to interrupt at the requested rate. */
+	portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+	portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+	void vPortValidateInterruptPriority( void )
+	{
+	uint32_t ulCurrentInterrupt;
+	uint8_t ucCurrentPriority;
+
+		/* Obtain the number of the currently executing interrupt. */
+		__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+		/* Is the interrupt number a user defined interrupt? */
+		if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+		{
+			/* Look up the interrupt's priority. */
+			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+			/* The following assertion will fail if a service routine (ISR) for
+			an interrupt that has been assigned a priority above
+			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+			function.  ISR safe FreeRTOS API functions must *only* be called
+			from interrupts that have been assigned a priority at or below
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Numerically low interrupt priority numbers represent logically high
+			interrupt priorities, therefore the priority of the interrupt must
+			be set to a value equal to or numerically *higher* than
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Interrupts that	use the FreeRTOS API must not be left at their
+			default priority of	zero as that is the highest possible priority,
+			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+			and	therefore also guaranteed to be invalid.
+
+			FreeRTOS maintains separate thread and ISR API functions to ensure
+			interrupt entry is as fast and simple as possible.
+
+			The following links provide detailed information:
+			http://www.freertos.org/RTOS-Cortex-M3-M4.html
+			http://www.freertos.org/FAQHelp.html */
+			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+		}
+
+		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
+		that define each interrupt's priority to be split between bits that
+		define the interrupt's pre-emption priority bits and bits that define
+		the interrupt's sub-priority.  For simplicity all bits must be defined
+		to be pre-emption priority bits.  The following assertion will fail if
+		this is not the case (if some bits represent a sub-priority).
+
+		If the application only uses CMSIS libraries for interrupt
+		configuration then the correct setting can be achieved on all Cortex-M
+		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+		scheduler.  Note however that some vendor specific peripheral libraries
+		assume a non-zero priority group setting, in which cases using a value
+		of zero will result in unpredicable behaviour. */
+		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
+	}
+
+#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 185 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/portasm.s

@@ -0,0 +1,185 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#include <FreeRTOSConfig.h>
+
+	RSEG    CODE:CODE(2)
+	thumb
+
+	EXTERN pxCurrentTCB
+	EXTERN vTaskSwitchContext
+
+	PUBLIC xPortPendSVHandler
+	PUBLIC vPortSVCHandler
+	PUBLIC vPortStartFirstTask
+	PUBLIC vPortEnableVFP
+
+
+/*-----------------------------------------------------------*/
+
+xPortPendSVHandler:
+	mrs r0, psp
+	isb
+	/* Get the location of the current TCB. */
+	ldr	r3, =pxCurrentTCB
+	ldr	r2, [r3]
+
+	/* Is the task using the FPU context?  If so, push high vfp registers. */
+	tst r14, #0x10
+	it eq
+	vstmdbeq r0!, {s16-s31}
+
+	/* Save the core registers. */
+	stmdb r0!, {r4-r11, r14}
+
+	/* Save the new top of stack into the first member of the TCB. */
+	str r0, [r2]
+
+	stmdb sp!, {r3}
+	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r0
+	dsb
+	isb
+	bl vTaskSwitchContext
+	mov r0, #0
+	msr basepri, r0
+	ldmia sp!, {r3}
+
+	/* The first item in pxCurrentTCB is the task top of stack. */
+	ldr r1, [r3]
+	ldr r0, [r1]
+
+	/* Pop the core registers. */
+	ldmia r0!, {r4-r11, r14}
+
+	/* Is the task using the FPU context?  If so, pop the high vfp registers
+	too. */
+	tst r14, #0x10
+	it eq
+	vldmiaeq r0!, {s16-s31}
+
+	msr psp, r0
+	isb
+	#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
+		#if WORKAROUND_PMU_CM001 == 1
+			push { r14 }
+			pop { pc }
+		#endif
+	#endif
+
+	bx r14
+
+
+/*-----------------------------------------------------------*/
+
+vPortSVCHandler:
+	/* Get the location of the current TCB. */
+	ldr	r3, =pxCurrentTCB
+	ldr r1, [r3]
+	ldr r0, [r1]
+	/* Pop the core registers. */
+	ldmia r0!, {r4-r11, r14}
+	msr psp, r0
+	isb
+	mov r0, #0
+	msr	basepri, r0
+	bx r14
+
+/*-----------------------------------------------------------*/
+
+vPortStartFirstTask
+	/* Use the NVIC offset register to locate the stack. */
+	ldr r0, =0xE000ED08
+	ldr r0, [r0]
+	ldr r0, [r0]
+	/* Set the msp back to the start of the stack. */
+	msr msp, r0
+	/* Call SVC to start the first task. */
+	cpsie i
+	cpsie f
+	dsb
+	isb
+	svc 0
+
+/*-----------------------------------------------------------*/
+
+vPortEnableVFP:
+	/* The FPU enable bits are in the CPACR. */
+	ldr.w r0, =0xE000ED88
+	ldr	r1, [r0]
+
+	/* Enable CP10 and CP11 coprocessors, then save back. */
+	orr	r1, r1, #( 0xf << 20 )
+	str r1, [r0]
+	bx	r14
+
+
+
+	END
+

+ 213 - 0
app/FreeRTOS-8.2.3/portable/IAR/ARM_CM4F/portmacro.h

@@ -0,0 +1,213 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR		char
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		long
+#define portSHORT		short
+#define portSTACK_TYPE	uint32_t
+#define portBASE_TYPE	long
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef uint16_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffff
+#else
+	typedef uint32_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+	not need to be guarded with a critical section. */
+	#define portTICK_TYPE_IS_ATOMIC 1
+#endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+#define portYIELD()											\
+{															\
+	/* Set a PendSV to request a context switch. */			\
+	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;			\
+	__DSB();												\
+	__ISB();												\
+}
+
+#define portNVIC_INT_CTRL_REG		( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
+#define portNVIC_PENDSVSET_BIT		( 1UL << 28UL )
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+
+/*-----------------------------------------------------------*/
+
+/* Architecture specific optimisations. */
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#endif
+
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+
+	/* Check the configuration. */
+	#if( configMAX_PRIORITIES > 32 )
+		#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
+	#endif
+
+	/* Store/clear the ready priorities in a bit map. */
+	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
+	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
+
+	/*-----------------------------------------------------------*/
+
+	#include <intrinsics.h>
+	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
+
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+
+#define portDISABLE_INTERRUPTS()							\
+{															\
+	__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY );	\
+	__DSB();												\
+	__ISB();												\
+}
+
+#define portENABLE_INTERRUPTS()					__set_BASEPRI( 0 )
+#define portENTER_CRITICAL()					vPortEnterCritical()
+#define portEXIT_CRITICAL()						vPortExitCritical()
+#define portSET_INTERRUPT_MASK_FROM_ISR()		__get_BASEPRI(); portDISABLE_INTERRUPTS()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	__set_BASEPRI( x )
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+	extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
+#endif
+
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are
+not necessary for to use this port.  They are defined so the common demo files
+(which build with all the ports) will build. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+/*-----------------------------------------------------------*/
+
+#ifdef configASSERT
+	void vPortValidateInterruptPriority( void );
+	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() 	vPortValidateInterruptPriority()
+#endif
+
+/* portNOP() is not required by this port. */
+#define portNOP()
+
+/*-----------------------------------------------------------*/
+
+/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
+the source code because to do so would cause other compilers to generate
+warnings. */
+#pragma diag_suppress=Pe191
+#pragma diag_suppress=Pa082
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+

+ 1 - 0
app/FreeRTOS-8.2.3/portable/Keil/See-also-the-RVDS-directory.txt

@@ -0,0 +1 @@
+Nothing to see here.

+ 174 - 0
app/FreeRTOS-8.2.3/portable/MemMang/heap_1.c

@@ -0,0 +1,174 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+/*
+ * The simplest possible implementation of pvPortMalloc().  Note that this
+ * implementation does NOT allow allocated memory to be freed again.
+ *
+ * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the
+ * memory management pages of http://www.FreeRTOS.org for more information.
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* A few bytes might be lost to byte aligning the heap start address. */
+#define configADJUSTED_HEAP_SIZE	( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
+
+/* Allocate the memory for the heap. */
+static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+static size_t xNextFreeByte = ( size_t ) 0;
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+void *pvReturn = NULL;
+static uint8_t *pucAlignedHeap = NULL;
+
+	/* Ensure that blocks are always aligned to the required number of bytes. */
+	#if portBYTE_ALIGNMENT != 1
+		if( xWantedSize & portBYTE_ALIGNMENT_MASK )
+		{
+			/* Byte alignment required. */
+			xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+		}
+	#endif
+
+	vTaskSuspendAll();
+	{
+		if( pucAlignedHeap == NULL )
+		{
+			/* Ensure the heap starts on a correctly aligned boundary. */
+			pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
+		}
+
+		/* Check there is enough room left for the allocation. */
+		if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
+			( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )	)/* Check for overflow. */
+		{
+			/* Return the next free byte then increment the index past this
+			block. */
+			pvReturn = pucAlignedHeap + xNextFreeByte;
+			xNextFreeByte += xWantedSize;
+		}
+
+		traceMALLOC( pvReturn, xWantedSize );
+	}
+	( void ) xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+	/* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c and
+	heap_4.c for alternative implementations, and the memory management pages of
+	http://www.FreeRTOS.org for more information. */
+	( void ) pv;
+
+	/* Force an assert as it is invalid to call this function. */
+	configASSERT( pv == NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortInitialiseBlocks( void )
+{
+	/* Only required when static memory is not cleared. */
+	xNextFreeByte = ( size_t ) 0;
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
+}
+
+
+

+ 303 - 0
app/FreeRTOS-8.2.3/portable/MemMang/heap_2.c

@@ -0,0 +1,303 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*
+ * A sample implementation of pvPortMalloc() and vPortFree() that permits
+ * allocated blocks to be freed, but does not combine adjacent free blocks
+ * into a single larger block (and so will fragment memory).  See heap_4.c for
+ * an equivalent that does combine adjacent blocks into single larger blocks.
+ *
+ * See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the
+ * memory management pages of http://www.FreeRTOS.org for more information.
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* A few bytes might be lost to byte aligning the heap start address. */
+#define configADJUSTED_HEAP_SIZE	( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
+
+/*
+ * Initialises the heap structures before their first use.
+ */
+static void prvHeapInit( void );
+
+/* Allocate the memory for the heap. */
+static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+
+/* Define the linked list structure.  This is used to link free blocks in order
+of their size. */
+typedef struct A_BLOCK_LINK
+{
+	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
+	size_t xBlockSize;						/*<< The size of the free block. */
+} BlockLink_t;
+
+
+static const uint16_t heapSTRUCT_SIZE	= ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
+#define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
+
+/* Create a couple of list links to mark the start and end of the list. */
+static BlockLink_t xStart, xEnd;
+
+/* Keeps track of the number of free bytes remaining, but says nothing about
+fragmentation. */
+static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
+
+/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
+
+/*
+ * Insert a block into the list of free blocks - which is ordered by size of
+ * the block.  Small blocks at the start of the list and large blocks at the end
+ * of the list.
+ */
+#define prvInsertBlockIntoFreeList( pxBlockToInsert )								\
+{																					\
+BlockLink_t *pxIterator;																\
+size_t xBlockSize;																	\
+																					\
+	xBlockSize = pxBlockToInsert->xBlockSize;										\
+																					\
+	/* Iterate through the list until a block is found that has a larger size */	\
+	/* than the block we are inserting. */											\
+	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock )	\
+	{																				\
+		/* There is nothing to do here - just iterate to the correct position. */	\
+	}																				\
+																					\
+	/* Update the list to include the block being inserted in the correct */		\
+	/* position. */																	\
+	pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;					\
+	pxIterator->pxNextFreeBlock = pxBlockToInsert;									\
+}
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
+static BaseType_t xHeapHasBeenInitialised = pdFALSE;
+void *pvReturn = NULL;
+
+	vTaskSuspendAll();
+	{
+		/* If this is the first call to malloc then the heap will require
+		initialisation to setup the list of free blocks. */
+		if( xHeapHasBeenInitialised == pdFALSE )
+		{
+			prvHeapInit();
+			xHeapHasBeenInitialised = pdTRUE;
+		}
+
+		/* The wanted size is increased so it can contain a BlockLink_t
+		structure in addition to the requested amount of bytes. */
+		if( xWantedSize > 0 )
+		{
+			xWantedSize += heapSTRUCT_SIZE;
+
+			/* Ensure that blocks are always aligned to the required number of bytes. */
+			if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 )
+			{
+				/* Byte alignment required. */
+				xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+			}
+		}
+
+		if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) )
+		{
+			/* Blocks are stored in byte order - traverse the list from the start
+			(smallest) block until one of adequate size is found. */
+			pxPreviousBlock = &xStart;
+			pxBlock = xStart.pxNextFreeBlock;
+			while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
+			{
+				pxPreviousBlock = pxBlock;
+				pxBlock = pxBlock->pxNextFreeBlock;
+			}
+
+			/* If we found the end marker then a block of adequate size was not found. */
+			if( pxBlock != &xEnd )
+			{
+				/* Return the memory space - jumping over the BlockLink_t structure
+				at its start. */
+				pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
+
+				/* This block is being returned for use so must be taken out of the
+				list of free blocks. */
+				pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
+
+				/* If the block is larger than required it can be split into two. */
+				if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
+				{
+					/* This block is to be split into two.  Create a new block
+					following the number of bytes requested. The void cast is
+					used to prevent byte alignment warnings from the compiler. */
+					pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
+
+					/* Calculate the sizes of two blocks split from the single
+					block. */
+					pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
+					pxBlock->xBlockSize = xWantedSize;
+
+					/* Insert the new block into the list of free blocks. */
+					prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
+				}
+
+				xFreeBytesRemaining -= pxBlock->xBlockSize;
+			}
+		}
+
+		traceMALLOC( pvReturn, xWantedSize );
+	}
+	( void ) xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+uint8_t *puc = ( uint8_t * ) pv;
+BlockLink_t *pxLink;
+
+	if( pv != NULL )
+	{
+		/* The memory being freed will have an BlockLink_t structure immediately
+		before it. */
+		puc -= heapSTRUCT_SIZE;
+
+		/* This unexpected casting is to keep some compilers from issuing
+		byte alignment warnings. */
+		pxLink = ( void * ) puc;
+
+		vTaskSuspendAll();
+		{
+			/* Add this block to the list of free blocks. */
+			prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
+			xFreeBytesRemaining += pxLink->xBlockSize;
+			traceFREE( pv, pxLink->xBlockSize );
+		}
+		( void ) xTaskResumeAll();
+	}
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return xFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+void vPortInitialiseBlocks( void )
+{
+	/* This just exists to keep the linker quiet. */
+}
+/*-----------------------------------------------------------*/
+
+static void prvHeapInit( void )
+{
+BlockLink_t *pxFirstFreeBlock;
+uint8_t *pucAlignedHeap;
+
+	/* Ensure the heap starts on a correctly aligned boundary. */
+	pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
+
+	/* xStart is used to hold a pointer to the first item in the list of free
+	blocks.  The void cast is used to prevent compiler warnings. */
+	xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
+	xStart.xBlockSize = ( size_t ) 0;
+
+	/* xEnd is used to mark the end of the list of free blocks. */
+	xEnd.xBlockSize = configADJUSTED_HEAP_SIZE;
+	xEnd.pxNextFreeBlock = NULL;
+
+	/* To start with there is a single free block that is sized to take up the
+	entire heap space. */
+	pxFirstFreeBlock = ( void * ) pucAlignedHeap;
+	pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE;
+	pxFirstFreeBlock->pxNextFreeBlock = &xEnd;
+}
+/*-----------------------------------------------------------*/

+ 135 - 0
app/FreeRTOS-8.2.3/portable/MemMang/heap_3.c

@@ -0,0 +1,135 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+/*
+ * Implementation of pvPortMalloc() and vPortFree() that relies on the
+ * compilers own malloc() and free() implementations.
+ *
+ * This file can only be used if the linker is configured to to generate
+ * a heap memory area.
+ *
+ * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
+ * memory management pages of http://www.FreeRTOS.org for more information.
+ */
+
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+void *pvReturn;
+
+	vTaskSuspendAll();
+	{
+		pvReturn = malloc( xWantedSize );
+		traceMALLOC( pvReturn, xWantedSize );
+	}
+	( void ) xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+	if( pv )
+	{
+		vTaskSuspendAll();
+		{
+			free( pv );
+			traceFREE( pv, 0 );
+		}
+		( void ) xTaskResumeAll();
+	}
+}
+
+
+

+ 474 - 0
app/FreeRTOS-8.2.3/portable/MemMang/heap_4.c

@@ -0,0 +1,474 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*
+ * A sample implementation of pvPortMalloc() and vPortFree() that combines
+ * (coalescences) adjacent memory blocks as they are freed, and in so doing
+ * limits memory fragmentation.
+ *
+ * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
+ * memory management pages of http://www.FreeRTOS.org for more information.
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* Block sizes must not get too small. */
+#define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( xHeapStructSize << 1 ) )
+
+/* Assumes 8bit bytes! */
+#define heapBITS_PER_BYTE		( ( size_t ) 8 )
+
+/* Allocate the memory for the heap. */
+#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
+	/* The application writer has already defined the array used for the RTOS
+	heap - probably so it can be placed in a special segment or address. */
+	extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#else
+	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#endif /* configAPPLICATION_ALLOCATED_HEAP */
+
+/* Define the linked list structure.  This is used to link free blocks in order
+of their memory address. */
+typedef struct A_BLOCK_LINK
+{
+	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
+	size_t xBlockSize;						/*<< The size of the free block. */
+} BlockLink_t;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Inserts a block of memory that is being freed into the correct position in
+ * the list of free memory blocks.  The block being freed will be merged with
+ * the block in front it and/or the block behind it if the memory blocks are
+ * adjacent to each other.
+ */
+static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
+
+/*
+ * Called automatically to setup the required heap structures the first time
+ * pvPortMalloc() is called.
+ */
+static void prvHeapInit( void );
+
+/*-----------------------------------------------------------*/
+
+/* The size of the structure placed at the beginning of each allocated memory
+block must by correctly byte aligned. */
+static const size_t xHeapStructSize	= ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
+
+/* Create a couple of list links to mark the start and end of the list. */
+static BlockLink_t xStart, *pxEnd = NULL;
+
+/* Keeps track of the number of free bytes remaining, but says nothing about
+fragmentation. */
+static size_t xFreeBytesRemaining = 0U;
+static size_t xMinimumEverFreeBytesRemaining = 0U;
+
+/* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize
+member of an BlockLink_t structure is set then the block belongs to the
+application.  When the bit is free the block is still part of the free heap
+space. */
+static size_t xBlockAllocatedBit = 0;
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
+void *pvReturn = NULL;
+
+	vTaskSuspendAll();
+	{
+		/* If this is the first call to malloc then the heap will require
+		initialisation to setup the list of free blocks. */
+		if( pxEnd == NULL )
+		{
+			prvHeapInit();
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+
+		/* Check the requested block size is not so large that the top bit is
+		set.  The top bit of the block size member of the BlockLink_t structure
+		is used to determine who owns the block - the application or the
+		kernel, so it must be free. */
+		if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
+		{
+			/* The wanted size is increased so it can contain a BlockLink_t
+			structure in addition to the requested amount of bytes. */
+			if( xWantedSize > 0 )
+			{
+				xWantedSize += xHeapStructSize;
+
+				/* Ensure that blocks are always aligned to the required number
+				of bytes. */
+				if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
+				{
+					/* Byte alignment required. */
+					xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+					configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+
+			if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
+			{
+				/* Traverse the list from the start	(lowest address) block until
+				one	of adequate size is found. */
+				pxPreviousBlock = &xStart;
+				pxBlock = xStart.pxNextFreeBlock;
+				while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
+				{
+					pxPreviousBlock = pxBlock;
+					pxBlock = pxBlock->pxNextFreeBlock;
+				}
+
+				/* If the end marker was reached then a block of adequate size
+				was	not found. */
+				if( pxBlock != pxEnd )
+				{
+					/* Return the memory space pointed to - jumping over the
+					BlockLink_t structure at its start. */
+					pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
+
+					/* This block is being returned for use so must be taken out
+					of the list of free blocks. */
+					pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
+
+					/* If the block is larger than required it can be split into
+					two. */
+					if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
+					{
+						/* This block is to be split into two.  Create a new
+						block following the number of bytes requested. The void
+						cast is used to prevent byte alignment warnings from the
+						compiler. */
+						pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
+						configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
+
+						/* Calculate the sizes of two blocks split from the
+						single block. */
+						pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
+						pxBlock->xBlockSize = xWantedSize;
+
+						/* Insert the new block into the list of free blocks. */
+						prvInsertBlockIntoFreeList( pxNewBlockLink );
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+
+					xFreeBytesRemaining -= pxBlock->xBlockSize;
+
+					if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
+					{
+						xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+
+					/* The block is being returned - it is allocated and owned
+					by the application and has no "next" block. */
+					pxBlock->xBlockSize |= xBlockAllocatedBit;
+					pxBlock->pxNextFreeBlock = NULL;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+
+		traceMALLOC( pvReturn, xWantedSize );
+	}
+	( void ) xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	#endif
+
+	configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 );
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+uint8_t *puc = ( uint8_t * ) pv;
+BlockLink_t *pxLink;
+
+	if( pv != NULL )
+	{
+		/* The memory being freed will have an BlockLink_t structure immediately
+		before it. */
+		puc -= xHeapStructSize;
+
+		/* This casting is to keep the compiler from issuing warnings. */
+		pxLink = ( void * ) puc;
+
+		/* Check the block is actually allocated. */
+		configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
+		configASSERT( pxLink->pxNextFreeBlock == NULL );
+
+		if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
+		{
+			if( pxLink->pxNextFreeBlock == NULL )
+			{
+				/* The block is being returned to the heap - it is no longer
+				allocated. */
+				pxLink->xBlockSize &= ~xBlockAllocatedBit;
+
+				vTaskSuspendAll();
+				{
+					/* Add this block to the list of free blocks. */
+					xFreeBytesRemaining += pxLink->xBlockSize;
+					traceFREE( pv, pxLink->xBlockSize );
+					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
+				}
+				( void ) xTaskResumeAll();
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return xFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetMinimumEverFreeHeapSize( void )
+{
+	return xMinimumEverFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+void vPortInitialiseBlocks( void )
+{
+	/* This just exists to keep the linker quiet. */
+}
+/*-----------------------------------------------------------*/
+
+static void prvHeapInit( void )
+{
+BlockLink_t *pxFirstFreeBlock;
+uint8_t *pucAlignedHeap;
+size_t uxAddress;
+size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
+
+	/* Ensure the heap starts on a correctly aligned boundary. */
+	uxAddress = ( size_t ) ucHeap;
+
+	if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
+	{
+		uxAddress += ( portBYTE_ALIGNMENT - 1 );
+		uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
+		xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
+	}
+
+	pucAlignedHeap = ( uint8_t * ) uxAddress;
+
+	/* xStart is used to hold a pointer to the first item in the list of free
+	blocks.  The void cast is used to prevent compiler warnings. */
+	xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
+	xStart.xBlockSize = ( size_t ) 0;
+
+	/* pxEnd is used to mark the end of the list of free blocks and is inserted
+	at the end of the heap space. */
+	uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
+	uxAddress -= xHeapStructSize;
+	uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
+	pxEnd = ( void * ) uxAddress;
+	pxEnd->xBlockSize = 0;
+	pxEnd->pxNextFreeBlock = NULL;
+
+	/* To start with there is a single free block that is sized to take up the
+	entire heap space, minus the space taken by pxEnd. */
+	pxFirstFreeBlock = ( void * ) pucAlignedHeap;
+	pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
+	pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
+
+	/* Only one block exists - and it covers the entire usable heap space. */
+	xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
+	xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
+
+	/* Work out the position of the top bit in a size_t variable. */
+	xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
+}
+/*-----------------------------------------------------------*/
+
+static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
+{
+BlockLink_t *pxIterator;
+uint8_t *puc;
+
+	/* Iterate through the list until a block is found that has a higher address
+	than the block being inserted. */
+	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
+	{
+		/* Nothing to do here, just iterate to the right position. */
+	}
+
+	/* Do the block being inserted, and the block it is being inserted after
+	make a contiguous block of memory? */
+	puc = ( uint8_t * ) pxIterator;
+	if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
+	{
+		pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
+		pxBlockToInsert = pxIterator;
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	/* Do the block being inserted, and the block it is being inserted before
+	make a contiguous block of memory? */
+	puc = ( uint8_t * ) pxBlockToInsert;
+	if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
+	{
+		if( pxIterator->pxNextFreeBlock != pxEnd )
+		{
+			/* Form one big block from the two blocks. */
+			pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
+			pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
+		}
+		else
+		{
+			pxBlockToInsert->pxNextFreeBlock = pxEnd;
+		}
+	}
+	else
+	{
+		pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
+	}
+
+	/* If the block being inserted plugged a gab, so was merged with the block
+	before and the block after, then it's pxNextFreeBlock pointer will have
+	already been set, and should not be set here as that would make it point
+	to itself. */
+	if( pxIterator != pxBlockToInsert )
+	{
+		pxIterator->pxNextFreeBlock = pxBlockToInsert;
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+}
+

+ 523 - 0
app/FreeRTOS-8.2.3/portable/MemMang/heap_5.c

@@ -0,0 +1,523 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*
+ * A sample implementation of pvPortMalloc() that allows the heap to be defined
+ * across multiple non-contigous blocks and combines (coalescences) adjacent
+ * memory blocks as they are freed.
+ *
+ * See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative
+ * implementations, and the memory management pages of http://www.FreeRTOS.org
+ * for more information.
+ *
+ * Usage notes:
+ *
+ * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc().
+ * pvPortMalloc() will be called if any task objects (tasks, queues, event
+ * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be
+ * called before any other objects are defined.
+ *
+ * vPortDefineHeapRegions() takes a single parameter.  The parameter is an array
+ * of HeapRegion_t structures.  HeapRegion_t is defined in portable.h as
+ *
+ * typedef struct HeapRegion
+ * {
+ *	uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap.
+ *	size_t xSizeInBytes;	  << Size of the block of memory.
+ * } HeapRegion_t;
+ *
+ * The array is terminated using a NULL zero sized region definition, and the
+ * memory regions defined in the array ***must*** appear in address order from
+ * low address to high address.  So the following is a valid example of how
+ * to use the function.
+ *
+ * HeapRegion_t xHeapRegions[] =
+ * {
+ * 	{ ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000
+ * 	{ ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000
+ * 	{ NULL, 0 }                << Terminates the array.
+ * };
+ *
+ * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions().
+ *
+ * Note 0x80000000 is the lower address so appears in the array first.
+ *
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* Block sizes must not get too small. */
+#define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( xHeapStructSize << 1 ) )
+
+/* Assumes 8bit bytes! */
+#define heapBITS_PER_BYTE		( ( size_t ) 8 )
+
+/* Define the linked list structure.  This is used to link free blocks in order
+of their memory address. */
+typedef struct A_BLOCK_LINK
+{
+	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
+	size_t xBlockSize;						/*<< The size of the free block. */
+} BlockLink_t;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Inserts a block of memory that is being freed into the correct position in
+ * the list of free memory blocks.  The block being freed will be merged with
+ * the block in front it and/or the block behind it if the memory blocks are
+ * adjacent to each other.
+ */
+static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
+
+/*-----------------------------------------------------------*/
+
+/* The size of the structure placed at the beginning of each allocated memory
+block must by correctly byte aligned. */
+static const size_t xHeapStructSize	= ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
+
+/* Create a couple of list links to mark the start and end of the list. */
+static BlockLink_t xStart, *pxEnd = NULL;
+
+/* Keeps track of the number of free bytes remaining, but says nothing about
+fragmentation. */
+static size_t xFreeBytesRemaining = 0U;
+static size_t xMinimumEverFreeBytesRemaining = 0U;
+
+/* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize
+member of an BlockLink_t structure is set then the block belongs to the
+application.  When the bit is free the block is still part of the free heap
+space. */
+static size_t xBlockAllocatedBit = 0;
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
+void *pvReturn = NULL;
+
+	/* The heap must be initialised before the first call to
+	prvPortMalloc(). */
+	configASSERT( pxEnd );
+
+	vTaskSuspendAll();
+	{
+		/* Check the requested block size is not so large that the top bit is
+		set.  The top bit of the block size member of the BlockLink_t structure
+		is used to determine who owns the block - the application or the
+		kernel, so it must be free. */
+		if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
+		{
+			/* The wanted size is increased so it can contain a BlockLink_t
+			structure in addition to the requested amount of bytes. */
+			if( xWantedSize > 0 )
+			{
+				xWantedSize += xHeapStructSize;
+
+				/* Ensure that blocks are always aligned to the required number
+				of bytes. */
+				if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
+				{
+					/* Byte alignment required. */
+					xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+
+			if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
+			{
+				/* Traverse the list from the start	(lowest address) block until
+				one	of adequate size is found. */
+				pxPreviousBlock = &xStart;
+				pxBlock = xStart.pxNextFreeBlock;
+				while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
+				{
+					pxPreviousBlock = pxBlock;
+					pxBlock = pxBlock->pxNextFreeBlock;
+				}
+
+				/* If the end marker was reached then a block of adequate size
+				was	not found. */
+				if( pxBlock != pxEnd )
+				{
+					/* Return the memory space pointed to - jumping over the
+					BlockLink_t structure at its start. */
+					pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
+
+					/* This block is being returned for use so must be taken out
+					of the list of free blocks. */
+					pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
+
+					/* If the block is larger than required it can be split into
+					two. */
+					if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
+					{
+						/* This block is to be split into two.  Create a new
+						block following the number of bytes requested. The void
+						cast is used to prevent byte alignment warnings from the
+						compiler. */
+						pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
+
+						/* Calculate the sizes of two blocks split from the
+						single block. */
+						pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
+						pxBlock->xBlockSize = xWantedSize;
+
+						/* Insert the new block into the list of free blocks. */
+						prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+
+					xFreeBytesRemaining -= pxBlock->xBlockSize;
+
+					if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
+					{
+						xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+
+					/* The block is being returned - it is allocated and owned
+					by the application and has no "next" block. */
+					pxBlock->xBlockSize |= xBlockAllocatedBit;
+					pxBlock->pxNextFreeBlock = NULL;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+
+		traceMALLOC( pvReturn, xWantedSize );
+	}
+	( void ) xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	#endif
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+uint8_t *puc = ( uint8_t * ) pv;
+BlockLink_t *pxLink;
+
+	if( pv != NULL )
+	{
+		/* The memory being freed will have an BlockLink_t structure immediately
+		before it. */
+		puc -= xHeapStructSize;
+
+		/* This casting is to keep the compiler from issuing warnings. */
+		pxLink = ( void * ) puc;
+
+		/* Check the block is actually allocated. */
+		configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
+		configASSERT( pxLink->pxNextFreeBlock == NULL );
+
+		if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
+		{
+			if( pxLink->pxNextFreeBlock == NULL )
+			{
+				/* The block is being returned to the heap - it is no longer
+				allocated. */
+				pxLink->xBlockSize &= ~xBlockAllocatedBit;
+
+				vTaskSuspendAll();
+				{
+					/* Add this block to the list of free blocks. */
+					xFreeBytesRemaining += pxLink->xBlockSize;
+					traceFREE( pv, pxLink->xBlockSize );
+					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
+				}
+				( void ) xTaskResumeAll();
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return xFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetMinimumEverFreeHeapSize( void )
+{
+	return xMinimumEverFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
+{
+BlockLink_t *pxIterator;
+uint8_t *puc;
+
+	/* Iterate through the list until a block is found that has a higher address
+	than the block being inserted. */
+	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
+	{
+		/* Nothing to do here, just iterate to the right position. */
+	}
+
+	/* Do the block being inserted, and the block it is being inserted after
+	make a contiguous block of memory? */
+	puc = ( uint8_t * ) pxIterator;
+	if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
+	{
+		pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
+		pxBlockToInsert = pxIterator;
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	/* Do the block being inserted, and the block it is being inserted before
+	make a contiguous block of memory? */
+	puc = ( uint8_t * ) pxBlockToInsert;
+	if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
+	{
+		if( pxIterator->pxNextFreeBlock != pxEnd )
+		{
+			/* Form one big block from the two blocks. */
+			pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
+			pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
+		}
+		else
+		{
+			pxBlockToInsert->pxNextFreeBlock = pxEnd;
+		}
+	}
+	else
+	{
+		pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
+	}
+
+	/* If the block being inserted plugged a gab, so was merged with the block
+	before and the block after, then it's pxNextFreeBlock pointer will have
+	already been set, and should not be set here as that would make it point
+	to itself. */
+	if( pxIterator != pxBlockToInsert )
+	{
+		pxIterator->pxNextFreeBlock = pxBlockToInsert;
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
+{
+BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;
+size_t xAlignedHeap;
+size_t xTotalRegionSize, xTotalHeapSize = 0;
+BaseType_t xDefinedRegions = 0;
+size_t xAddress;
+const HeapRegion_t *pxHeapRegion;
+
+	/* Can only call once! */
+	configASSERT( pxEnd == NULL );
+
+	pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
+
+	while( pxHeapRegion->xSizeInBytes > 0 )
+	{
+		xTotalRegionSize = pxHeapRegion->xSizeInBytes;
+
+		/* Ensure the heap region starts on a correctly aligned boundary. */
+		xAddress = ( size_t ) pxHeapRegion->pucStartAddress;
+		if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
+		{
+			xAddress += ( portBYTE_ALIGNMENT - 1 );
+			xAddress &= ~portBYTE_ALIGNMENT_MASK;
+
+			/* Adjust the size for the bytes lost to alignment. */
+			xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress;
+		}
+
+		xAlignedHeap = xAddress;
+
+		/* Set xStart if it has not already been set. */
+		if( xDefinedRegions == 0 )
+		{
+			/* xStart is used to hold a pointer to the first item in the list of
+			free blocks.  The void cast is used to prevent compiler warnings. */
+			xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap;
+			xStart.xBlockSize = ( size_t ) 0;
+		}
+		else
+		{
+			/* Should only get here if one region has already been added to the
+			heap. */
+			configASSERT( pxEnd != NULL );
+
+			/* Check blocks are passed in with increasing start addresses. */
+			configASSERT( xAddress > ( size_t ) pxEnd );
+		}
+
+		/* Remember the location of the end marker in the previous region, if
+		any. */
+		pxPreviousFreeBlock = pxEnd;
+
+		/* pxEnd is used to mark the end of the list of free blocks and is
+		inserted at the end of the region space. */
+		xAddress = xAlignedHeap + xTotalRegionSize;
+		xAddress -= xHeapStructSize;
+		xAddress &= ~portBYTE_ALIGNMENT_MASK;
+		pxEnd = ( BlockLink_t * ) xAddress;
+		pxEnd->xBlockSize = 0;
+		pxEnd->pxNextFreeBlock = NULL;
+
+		/* To start with there is a single free block in this region that is
+		sized to take up the entire heap region minus the space taken by the
+		free block structure. */
+		pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
+		pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion;
+		pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
+
+		/* If this is not the first region that makes up the entire heap space
+		then link the previous region to this region. */
+		if( pxPreviousFreeBlock != NULL )
+		{
+			pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
+		}
+
+		xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
+
+		/* Move onto the next HeapRegion_t structure. */
+		xDefinedRegions++;
+		pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
+	}
+
+	xMinimumEverFreeBytesRemaining = xTotalHeapSize;
+	xFreeBytesRemaining = xTotalHeapSize;
+
+	/* Check something was actually defined before it is accessed. */
+	configASSERT( xTotalHeapSize );
+
+	/* Work out the position of the top bit in a size_t variable. */
+	xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
+}
+

+ 729 - 0
app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM3/port.c

@@ -0,0 +1,729 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM3 port.
+ *----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+#ifndef configKERNEL_INTERRUPT_PRIORITY
+	#define configKERNEL_INTERRUPT_PRIORITY 255
+#endif
+
+#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+	#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
+#endif
+
+#ifndef configSYSTICK_CLOCK_HZ
+	#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+	/* Ensure the SysTick is clocked at the same frequency as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL )
+#else
+	/* The way the SysTick is clocked is not modified in case it is not the same
+	as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 0 )
+#endif
+
+/* The __weak attribute does not work as you might expect with the Keil tools
+so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
+the application writer wants to provide their own implementation of
+vPortSetupTimerInterrupt().  Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
+is defined. */
+#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
+	#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
+#endif
+
+/* Constants required to manipulate the core.  Registers first... */
+#define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG	( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSPRI2_REG				( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
+/* ...then bits in the registers. */
+#define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT		( 1UL << 16UL )
+#define portNVIC_PENDSVCLEAR_BIT 			( 1UL << 27UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT		( 1UL << 25UL )
+
+/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
+#define portVECTACTIVE_MASK					( 0xFFUL )
+
+#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
+#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+
+/* Constants required to check the validity of an interrupt priority. */
+#define portFIRST_USER_INTERRUPT_NUMBER		( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 )
+#define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
+#define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff )
+#define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 )
+#define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 )
+#define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL )
+#define portPRIGROUP_SHIFT					( 8UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR			( 0x01000000 )
+
+/* Constants used with memory barrier intrinsics. */
+#define portSY_FULL_READ_WRITE		( 15 )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER				( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+occurred while the SysTick counter is stopped during tickless idle
+calculations. */
+#define portMISSED_COUNTS_FACTOR			( 45UL )
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.  The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler( void );
+void xPortSysTickHandler( void );
+void vPortSVCHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+static void prvStartFirstTask( void );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+	 static uint8_t ucMaxSysCallPriority = 0;
+	 static uint32_t ulMaxPRIGROUPValue = 0;
+	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+{
+	/* Simulate the stack frame as it would be created by a context switch
+	interrupt. */
+	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) pxCode;	/* PC */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */
+
+	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
+	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
+	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+	/* A function that implements a task must not exit or attempt to return to
+	its caller as there is nothing to return to.  If a task wants to exit it
+	should instead call vTaskDelete( NULL ).
+
+	Artificially force an assert() to be triggered if configASSERT() is
+	defined, then stop here so application writers can catch the error. */
+	configASSERT( uxCriticalNesting == ~0UL );
+	portDISABLE_INTERRUPTS();
+	for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+__asm void vPortSVCHandler( void )
+{
+	PRESERVE8
+
+	ldr	r3, =pxCurrentTCB	/* Restore the context. */
+	ldr r1, [r3]			/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
+	ldr r0, [r1]			/* The first item in pxCurrentTCB is the task top of stack. */
+	ldmia r0!, {r4-r11}		/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
+	msr psp, r0				/* Restore the task stack pointer. */
+	isb
+	mov r0, #0
+	msr	basepri, r0
+	orr r14, #0xd
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+__asm void prvStartFirstTask( void )
+{
+	PRESERVE8
+
+	/* Use the NVIC offset register to locate the stack. */
+	ldr r0, =0xE000ED08
+	ldr r0, [r0]
+	ldr r0, [r0]
+
+	/* Set the msp back to the start of the stack. */
+	msr msp, r0
+	/* Globally enable interrupts. */
+	cpsie i
+	cpsie f
+	dsb
+	isb
+	/* Call SVC to start the first task. */
+	svc 0
+	nop
+	nop
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+	#if( configASSERT_DEFINED == 1 )
+	{
+		volatile uint32_t ulOriginalPriority;
+		volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+		volatile uint8_t ucMaxPriorityValue;
+
+		/* Determine the maximum priority from which ISR safe FreeRTOS API
+		functions can be called.  ISR safe functions are those that end in
+		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to
+		ensure interrupt entry is as fast and simple as possible.
+
+		Save the interrupt priority value that is about to be clobbered. */
+		ulOriginalPriority = *pucFirstUserPriorityRegister;
+
+		/* Determine the number of priority bits available.  First write to all
+		possible bits. */
+		*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
+
+		/* Read the value back to see how many bits stuck. */
+		ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+
+		/* Use the same mask on the maximum system call priority. */
+		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+		/* Calculate the maximum acceptable priority group value for the number
+		of bits read back. */
+		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
+		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+		{
+			ulMaxPRIGROUPValue--;
+			ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+		}
+
+		/* Shift the priority group value back to its position within the AIRCR
+		register. */
+		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+
+		/* Restore the clobbered interrupt priority register to its original
+		value. */
+		*pucFirstUserPriorityRegister = ulOriginalPriority;
+	}
+	#endif /* conifgASSERT_DEFINED */
+
+	/* Make PendSV and SysTick the lowest priority interrupts. */
+	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
+	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	vPortSetupTimerInterrupt();
+
+	/* Initialise the critical nesting count ready for the first task. */
+	uxCriticalNesting = 0;
+
+	/* Start the first task. */
+	prvStartFirstTask();
+
+	/* Should not get here! */
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+	/* Not implemented in ports where there is nothing to return to.
+	Artificially force an assert. */
+	configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+	/* Set a PendSV to request a context switch. */
+	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+
+	/* Barriers are normally not required but do ensure the code is completely
+	within the specified behaviour for the architecture. */
+	__dsb( portSY_FULL_READ_WRITE );
+	__isb( portSY_FULL_READ_WRITE );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+	portDISABLE_INTERRUPTS();
+	uxCriticalNesting++;
+	__dsb( portSY_FULL_READ_WRITE );
+	__isb( portSY_FULL_READ_WRITE );
+
+	/* This is not the interrupt safe version of the enter critical function so
+	assert() if it is being called from an interrupt context.  Only API
+	functions that end in "FromISR" can be used in an interrupt.  Only assert if
+	the critical nesting count is 1 to protect against recursive calls if the
+	assert function also uses a critical section. */
+	if( uxCriticalNesting == 1 )
+	{
+		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+	configASSERT( uxCriticalNesting );
+	uxCriticalNesting--;
+	if( uxCriticalNesting == 0 )
+	{
+		portENABLE_INTERRUPTS();
+	}
+}
+/*-----------------------------------------------------------*/
+
+__asm void xPortPendSVHandler( void )
+{
+	extern uxCriticalNesting;
+	extern pxCurrentTCB;
+	extern vTaskSwitchContext;
+
+	PRESERVE8
+
+	mrs r0, psp
+	isb
+
+	ldr	r3, =pxCurrentTCB		/* Get the location of the current TCB. */
+	ldr	r2, [r3]
+
+	stmdb r0!, {r4-r11}			/* Save the remaining registers. */
+	str r0, [r2]				/* Save the new top of stack into the first member of the TCB. */
+
+	stmdb sp!, {r3, r14}
+	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r0
+	bl vTaskSwitchContext
+	mov r0, #0
+	msr basepri, r0
+	ldmia sp!, {r3, r14}
+
+	ldr r1, [r3]
+	ldr r0, [r1]				/* The first item in pxCurrentTCB is the task top of stack. */
+	ldmia r0!, {r4-r11}			/* Pop the registers and the critical nesting count. */
+	msr psp, r0
+	isb
+	bx r14
+	nop
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
+	executes all interrupts must be unmasked.  There is therefore no need to
+	save and then restore the interrupt mask value as its value is already
+	known. */
+	( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* Increment the RTOS tick. */
+		if( xTaskIncrementTick() != pdFALSE )
+		{
+			/* A context switch is required.  Context switching is performed in
+			the PendSV interrupt.  Pend the PendSV interrupt. */
+			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TICKLESS_IDLE == 1
+
+	__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+	{
+	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+	TickType_t xModifiableIdleTime;
+
+		/* Make sure the SysTick reload value does not overflow the counter. */
+		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+		{
+			xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+		}
+
+		/* Stop the SysTick momentarily.  The time the SysTick is stopped for
+		is accounted for as best it can be, but using the tickless mode will
+		inevitably result in some tiny drift of the time maintained by the
+		kernel with respect to calendar time. */
+		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+		/* Calculate the reload value required to wait xExpectedIdleTime
+		tick periods.  -1 is used because this code will execute part way
+		through one of the tick periods. */
+		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+		if( ulReloadValue > ulStoppedTimerCompensation )
+		{
+			ulReloadValue -= ulStoppedTimerCompensation;
+		}
+
+		/* Enter a critical section but don't use the taskENTER_CRITICAL()
+		method as that will mask interrupts that should exit sleep mode. */
+		__disable_irq();
+
+		/* If a context switch is pending or a task is waiting for the scheduler
+		to be unsuspended then abandon the low power entry. */
+		if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+		{
+			/* Restart from whatever is left in the count register to complete
+			this tick period. */
+			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Reset the reload register to the value required for normal tick
+			periods. */
+			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+			/* Re-enable interrupts - see comments above __disable_irq() call
+			above. */
+			__enable_irq();
+		}
+		else
+		{
+			/* Set the new reload value. */
+			portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+			/* Clear the SysTick count flag and set the count value back to
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
+			set its parameter to 0 to indicate that its implementation contains
+			its own wait for interrupt or wait for event instruction, and so wfi
+			should not be executed again.  However, the original expected idle
+			time variable must remain unmodified, so a copy is taken. */
+			xModifiableIdleTime = xExpectedIdleTime;
+			configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+			if( xModifiableIdleTime > 0 )
+			{
+				__dsb( portSY_FULL_READ_WRITE );
+				__wfi();
+				__isb( portSY_FULL_READ_WRITE );
+			}
+			configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+			/* Stop SysTick.  Again, the time the SysTick is stopped for is
+			accounted for as best it can be, but using the tickless mode will
+			inevitably result in some tiny drift of the time maintained by the
+			kernel with respect to calendar time. */
+			ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
+			portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
+
+			/* Re-enable interrupts - see comments above __disable_irq() call
+			above. */
+			__enable_irq();
+
+			if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+			{
+				uint32_t ulCalculatedLoadValue;
+
+				/* The tick interrupt has already executed, and the SysTick
+				count reloaded with ulReloadValue.  Reset the
+				portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+				period. */
+				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+				/* Don't allow a tiny value, or values that have somehow
+				underflowed because the post sleep hook did something
+				that took too long. */
+				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+				{
+					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+				}
+
+				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+				/* The tick interrupt handler will already have pended the tick
+				processing in the kernel.  As the pending tick will be
+				processed as soon as this function exits, the tick value
+				maintained by the tick is stepped forward by one less than the
+				time spent waiting. */
+				ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+			}
+			else
+			{
+				/* Something other than the tick interrupt ended the sleep.
+				Work out how long the sleep lasted rounded to complete tick
+				periods (not the ulReload value which accounted for part
+				ticks). */
+				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+				/* How many complete tick periods passed while the processor
+				was waiting? */
+				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+				/* The reload value is set to whatever fraction of a single tick
+				period remains. */
+				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+			}
+
+			/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+			again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+			value.  The critical section is used to ensure the tick interrupt
+			can only execute once in the case that the reload register is near
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+			portENTER_CRITICAL();
+			{
+				portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+				vTaskStepTick( ulCompleteTickPeriods );
+				portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+			}
+			portEXIT_CRITICAL();
+		}
+	}
+
+#endif /* #if configUSE_TICKLESS_IDLE */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the SysTick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
+
+	void vPortSetupTimerInterrupt( void )
+	{
+		/* Calculate the constants required to configure the tick interrupt. */
+		#if configUSE_TICKLESS_IDLE == 1
+		{
+			ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+			xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+			ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+		}
+		#endif /* configUSE_TICKLESS_IDLE */
+
+		/* Configure SysTick to interrupt at the requested rate. */
+		portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+		portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+	}
+
+#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
+/*-----------------------------------------------------------*/
+
+__asm uint32_t ulPortSetInterruptMask( void )
+{
+	PRESERVE8
+
+	mrs r0, basepri
+	mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r1
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+__asm void vPortClearInterruptMask( uint32_t ulNewMask )
+{
+	PRESERVE8
+
+	msr basepri, r0
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+__asm uint32_t vPortGetIPSR( void )
+{
+	PRESERVE8
+
+	mrs r0, ipsr
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+	void vPortValidateInterruptPriority( void )
+	{
+	uint32_t ulCurrentInterrupt;
+	uint8_t ucCurrentPriority;
+
+		/* Obtain the number of the currently executing interrupt. */
+		ulCurrentInterrupt = vPortGetIPSR();
+
+		/* Is the interrupt number a user defined interrupt? */
+		if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+		{
+			/* Look up the interrupt's priority. */
+			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+			/* The following assertion will fail if a service routine (ISR) for
+			an interrupt that has been assigned a priority above
+			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+			function.  ISR safe FreeRTOS API functions must *only* be called
+			from interrupts that have been assigned a priority at or below
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Numerically low interrupt priority numbers represent logically high
+			interrupt priorities, therefore the priority of the interrupt must
+			be set to a value equal to or numerically *higher* than
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Interrupts that	use the FreeRTOS API must not be left at their
+			default priority of	zero as that is the highest possible priority,
+			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+			and	therefore also guaranteed to be invalid.
+
+			FreeRTOS maintains separate thread and ISR API functions to ensure
+			interrupt entry is as fast and simple as possible.
+
+			The following links provide detailed information:
+			http://www.freertos.org/RTOS-Cortex-M3-M4.html
+			http://www.freertos.org/FAQHelp.html */
+			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+		}
+
+		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
+		that define each interrupt's priority to be split between bits that
+		define the interrupt's pre-emption priority bits and bits that define
+		the interrupt's sub-priority.  For simplicity all bits must be defined
+		to be pre-emption priority bits.  The following assertion will fail if
+		this is not the case (if some bits represent a sub-priority).
+
+		If the application only uses CMSIS libraries for interrupt
+		configuration then the correct setting can be achieved on all Cortex-M
+		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+		scheduler.  Note however that some vendor specific peripheral libraries
+		assume a non-zero priority group setting, in which cases using a value
+		of zero will result in unpredicable behaviour. */
+		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
+	}
+
+#endif /* configASSERT_DEFINED */
+
+

+ 193 - 0
app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM3/portmacro.h

@@ -0,0 +1,193 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR		char
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		long
+#define portSHORT		short
+#define portSTACK_TYPE	uint32_t
+#define portBASE_TYPE	long
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef uint16_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffff
+#else
+	typedef uint32_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+	not need to be guarded with a critical section. */
+	#define portTICK_TYPE_IS_ATOMIC 1
+#endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+extern void vPortYield( void );
+#define portNVIC_INT_CTRL_REG		( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
+#define portNVIC_PENDSVSET_BIT		( 1UL << 28UL )
+#define portYIELD()					vPortYield()
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern uint32_t ulPortSetInterruptMask( void );
+extern void vPortClearInterruptMask( uint32_t ulNewMask );
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+
+#define portDISABLE_INTERRUPTS()				ulPortSetInterruptMask()
+#define portENABLE_INTERRUPTS()					vPortClearInterruptMask( 0 )
+#define portENTER_CRITICAL()					vPortEnterCritical()
+#define portEXIT_CRITICAL()						vPortExitCritical()
+#define portSET_INTERRUPT_MASK_FROM_ISR()		ulPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortClearInterruptMask(x)
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+	extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
+#endif
+/*-----------------------------------------------------------*/
+
+/* Port specific optimisations. */
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#endif
+
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+
+	/* Check the configuration. */
+	#if( configMAX_PRIORITIES > 32 )
+		#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
+	#endif
+
+	/* Store/clear the ready priorities in a bit map. */
+	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
+	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
+
+	/*-----------------------------------------------------------*/
+
+	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
+
+#endif /* taskRECORD_READY_PRIORITY */
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are
+not necessary for to use this port.  They are defined so the common demo files
+(which build with all the ports) will build. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+/*-----------------------------------------------------------*/
+
+#ifdef configASSERT
+	void vPortValidateInterruptPriority( void );
+	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() 	vPortValidateInterruptPriority()
+#endif
+
+/* portNOP() is not required by this port. */
+#define portNOP()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+

+ 782 - 0
app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM4F/port.c

@@ -0,0 +1,782 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM4F port.
+ *----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+#ifndef __TARGET_FPU_VFP
+	#error This port can only be used when the project options are configured to enable hardware floating point support.
+#endif
+
+#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+	#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
+#endif
+
+#ifndef configSYSTICK_CLOCK_HZ
+	#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+	/* Ensure the SysTick is clocked at the same frequency as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL )
+#else
+	/* The way the SysTick is clocked is not modified in case it is not the same
+	as the core. */
+	#define portNVIC_SYSTICK_CLK_BIT	( 0 )
+#endif
+
+/* The __weak attribute does not work as you might expect with the Keil tools
+so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
+the application writer wants to provide their own implementation of
+vPortSetupTimerInterrupt().  Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
+is defined. */
+#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
+	#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
+#endif
+
+/* Constants required to manipulate the core.  Registers first... */
+#define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG	( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSPRI2_REG				( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
+/* ...then bits in the registers. */
+#define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT		( 1UL << 16UL )
+#define portNVIC_PENDSVCLEAR_BIT 			( 1UL << 27UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT		( 1UL << 25UL )
+
+/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
+r0p1 port. */
+#define portCPUID							( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
+#define portCORTEX_M7_r0p1_ID				( 0x410FC271UL )
+#define portCORTEX_M7_r0p0_ID				( 0x410FC270UL )
+
+#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
+#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+
+/* Constants required to check the validity of an interrupt priority. */
+#define portFIRST_USER_INTERRUPT_NUMBER		( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 	( 0xE000E3F0 )
+#define portAIRCR_REG						( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
+#define portMAX_8_BIT_VALUE					( ( uint8_t ) 0xff )
+#define portTOP_BIT_OF_BYTE					( ( uint8_t ) 0x80 )
+#define portMAX_PRIGROUP_BITS				( ( uint8_t ) 7 )
+#define portPRIORITY_GROUP_MASK				( 0x07UL << 8UL )
+#define portPRIGROUP_SHIFT					( 8UL )
+
+/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
+#define portVECTACTIVE_MASK					( 0xFFUL )
+
+/* Constants required to manipulate the VFP. */
+#define portFPCCR					( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
+#define portASPEN_AND_LSPEN_BITS	( 0x3UL << 30UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR			( 0x01000000 )
+#define portINITIAL_EXEC_RETURN		( 0xfffffffd )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER				( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+occurred while the SysTick counter is stopped during tickless idle
+calculations. */
+#define portMISSED_COUNTS_FACTOR			( 45UL )
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.  The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler( void );
+void xPortSysTickHandler( void );
+void vPortSVCHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+static void prvStartFirstTask( void );
+
+/*
+ * Functions defined in portasm.s to enable the VFP.
+ */
+static void prvEnableVFP( void );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+	static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+	 static uint8_t ucMaxSysCallPriority = 0;
+	 static uint32_t ulMaxPRIGROUPValue = 0;
+	 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+{
+	/* Simulate the stack frame as it would be created by a context switch
+	interrupt. */
+
+	/* Offset added to account for the way the MCU uses the stack on entry/exit
+	of interrupts, and to ensure alignment. */
+	pxTopOfStack--;
+
+	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) pxCode;	/* PC */
+	pxTopOfStack--;
+	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */
+
+	/* Save code space by skipping register initialisation. */
+	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
+	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
+
+	/* A save method is being used that requires each task to maintain its
+	own exec return value. */
+	pxTopOfStack--;
+	*pxTopOfStack = portINITIAL_EXEC_RETURN;
+
+	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+	/* A function that implements a task must not exit or attempt to return to
+	its caller as there is nothing to return to.  If a task wants to exit it
+	should instead call vTaskDelete( NULL ).
+
+	Artificially force an assert() to be triggered if configASSERT() is
+	defined, then stop here so application writers can catch the error. */
+	configASSERT( uxCriticalNesting == ~0UL );
+	portDISABLE_INTERRUPTS();
+	for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+__asm void vPortSVCHandler( void )
+{
+	PRESERVE8
+
+	/* Get the location of the current TCB. */
+	ldr	r3, =pxCurrentTCB
+	ldr r1, [r3]
+	ldr r0, [r1]
+	/* Pop the core registers. */
+	ldmia r0!, {r4-r11, r14}
+	msr psp, r0
+	isb
+	mov r0, #0
+	msr	basepri, r0
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+__asm void prvStartFirstTask( void )
+{
+	PRESERVE8
+
+	/* Use the NVIC offset register to locate the stack. */
+	ldr r0, =0xE000ED08
+	ldr r0, [r0]
+	ldr r0, [r0]
+	/* Set the msp back to the start of the stack. */
+	msr msp, r0
+	/* Globally enable interrupts. */
+	cpsie i
+	cpsie f
+	dsb
+	isb
+	/* Call SVC to start the first task. */
+	svc 0
+	nop
+	nop
+}
+/*-----------------------------------------------------------*/
+
+__asm void prvEnableVFP( void )
+{
+	PRESERVE8
+
+	/* The FPU enable bits are in the CPACR. */
+	ldr.w r0, =0xE000ED88
+	ldr	r1, [r0]
+
+	/* Enable CP10 and CP11 coprocessors, then save back. */
+	orr	r1, r1, #( 0xf << 20 )
+	str r1, [r0]
+	bx	r14
+	nop
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+	/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
+	See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+	configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+
+	/* This port can be used on all revisions of the Cortex-M7 core other than
+	the r0p1 parts.  r0p1 parts should use the port from the
+	/source/portable/GCC/ARM_CM7/r0p1 directory. */
+	configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
+	configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
+
+	#if( configASSERT_DEFINED == 1 )
+	{
+		volatile uint32_t ulOriginalPriority;
+		volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+		volatile uint8_t ucMaxPriorityValue;
+
+		/* Determine the maximum priority from which ISR safe FreeRTOS API
+		functions can be called.  ISR safe functions are those that end in
+		"FromISR".  FreeRTOS maintains separate thread and ISR API functions to
+		ensure interrupt entry is as fast and simple as possible.
+
+		Save the interrupt priority value that is about to be clobbered. */
+		ulOriginalPriority = *pucFirstUserPriorityRegister;
+
+		/* Determine the number of priority bits available.  First write to all
+		possible bits. */
+		*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
+
+		/* Read the value back to see how many bits stuck. */
+		ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+
+		/* The kernel interrupt priority should be set to the lowest
+		priority. */
+		configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );
+
+		/* Use the same mask on the maximum system call priority. */
+		ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+		/* Calculate the maximum acceptable priority group value for the number
+		of bits read back. */
+		ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
+		while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+		{
+			ulMaxPRIGROUPValue--;
+			ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+		}
+
+		/* Shift the priority group value back to its position within the AIRCR
+		register. */
+		ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+		ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+
+		/* Restore the clobbered interrupt priority register to its original
+		value. */
+		*pucFirstUserPriorityRegister = ulOriginalPriority;
+	}
+	#endif /* conifgASSERT_DEFINED */
+
+	/* Make PendSV and SysTick the lowest priority interrupts. */
+	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
+	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	vPortSetupTimerInterrupt();
+
+	/* Initialise the critical nesting count ready for the first task. */
+	uxCriticalNesting = 0;
+
+	/* Ensure the VFP is enabled - it should be anyway. */
+	prvEnableVFP();
+
+	/* Lazy save always. */
+	*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
+
+	/* Start the first task. */
+	prvStartFirstTask();
+
+	/* Should not get here! */
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+	/* Not implemented in ports where there is nothing to return to.
+	Artificially force an assert. */
+	configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+	portDISABLE_INTERRUPTS();
+	uxCriticalNesting++;
+
+	/* This is not the interrupt safe version of the enter critical function so
+	assert() if it is being called from an interrupt context.  Only API
+	functions that end in "FromISR" can be used in an interrupt.  Only assert if
+	the critical nesting count is 1 to protect against recursive calls if the
+	assert function also uses a critical section. */
+	if( uxCriticalNesting == 1 )
+	{
+		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+	configASSERT( uxCriticalNesting );
+	uxCriticalNesting--;
+	if( uxCriticalNesting == 0 )
+	{
+		portENABLE_INTERRUPTS();
+	}
+}
+/*-----------------------------------------------------------*/
+
+__asm void xPortPendSVHandler( void )
+{
+	extern uxCriticalNesting;
+	extern pxCurrentTCB;
+	extern vTaskSwitchContext;
+
+	PRESERVE8
+
+	mrs r0, psp
+	isb
+	/* Get the location of the current TCB. */
+	ldr	r3, =pxCurrentTCB
+	ldr	r2, [r3]
+
+	/* Is the task using the FPU context?  If so, push high vfp registers. */
+	tst r14, #0x10
+	it eq
+	vstmdbeq r0!, {s16-s31}
+
+	/* Save the core registers. */
+	stmdb r0!, {r4-r11, r14}
+
+	/* Save the new top of stack into the first member of the TCB. */
+	str r0, [r2]
+
+	stmdb sp!, {r3}
+	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
+	msr basepri, r0
+	dsb
+	isb
+	bl vTaskSwitchContext
+	mov r0, #0
+	msr basepri, r0
+	ldmia sp!, {r3}
+
+	/* The first item in pxCurrentTCB is the task top of stack. */
+	ldr r1, [r3]
+	ldr r0, [r1]
+
+	/* Pop the core registers. */
+	ldmia r0!, {r4-r11, r14}
+
+	/* Is the task using the FPU context?  If so, pop the high vfp registers
+	too. */
+	tst r14, #0x10
+	it eq
+	vldmiaeq r0!, {s16-s31}
+
+	msr psp, r0
+	isb
+	#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
+		#if WORKAROUND_PMU_CM001 == 1
+			push { r14 }
+			pop { pc }
+			nop
+		#endif
+	#endif
+
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
+	executes all interrupts must be unmasked.  There is therefore no need to
+	save and then restore the interrupt mask value as its value is already
+	known. */
+	( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* Increment the RTOS tick. */
+		if( xTaskIncrementTick() != pdFALSE )
+		{
+			/* A context switch is required.  Context switching is performed in
+			the PendSV interrupt.  Pend the PendSV interrupt. */
+			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TICKLESS_IDLE == 1
+
+	__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+	{
+	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+	TickType_t xModifiableIdleTime;
+
+		/* Make sure the SysTick reload value does not overflow the counter. */
+		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+		{
+			xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+		}
+
+		/* Stop the SysTick momentarily.  The time the SysTick is stopped for
+		is accounted for as best it can be, but using the tickless mode will
+		inevitably result in some tiny drift of the time maintained by the
+		kernel with respect to calendar time. */
+		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+		/* Calculate the reload value required to wait xExpectedIdleTime
+		tick periods.  -1 is used because this code will execute part way
+		through one of the tick periods. */
+		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+		if( ulReloadValue > ulStoppedTimerCompensation )
+		{
+			ulReloadValue -= ulStoppedTimerCompensation;
+		}
+
+		/* Enter a critical section but don't use the taskENTER_CRITICAL()
+		method as that will mask interrupts that should exit sleep mode. */
+		__disable_irq();
+
+		/* If a context switch is pending or a task is waiting for the scheduler
+		to be unsuspended then abandon the low power entry. */
+		if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+		{
+			/* Restart from whatever is left in the count register to complete
+			this tick period. */
+			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Reset the reload register to the value required for normal tick
+			periods. */
+			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+			/* Re-enable interrupts - see comments above __disable_irq() call
+			above. */
+			__enable_irq();
+		}
+		else
+		{
+			/* Set the new reload value. */
+			portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+			/* Clear the SysTick count flag and set the count value back to
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+			/* Restart SysTick. */
+			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+			/* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
+			set its parameter to 0 to indicate that its implementation contains
+			its own wait for interrupt or wait for event instruction, and so wfi
+			should not be executed again.  However, the original expected idle
+			time variable must remain unmodified, so a copy is taken. */
+			xModifiableIdleTime = xExpectedIdleTime;
+			configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+			if( xModifiableIdleTime > 0 )
+			{
+				__dsb( portSY_FULL_READ_WRITE );
+				__wfi();
+				__isb( portSY_FULL_READ_WRITE );
+			}
+			configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+			/* Stop SysTick.  Again, the time the SysTick is stopped for is
+			accounted for as best it can be, but using the tickless mode will
+			inevitably result in some tiny drift of the time maintained by the
+			kernel with respect to calendar time. */
+			ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
+			portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
+
+			/* Re-enable interrupts - see comments above __disable_irq() call
+			above. */
+			__enable_irq();
+
+			if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+			{
+				uint32_t ulCalculatedLoadValue;
+
+				/* The tick interrupt has already executed, and the SysTick
+				count reloaded with ulReloadValue.  Reset the
+				portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+				period. */
+				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+				/* Don't allow a tiny value, or values that have somehow
+				underflowed because the post sleep hook did something
+				that took too long. */
+				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+				{
+					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+				}
+
+				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+				/* The tick interrupt handler will already have pended the tick
+				processing in the kernel.  As the pending tick will be
+				processed as soon as this function exits, the tick value
+				maintained by the tick is stepped forward by one less than the
+				time spent waiting. */
+				ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+			}
+			else
+			{
+				/* Something other than the tick interrupt ended the sleep.
+				Work out how long the sleep lasted rounded to complete tick
+				periods (not the ulReload value which accounted for part
+				ticks). */
+				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+				/* How many complete tick periods passed while the processor
+				was waiting? */
+				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+				/* The reload value is set to whatever fraction of a single tick
+				period remains. */
+				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+			}
+
+			/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+			again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+			value.  The critical section is used to ensure the tick interrupt
+			can only execute once in the case that the reload register is near
+			zero. */
+			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+			portENTER_CRITICAL();
+			{
+				portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+				vTaskStepTick( ulCompleteTickPeriods );
+				portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+			}
+			portEXIT_CRITICAL();
+		}
+	}
+
+#endif /* #if configUSE_TICKLESS_IDLE */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the SysTick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
+
+	void vPortSetupTimerInterrupt( void )
+	{
+		/* Calculate the constants required to configure the tick interrupt. */
+		#if configUSE_TICKLESS_IDLE == 1
+		{
+			ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+			xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+			ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+		}
+		#endif /* configUSE_TICKLESS_IDLE */
+
+		/* Configure SysTick to interrupt at the requested rate. */
+		portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+		portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+	}
+
+#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
+/*-----------------------------------------------------------*/
+
+__asm uint32_t vPortGetIPSR( void )
+{
+	PRESERVE8
+
+	mrs r0, ipsr
+	bx r14
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+	void vPortValidateInterruptPriority( void )
+	{
+	uint32_t ulCurrentInterrupt;
+	uint8_t ucCurrentPriority;
+
+		/* Obtain the number of the currently executing interrupt. */
+		ulCurrentInterrupt = vPortGetIPSR();
+
+		/* Is the interrupt number a user defined interrupt? */
+		if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+		{
+			/* Look up the interrupt's priority. */
+			ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+			/* The following assertion will fail if a service routine (ISR) for
+			an interrupt that has been assigned a priority above
+			configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+			function.  ISR safe FreeRTOS API functions must *only* be called
+			from interrupts that have been assigned a priority at or below
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Numerically low interrupt priority numbers represent logically high
+			interrupt priorities, therefore the priority of the interrupt must
+			be set to a value equal to or numerically *higher* than
+			configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+			Interrupts that	use the FreeRTOS API must not be left at their
+			default priority of	zero as that is the highest possible priority,
+			which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+			and	therefore also guaranteed to be invalid.
+
+			FreeRTOS maintains separate thread and ISR API functions to ensure
+			interrupt entry is as fast and simple as possible.
+
+			The following links provide detailed information:
+			http://www.freertos.org/RTOS-Cortex-M3-M4.html
+			http://www.freertos.org/FAQHelp.html */
+			configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+		}
+
+		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
+		that define each interrupt's priority to be split between bits that
+		define the interrupt's pre-emption priority bits and bits that define
+		the interrupt's sub-priority.  For simplicity all bits must be defined
+		to be pre-emption priority bits.  The following assertion will fail if
+		this is not the case (if some bits represent a sub-priority).
+
+		If the application only uses CMSIS libraries for interrupt
+		configuration then the correct setting can be achieved on all Cortex-M
+		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+		scheduler.  Note however that some vendor specific peripheral libraries
+		assume a non-zero priority group setting, in which cases using a value
+		of zero will result in unpredicable behaviour. */
+		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
+	}
+
+#endif /* configASSERT_DEFINED */
+
+

+ 256 - 0
app/FreeRTOS-8.2.3/portable/RVDS/ARM_CM4F/portmacro.h

@@ -0,0 +1,256 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR		char
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		long
+#define portSHORT		short
+#define portSTACK_TYPE	uint32_t
+#define portBASE_TYPE	long
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef uint16_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffff
+#else
+	typedef uint32_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+	not need to be guarded with a critical section. */
+	#define portTICK_TYPE_IS_ATOMIC 1
+#endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+
+/* Constants used with memory barrier intrinsics. */
+#define portSY_FULL_READ_WRITE		( 15 )
+
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+#define portYIELD()																\
+{																				\
+	/* Set a PendSV to request a context switch. */								\
+	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;								\
+																				\
+	/* Barriers are normally not required but do ensure the code is completely	\
+	within the specified behaviour for the architecture. */						\
+	__dsb( portSY_FULL_READ_WRITE );											\
+	__isb( portSY_FULL_READ_WRITE );											\
+}
+/*-----------------------------------------------------------*/
+
+#define portNVIC_INT_CTRL_REG		( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
+#define portNVIC_PENDSVSET_BIT		( 1UL << 28UL )
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+
+#define portDISABLE_INTERRUPTS()				vPortRaiseBASEPRI()
+#define portENABLE_INTERRUPTS()					vPortSetBASEPRI( 0 )
+#define portENTER_CRITICAL()					vPortEnterCritical()
+#define portEXIT_CRITICAL()						vPortExitCritical()
+#define portSET_INTERRUPT_MASK_FROM_ISR()		ulPortRaiseBASEPRI()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortSetBASEPRI(x)
+
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+	extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
+#endif
+/*-----------------------------------------------------------*/
+
+/* Port specific optimisations. */
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#endif
+
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+
+	/* Check the configuration. */
+	#if( configMAX_PRIORITIES > 32 )
+		#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
+	#endif
+
+	/* Store/clear the ready priorities in a bit map. */
+	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
+	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
+
+	/*-----------------------------------------------------------*/
+
+	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
+
+#endif /* taskRECORD_READY_PRIORITY */
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are
+not necessary for to use this port.  They are defined so the common demo files
+(which build with all the ports) will build. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+/*-----------------------------------------------------------*/
+
+#ifdef configASSERT
+	void vPortValidateInterruptPriority( void );
+	#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() 	vPortValidateInterruptPriority()
+#endif
+
+/* portNOP() is not required by this port. */
+#define portNOP()
+
+#ifndef portFORCE_INLINE
+	#define portFORCE_INLINE __forceinline
+#endif
+
+/*-----------------------------------------------------------*/
+
+static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
+{
+	__asm
+	{
+		/* Barrier instructions are not used as this function is only used to
+		lower the BASEPRI value. */
+		msr basepri, ulBASEPRI
+	}
+}
+/*-----------------------------------------------------------*/
+
+static portFORCE_INLINE void vPortRaiseBASEPRI( void )
+{
+uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+	__asm
+	{
+		/* Set BASEPRI to the max syscall priority to effect a critical
+		section. */
+		msr basepri, ulNewBASEPRI
+		dsb
+		isb
+	}
+}
+/*-----------------------------------------------------------*/
+
+static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
+{
+uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+	__asm
+	{
+		/* Set BASEPRI to the max syscall priority to effect a critical
+		section. */
+		mrs ulReturn, basepri
+		msr basepri, ulNewBASEPRI
+		dsb
+		isb
+	}
+
+	return ulReturn;
+}
+/*-----------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+

+ 19 - 0
app/FreeRTOS-8.2.3/portable/readme.txt

@@ -0,0 +1,19 @@
+Each real time kernel port consists of three files that contain the core kernel
+components and are common to every port, and one or more files that are 
+specific to a particular microcontroller and/or compiler.
+
+
++ The FreeRTOS/Source/Portable/MemMang directory contains the three sample 
+memory allocators as described on the http://www.FreeRTOS.org WEB site.
+
++ The other directories each contain files specific to a particular 
+microcontroller or compiler.
+
+
+
+For example, if you are interested in the GCC port for the ATMega323 
+microcontroller then the port specific files are contained in
+FreeRTOS/Source/Portable/GCC/ATMega323 directory.  If this is the only
+port you are interested in then all the other directories can be
+ignored.
+

File diff suppressed because it is too large
+ 2608 - 0
app/FreeRTOS-8.2.3/queue.c


File diff suppressed because it is too large
+ 4477 - 0
app/FreeRTOS-8.2.3/tasks.c


+ 929 - 0
app/FreeRTOS-8.2.3/timers.c

@@ -0,0 +1,929 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/* Standard includes. */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "timers.h"
+
+#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
+	#error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
+#endif
+
+/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
+MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
+header files above, but not in this file, in order to generate the correct
+privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
+
+
+/* This entire source file will be skipped if the application is not configured
+to include software timer functionality.  This #if is closed at the very bottom
+of this file.  If you want to include software timer functionality then ensure
+configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
+#if ( configUSE_TIMERS == 1 )
+
+/* Misc definitions. */
+#define tmrNO_DELAY		( TickType_t ) 0U
+
+/* The definition of the timers themselves. */
+typedef struct tmrTimerControl
+{
+	const char				*pcTimerName;		/*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+	ListItem_t				xTimerListItem;		/*<< Standard linked list item as used by all kernel features for event management. */
+	TickType_t				xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
+	UBaseType_t				uxAutoReload;		/*<< Set to pdTRUE if the timer should be automatically restarted once expired.  Set to pdFALSE if the timer is, in effect, a one-shot timer. */
+	void 					*pvTimerID;			/*<< An ID to identify the timer.  This allows the timer to be identified when the same callback is used for multiple timers. */
+	TimerCallbackFunction_t	pxCallbackFunction;	/*<< The function that will be called when the timer expires. */
+	#if( configUSE_TRACE_FACILITY == 1 )
+		UBaseType_t			uxTimerNumber;		/*<< An ID assigned by trace tools such as FreeRTOS+Trace */
+	#endif
+} xTIMER;
+
+/* The old xTIMER name is maintained above then typedefed to the new Timer_t
+name below to enable the use of older kernel aware debuggers. */
+typedef xTIMER Timer_t;
+
+/* The definition of messages that can be sent and received on the timer queue.
+Two types of message can be queued - messages that manipulate a software timer,
+and messages that request the execution of a non-timer related callback.  The
+two message types are defined in two separate structures, xTimerParametersType
+and xCallbackParametersType respectively. */
+typedef struct tmrTimerParameters
+{
+	TickType_t			xMessageValue;		/*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
+	Timer_t *			pxTimer;			/*<< The timer to which the command will be applied. */
+} TimerParameter_t;
+
+
+typedef struct tmrCallbackParameters
+{
+	PendedFunction_t	pxCallbackFunction;	/* << The callback function to execute. */
+	void *pvParameter1;						/* << The value that will be used as the callback functions first parameter. */
+	uint32_t ulParameter2;					/* << The value that will be used as the callback functions second parameter. */
+} CallbackParameters_t;
+
+/* The structure that contains the two message types, along with an identifier
+that is used to determine which message type is valid. */
+typedef struct tmrTimerQueueMessage
+{
+	BaseType_t			xMessageID;			/*<< The command being sent to the timer service task. */
+	union
+	{
+		TimerParameter_t xTimerParameters;
+
+		/* Don't include xCallbackParameters if it is not going to be used as
+		it makes the structure (and therefore the timer queue) larger. */
+		#if ( INCLUDE_xTimerPendFunctionCall == 1 )
+			CallbackParameters_t xCallbackParameters;
+		#endif /* INCLUDE_xTimerPendFunctionCall */
+	} u;
+} DaemonTaskMessage_t;
+
+/*lint -e956 A manual analysis and inspection has been used to determine which
+static variables must be declared volatile. */
+
+/* The list in which active timers are stored.  Timers are referenced in expire
+time order, with the nearest expiry time at the front of the list.  Only the
+timer service task is allowed to access these lists. */
+PRIVILEGED_DATA static List_t xActiveTimerList1;
+PRIVILEGED_DATA static List_t xActiveTimerList2;
+PRIVILEGED_DATA static List_t *pxCurrentTimerList;
+PRIVILEGED_DATA static List_t *pxOverflowTimerList;
+
+/* A queue that is used to send commands to the timer service task. */
+PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
+
+#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+
+	PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
+
+#endif
+
+/*lint +e956 */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Initialise the infrastructure used by the timer service task if it has not
+ * been initialised already.
+ */
+static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The timer service task (daemon).  Timer functionality is controlled by this
+ * task.  Other tasks communicate with the timer service task using the
+ * xTimerQueue queue.
+ */
+static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called by the timer service task to interpret and process a command it
+ * received on the timer queue.
+ */
+static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
+ * depending on if the expire time causes a timer counter overflow.
+ */
+static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
+
+/*
+ * An active timer has reached its expire time.  Reload the timer if it is an
+ * auto reload timer, then call its callback.
+ */
+static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
+
+/*
+ * The tick count has overflowed.  Switch the timer lists after ensuring the
+ * current timer list does not still reference some timers.
+ */
+static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
+ * if a tick count overflow occurred since prvSampleTimeNow() was last called.
+ */
+static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;
+
+/*
+ * If the timer list contains any active timers then return the expire time of
+ * the timer that will expire first and set *pxListWasEmpty to false.  If the
+ * timer list does not contain any timers then return 0 and set *pxListWasEmpty
+ * to pdTRUE.
+ */
+static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;
+
+/*
+ * If a timer has expired, process it.  Otherwise, block the timer service task
+ * until either a timer does expire or a command is received.
+ */
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------*/
+
+BaseType_t xTimerCreateTimerTask( void )
+{
+BaseType_t xReturn = pdFAIL;
+
+	/* This function is called when the scheduler is started if
+	configUSE_TIMERS is set to 1.  Check that the infrastructure used by the
+	timer service task has been created/initialised.  If timers have already
+	been created then the initialisation will already have been performed. */
+	prvCheckForValidListAndQueue();
+
+	if( xTimerQueue != NULL )
+	{
+		#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+		{
+			/* Create the timer task, storing its handle in xTimerTaskHandle so
+			it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
+			xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
+		}
+		#else
+		{
+			/* Create the timer task without storing its handle. */
+			xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
+		}
+		#endif
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	configASSERT( xReturn );
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
+Timer_t *pxNewTimer;
+
+	/* Allocate the timer structure. */
+	if( xTimerPeriodInTicks == ( TickType_t ) 0U )
+	{
+		pxNewTimer = NULL;
+	}
+	else
+	{
+		pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
+		if( pxNewTimer != NULL )
+		{
+			/* Ensure the infrastructure used by the timer service task has been
+			created/initialised. */
+			prvCheckForValidListAndQueue();
+
+			/* Initialise the timer structure members using the function parameters. */
+			pxNewTimer->pcTimerName = pcTimerName;
+			pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
+			pxNewTimer->uxAutoReload = uxAutoReload;
+			pxNewTimer->pvTimerID = pvTimerID;
+			pxNewTimer->pxCallbackFunction = pxCallbackFunction;
+			vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
+
+			traceTIMER_CREATE( pxNewTimer );
+		}
+		else
+		{
+			traceTIMER_CREATE_FAILED();
+		}
+	}
+
+	/* 0 is not a valid value for xTimerPeriodInTicks. */
+	configASSERT( ( xTimerPeriodInTicks > 0 ) );
+
+	return ( TimerHandle_t ) pxNewTimer;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
+{
+BaseType_t xReturn = pdFAIL;
+DaemonTaskMessage_t xMessage;
+
+	configASSERT( xTimer );
+
+	/* Send a message to the timer service task to perform a particular action
+	on a particular timer definition. */
+	if( xTimerQueue != NULL )
+	{
+		/* Send a command to the timer service task to start the xTimer timer. */
+		xMessage.xMessageID = xCommandID;
+		xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
+		xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
+
+		if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
+		{
+			if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
+			{
+				xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
+			}
+			else
+			{
+				xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );
+			}
+		}
+		else
+		{
+			xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
+		}
+
+		traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+
+	TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
+	{
+		/* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
+		started, then xTimerTaskHandle will be NULL. */
+		configASSERT( ( xTimerTaskHandle != NULL ) );
+		return xTimerTaskHandle;
+	}
+
+#endif
+/*-----------------------------------------------------------*/
+
+const char * pcTimerGetTimerName( TimerHandle_t xTimer )
+{
+Timer_t *pxTimer = ( Timer_t * ) xTimer;
+
+	configASSERT( xTimer );
+	return pxTimer->pcTimerName;
+}
+/*-----------------------------------------------------------*/
+
+static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
+{
+BaseType_t xResult;
+Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
+
+	/* Remove the timer from the list of active timers.  A check has already
+	been performed to ensure the list is not empty. */
+	( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
+	traceTIMER_EXPIRED( pxTimer );
+
+	/* If the timer is an auto reload timer then calculate the next
+	expiry time and re-insert the timer in the list of active timers. */
+	if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
+	{
+		/* The timer is inserted into a list using a time relative to anything
+		other than the current time.  It will therefore be inserted into the
+		correct list relative to the time this task thinks it is now. */
+		if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
+		{
+			/* The timer expired before it was added to the active timer
+			list.  Reload it now.  */
+			xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
+			configASSERT( xResult );
+			( void ) xResult;
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	else
+	{
+		mtCOVERAGE_TEST_MARKER();
+	}
+
+	/* Call the timer callback. */
+	pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+}
+/*-----------------------------------------------------------*/
+
+static void prvTimerTask( void *pvParameters )
+{
+TickType_t xNextExpireTime;
+BaseType_t xListWasEmpty;
+
+	/* Just to avoid compiler warnings. */
+	( void ) pvParameters;
+
+	for( ;; )
+	{
+		/* Query the timers list to see if it contains any timers, and if so,
+		obtain the time at which the next timer will expire. */
+		xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );
+
+		/* If a timer has expired, process it.  Otherwise, block this task
+		until either a timer does expire, or a command is received. */
+		prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );
+
+		/* Empty the command queue. */
+		prvProcessReceivedCommands();
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )
+{
+TickType_t xTimeNow;
+BaseType_t xTimerListsWereSwitched;
+
+	vTaskSuspendAll();
+	{
+		/* Obtain the time now to make an assessment as to whether the timer
+		has expired or not.  If obtaining the time causes the lists to switch
+		then don't process this timer as any timers that remained in the list
+		when the lists were switched will have been processed within the
+		prvSampleTimeNow() function. */
+		xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
+		if( xTimerListsWereSwitched == pdFALSE )
+		{
+			/* The tick count has not overflowed, has the timer expired? */
+			if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
+			{
+				( void ) xTaskResumeAll();
+				prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
+			}
+			else
+			{
+				/* The tick count has not overflowed, and the next expire
+				time has not been reached yet.  This task should therefore
+				block to wait for the next expire time or a command to be
+				received - whichever comes first.  The following line cannot
+				be reached unless xNextExpireTime > xTimeNow, except in the
+				case when the current timer list is empty. */
+				if( xListWasEmpty != pdFALSE )
+				{
+					/* The current timer list is empty - is the overflow list
+					also empty? */
+					xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
+				}
+
+				vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );
+
+				if( xTaskResumeAll() == pdFALSE )
+				{
+					/* Yield to wait for either a command to arrive, or the
+					block time to expire.  If a command arrived between the
+					critical section being exited and this yield then the yield
+					will not cause the task to block. */
+					portYIELD_WITHIN_API();
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+		}
+		else
+		{
+			( void ) xTaskResumeAll();
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )
+{
+TickType_t xNextExpireTime;
+
+	/* Timers are listed in expiry time order, with the head of the list
+	referencing the task that will expire first.  Obtain the time at which
+	the timer with the nearest expiry time will expire.  If there are no
+	active timers then just set the next expire time to 0.  That will cause
+	this task to unblock when the tick count overflows, at which point the
+	timer lists will be switched and the next expiry time can be
+	re-assessed.  */
+	*pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );
+	if( *pxListWasEmpty == pdFALSE )
+	{
+		xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
+	}
+	else
+	{
+		/* Ensure the task unblocks when the tick count rolls over. */
+		xNextExpireTime = ( TickType_t ) 0U;
+	}
+
+	return xNextExpireTime;
+}
+/*-----------------------------------------------------------*/
+
+static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
+{
+TickType_t xTimeNow;
+PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
+
+	xTimeNow = xTaskGetTickCount();
+
+	if( xTimeNow < xLastTime )
+	{
+		prvSwitchTimerLists();
+		*pxTimerListsWereSwitched = pdTRUE;
+	}
+	else
+	{
+		*pxTimerListsWereSwitched = pdFALSE;
+	}
+
+	xLastTime = xTimeNow;
+
+	return xTimeNow;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )
+{
+BaseType_t xProcessTimerNow = pdFALSE;
+
+	listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );
+	listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
+
+	if( xNextExpiryTime <= xTimeNow )
+	{
+		/* Has the expiry time elapsed between the command to start/reset a
+		timer was issued, and the time the command was processed? */
+		if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )
+		{
+			/* The time between a command being issued and the command being
+			processed actually exceeds the timers period.  */
+			xProcessTimerNow = pdTRUE;
+		}
+		else
+		{
+			vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );
+		}
+	}
+	else
+	{
+		if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )
+		{
+			/* If, since the command was issued, the tick count has overflowed
+			but the expiry time has not, then the timer must have already passed
+			its expiry time and should be processed immediately. */
+			xProcessTimerNow = pdTRUE;
+		}
+		else
+		{
+			vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
+		}
+	}
+
+	return xProcessTimerNow;
+}
+/*-----------------------------------------------------------*/
+
+static void	prvProcessReceivedCommands( void )
+{
+DaemonTaskMessage_t xMessage;
+Timer_t *pxTimer;
+BaseType_t xTimerListsWereSwitched, xResult;
+TickType_t xTimeNow;
+
+	while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */
+	{
+		#if ( INCLUDE_xTimerPendFunctionCall == 1 )
+		{
+			/* Negative commands are pended function calls rather than timer
+			commands. */
+			if( xMessage.xMessageID < ( BaseType_t ) 0 )
+			{
+				const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );
+
+				/* The timer uses the xCallbackParameters member to request a
+				callback be executed.  Check the callback is not NULL. */
+				configASSERT( pxCallback );
+
+				/* Call the function. */
+				pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		#endif /* INCLUDE_xTimerPendFunctionCall */
+
+		/* Commands that are positive are timer commands rather than pended
+		function calls. */
+		if( xMessage.xMessageID >= ( BaseType_t ) 0 )
+		{
+			/* The messages uses the xTimerParameters member to work on a
+			software timer. */
+			pxTimer = xMessage.u.xTimerParameters.pxTimer;
+
+			if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
+			{
+				/* The timer is in a list, remove it. */
+				( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+
+			traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
+
+			/* In this case the xTimerListsWereSwitched parameter is not used, but
+			it must be present in the function call.  prvSampleTimeNow() must be
+			called after the message is received from xTimerQueue so there is no
+			possibility of a higher priority task adding a message to the message
+			queue with a time that is ahead of the timer daemon task (because it
+			pre-empted the timer daemon task after the xTimeNow value was set). */
+			xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
+
+			switch( xMessage.xMessageID )
+			{
+				case tmrCOMMAND_START :
+			    case tmrCOMMAND_START_FROM_ISR :
+			    case tmrCOMMAND_RESET :
+			    case tmrCOMMAND_RESET_FROM_ISR :
+				case tmrCOMMAND_START_DONT_TRACE :
+					/* Start or restart a timer. */
+					if( prvInsertTimerInActiveList( pxTimer,  xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
+					{
+						/* The timer expired before it was added to the active
+						timer list.  Process it now. */
+						pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+						traceTIMER_EXPIRED( pxTimer );
+
+						if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
+						{
+							xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
+							configASSERT( xResult );
+							( void ) xResult;
+						}
+						else
+						{
+							mtCOVERAGE_TEST_MARKER();
+						}
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+					break;
+
+				case tmrCOMMAND_STOP :
+				case tmrCOMMAND_STOP_FROM_ISR :
+					/* The timer has already been removed from the active list.
+					There is nothing to do here. */
+					break;
+
+				case tmrCOMMAND_CHANGE_PERIOD :
+				case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :
+					pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
+					configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
+
+					/* The new period does not really have a reference, and can be
+					longer or shorter than the old one.  The command time is
+					therefore set to the current time, and as the period cannot be
+					zero the next expiry time can only be in the future, meaning
+					(unlike for the xTimerStart() case above) there is no fail case
+					that needs to be handled here. */
+					( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
+					break;
+
+				case tmrCOMMAND_DELETE :
+					/* The timer has already been removed from the active list,
+					just free up the memory. */
+					vPortFree( pxTimer );
+					break;
+
+				default	:
+					/* Don't expect to get here. */
+					break;
+			}
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvSwitchTimerLists( void )
+{
+TickType_t xNextExpireTime, xReloadTime;
+List_t *pxTemp;
+Timer_t *pxTimer;
+BaseType_t xResult;
+
+	/* The tick count has overflowed.  The timer lists must be switched.
+	If there are any timers still referenced from the current timer list
+	then they must have expired and should be processed before the lists
+	are switched. */
+	while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )
+	{
+		xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
+
+		/* Remove the timer from the list. */
+		pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
+		( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
+		traceTIMER_EXPIRED( pxTimer );
+
+		/* Execute its callback, then send a command to restart the timer if
+		it is an auto-reload timer.  It cannot be restarted here as the lists
+		have not yet been switched. */
+		pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+
+		if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
+		{
+			/* Calculate the reload value, and if the reload value results in
+			the timer going into the same timer list then it has already expired
+			and the timer should be re-inserted into the current list so it is
+			processed again within this loop.  Otherwise a command should be sent
+			to restart the timer to ensure it is only inserted into a list after
+			the lists have been swapped. */
+			xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );
+			if( xReloadTime > xNextExpireTime )
+			{
+				listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );
+				listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
+				vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
+			}
+			else
+			{
+				xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
+				configASSERT( xResult );
+				( void ) xResult;
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+
+	pxTemp = pxCurrentTimerList;
+	pxCurrentTimerList = pxOverflowTimerList;
+	pxOverflowTimerList = pxTemp;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckForValidListAndQueue( void )
+{
+	/* Check that the list from which active timers are referenced, and the
+	queue used to communicate with the timer service, have been
+	initialised. */
+	taskENTER_CRITICAL();
+	{
+		if( xTimerQueue == NULL )
+		{
+			vListInitialise( &xActiveTimerList1 );
+			vListInitialise( &xActiveTimerList2 );
+			pxCurrentTimerList = &xActiveTimerList1;
+			pxOverflowTimerList = &xActiveTimerList2;
+			xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
+			configASSERT( xTimerQueue );
+
+			#if ( configQUEUE_REGISTRY_SIZE > 0 )
+			{
+				if( xTimerQueue != NULL )
+				{
+					vQueueAddToRegistry( xTimerQueue, "TmrQ" );
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			#endif /* configQUEUE_REGISTRY_SIZE */
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+	taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
+{
+BaseType_t xTimerIsInActiveList;
+Timer_t *pxTimer = ( Timer_t * ) xTimer;
+
+	configASSERT( xTimer );
+
+	/* Is the timer in the list of active timers? */
+	taskENTER_CRITICAL();
+	{
+		/* Checking to see if it is in the NULL list in effect checks to see if
+		it is referenced from either the current or the overflow timer lists in
+		one go, but the logic has to be reversed, hence the '!'. */
+		xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
+	}
+	taskEXIT_CRITICAL();
+
+	return xTimerIsInActiveList;
+} /*lint !e818 Can't be pointer to const due to the typedef. */
+/*-----------------------------------------------------------*/
+
+void *pvTimerGetTimerID( const TimerHandle_t xTimer )
+{
+Timer_t * const pxTimer = ( Timer_t * ) xTimer;
+void *pvReturn;
+
+	configASSERT( xTimer );
+
+	taskENTER_CRITICAL();
+	{
+		pvReturn = pxTimer->pvTimerID;
+	}
+	taskEXIT_CRITICAL();
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )
+{
+Timer_t * const pxTimer = ( Timer_t * ) xTimer;
+
+	configASSERT( xTimer );
+
+	taskENTER_CRITICAL();
+	{
+		pxTimer->pvTimerID = pvNewID;
+	}
+	taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+#if( INCLUDE_xTimerPendFunctionCall == 1 )
+
+	BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )
+	{
+	DaemonTaskMessage_t xMessage;
+	BaseType_t xReturn;
+
+		/* Complete the message with the function parameters and post it to the
+		daemon task. */
+		xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
+		xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
+		xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
+		xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
+
+		xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
+
+		tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
+
+		return xReturn;
+	}
+
+#endif /* INCLUDE_xTimerPendFunctionCall */
+/*-----------------------------------------------------------*/
+
+#if( INCLUDE_xTimerPendFunctionCall == 1 )
+
+	BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )
+	{
+	DaemonTaskMessage_t xMessage;
+	BaseType_t xReturn;
+
+		/* This function can only be called after a timer has been created or
+		after the scheduler has been started because, until then, the timer
+		queue does not exist. */
+		configASSERT( xTimerQueue );
+
+		/* Complete the message with the function parameters and post it to the
+		daemon task. */
+		xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
+		xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
+		xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
+		xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
+
+		xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
+
+		tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
+
+		return xReturn;
+	}
+
+#endif /* INCLUDE_xTimerPendFunctionCall */
+/*-----------------------------------------------------------*/
+
+/* This entire source file will be skipped if the application is not configured
+to include software timer functionality.  If you want to include software timer
+functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
+#endif /* configUSE_TIMERS == 1 */
+
+
+

+ 99 - 0
app/HW/include/hd_eth.h

@@ -0,0 +1,99 @@
+/*!
+    \file  gd32f30x_enet_eval.h
+    \brief the header file of gd32f30x_enet_eval 
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+*/
+
+/*
+    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.
+*/
+
+#ifndef HD_ETH_H
+#define HD_ETH_H
+
+#define DP83848_PHY_ADDRESS   0x1
+#define ETH_INIT_FLAG           0x01 /* Ethernet Init Flag */
+#define ETH_LINK_FLAG           0x10 /* Ethernet Link Flag */
+
+#define USE_DHCP       /* enable DHCP, if disabled static address is used */
+
+/* MAC address: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0   2
+//取唯一id做为MAC地址0x1fffF7E8为gd32f307芯片唯一id地址
+#define MAC_ADDR1   (uint8_t)((*(uint32_t*)(0x1fffF7E8))>> 0)
+#define MAC_ADDR2   (uint8_t)((*(uint32_t*)(0x1fffF7E8))>> 8)
+#define MAC_ADDR3   (uint8_t)((*(uint32_t*)(0x1fffF7E8))>> 16)
+#define MAC_ADDR4   (uint8_t)((*(uint32_t*)(0x1fffF7E8))>> 24)
+#define MAC_ADDR5   0
+ 
+/* static IP address: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
+#define IP_ADDR0   192
+#define IP_ADDR1   168
+#define IP_ADDR2   2
+#define IP_ADDR3   126
+
+/* remote station IP address: IP_S_ADDR0.IP_S_ADDR1.IP_S_ADDR2.IP_S_ADDR3 */
+#define IP_S_ADDR0   192
+#define IP_S_ADDR1   168
+#define IP_S_ADDR2   2
+#define IP_S_ADDR3   22
+
+/* net mask */
+#define NETMASK_ADDR0   255
+#define NETMASK_ADDR1   255
+#define NETMASK_ADDR2   254
+#define NETMASK_ADDR3   0
+
+/* gateway address */
+#define GW_ADDR0   192
+#define GW_ADDR1   168
+#define GW_ADDR2   2
+#define GW_ADDR3   1  
+
+/* MII and RMII mode selection */
+//#define RMII_MODE  // user have to provide the 50 MHz clock by soldering a 50 MHz oscillator
+#define MII_MODE
+
+/* clock the PHY from external 25MHz crystal (only for MII mode) */
+#ifdef  MII_MODE
+#define PHY_CLOCK_MCO
+#endif
+
+
+/* function declarations */
+/* setup ethernet system(GPIOs, clocks, MAC, DMA, systick) */
+void  enet_system_setup(void);
+
+extern volatile uint32_t  EthStatus;
+
+
+
+#endif /* GD32F30x_ENET_EVAL_H */

+ 37 - 0
app/HW/include/led.h

@@ -0,0 +1,37 @@
+#ifndef LED_H
+#define LED_H
+
+#include "gd32f30x.h"
+/* exported types */
+typedef enum 
+{
+    LED_DEV = 0,
+		LED_485STATE,
+		LED_NETSTATE
+} led_typedef_enum;
+
+
+/* eval board low layer led */
+#define LEDn                             3U
+
+#define LED_DEV_PIN                      GPIO_PIN_4
+#define LED_DEV_GPIO_PORT                GPIOB
+#define LED_DEV_GPIO_CLK                 RCU_GPIOB
+
+#define LED_485STATE_PIN                 GPIO_PIN_2
+#define LED_485STATE_GPIO_PORT           GPIOD
+#define LED_485STATE_GPIO_CLK            RCU_GPIOD
+
+#define LED_NETSTATE_PIN                 GPIO_PIN_3
+#define LED_NETSTATE_GPIO_PORT           GPIOB
+#define LED_NETSTATE_GPIO_CLK            RCU_GPIOB
+/* configure led GPIO */
+void gd_eval_led_init(led_typedef_enum lednum);
+/* turn on selected led */
+void gd_eval_led_on(led_typedef_enum lednum);
+/* turn off selected led */
+void gd_eval_led_off(led_typedef_enum lednum);
+/* toggle the selected led */
+void gd_eval_led_toggle(led_typedef_enum lednum);
+
+#endif

+ 21 - 0
app/HW/include/netconf.h

@@ -0,0 +1,21 @@
+/*!
+    \file  netconf.h
+    \brief the header file of netconf 
+*/
+
+/*
+    Copyright (C) 2017 GigaDevice
+
+    2017-07-28, V1.0.0, demo for GD32F30x
+*/
+
+#ifndef NETCONF_H
+#define NETCONF_H
+
+/* function declarations */
+/* initializes the LwIP stack */
+void lwip_stack_init(void);
+/* dhcp_task */
+void dhcp_task(void * pvParameters);
+
+#endif /* NETCONF_H */

+ 36 - 0
app/HW/include/usart.h

@@ -0,0 +1,36 @@
+#ifndef USART_H
+#define USART_H
+
+#include "gd32f30x.h"
+
+typedef struct usart_data_buf_s
+{
+	uint8_t data[256];
+	uint16_t data_cnt;
+} usart_data_buf_t;
+
+#define DE485_PIN                        GPIO_PIN_8
+#define DE485_GPIO_PORT                  GPIOA
+#define DE485_GPIO_CLK                   RCU_GPIOA
+
+
+#define COM_485	                       USART0 
+#define COM_485_CLK                    RCU_USART0
+#define COM_485_TX_PIN                 GPIO_PIN_9
+#define COM_485_RX_PIN                 GPIO_PIN_10
+#define COM_485_GPIO_PORT              GPIOA
+#define COM_485_GPIO_CLK               RCU_GPIOA
+#define COM_485_IT_HANDLER             USART0_IRQn
+
+
+
+
+void config_485_port(uint32_t com,uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity);
+void gd_com_485_send(uint8_t *message,uint16_t size);
+void gd_485_DE_pin_init(void);
+void gd_485_DE_tx(void);
+void gd_485_DE_rx(void);
+
+
+
+#endif   

+ 191 - 0
app/HW/source/hd_eth.c

@@ -0,0 +1,191 @@
+
+
+#include "gd32f30x_enet.h"
+#include "hd_eth.h"
+#include "main.h"
+#include "lwip/netif.h"
+#include "lwip/dhcp.h"
+#include "tcpip.h"
+#include "lwip/netif.h"
+
+
+volatile uint32_t  EthStatus = 0;
+
+static void enet_gpio_config(void);
+static void enet_mac_dma_config(void);
+static void nvic_configuration(void);
+void eth_link_callback(struct netif *netif);
+/*!
+    \brief      setup ethernet system(GPIOs, clocks, MAC, DMA, systick)
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void enet_system_setup(void)
+{
+    nvic_configuration();   
+  
+    /* configure the GPIO ports for ethernet pins */
+    enet_gpio_config();
+    
+    /* configure the ethernet MAC/DMA */
+    enet_mac_dma_config();
+
+  
+    enet_interrupt_enable(ENET_DMA_INT_NIE);
+    enet_interrupt_enable(ENET_DMA_INT_RIE);
+}
+
+/*!
+    \brief      configures the ethernet interface
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void enet_mac_dma_config(void)
+{
+    ErrStatus reval_state = ERROR;
+    
+    /* enable ethernet clock  */
+    rcu_periph_clock_enable(RCU_ENET);
+    rcu_periph_clock_enable(RCU_ENETTX);
+    rcu_periph_clock_enable(RCU_ENETRX);
+    
+    /* reset ethernet on AHB bus */
+    enet_deinit();
+
+    reval_state = enet_software_reset();
+    if(ERROR == reval_state){
+        while(1){
+        }
+    }
+/* configure the parameters which are usually less cared for enet initialization */  
+//  enet_initpara_config(HALFDUPLEX_OPTION, ENET_CARRIERSENSE_ENABLE|ENET_RECEIVEOWN_ENABLE|ENET_RETRYTRANSMISSION_DISABLE|ENET_BACKOFFLIMIT_10|ENET_DEFERRALCHECK_DISABLE);
+  enet_initpara_config(DMA_OPTION, ENET_FLUSH_RXFRAME_ENABLE|ENET_SECONDFRAME_OPT_ENABLE|ENET_NORMAL_DESCRIPTOR);
+#ifdef CHECKSUM_BY_HARDWARE
+		if( enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS))
+		{
+			EthStatus = ETH_INIT_FLAG;
+		}
+    else
+		{
+			EthStatus = 0;
+		}
+#else  
+    if( enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS))EthStatus = ETH_INIT_FLAG;
+		esle																																																EthStatus = 0;
+#endif /* CHECKSUM_BY_HARDWARE */
+  
+}
+
+/*!
+    \brief      configures the nested vectored interrupt controller
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void nvic_configuration(void)
+{
+    nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x0);
+    nvic_irq_enable(ENET_IRQn, 2, 0);
+}
+
+/*!
+    \brief      configures the different GPIO ports
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+static void enet_gpio_config(void)
+{
+    rcu_periph_clock_enable(RCU_GPIOA);
+    rcu_periph_clock_enable(RCU_GPIOB);
+    rcu_periph_clock_enable(RCU_GPIOC);
+    rcu_periph_clock_enable(RCU_AF);
+  
+    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);
+  
+#ifdef MII_MODE 
+  
+#ifdef PHY_CLOCK_MCO
+    /* output HXTAL clock (25MHz) on CKOUT0 pin(PA8) to clock the PHY */
+    rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL);
+#endif /* PHY_CLOCK_MCO */
+
+    gpio_ethernet_phy_select(GPIO_ENET_PHY_MII);
+
+#elif defined RMII_MODE
+    /* choose PLL2 to get 50MHz from 25/5*10 on CKOUT0 pin (PA8) to clock the PHY */
+    rcu_pll2_config(RCU_PLL2_MUL10);  
+    rcu_osci_on(RCU_PLL2_CK);
+    rcu_osci_stab_wait(RCU_PLL2_CK);
+    rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2);
+    gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII);
+
+#endif /* MII_MODE */
+
+#ifdef MII_MODE
+
+    /* PA0: ETH_MII_CRS */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_0);  
+    /* PA1: ETH_MII_RX_CLK */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_1);      
+    /* PA2: ETH_MDIO */
+    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  
+    /* PA3: ETH_MII_COL */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_3);     
+    /* PA7: ETH_MII_RX_DV */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_7);  
+
+    /* PB0: ETH_MII_RXD2 */
+    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_0);  
+    /* PB1: ETH_MII_RXD3 */
+    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_1);  
+    /* PB8: ETH_MII_TXD3 */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);  
+    /* PB10: ETH_MII_RX_ER */
+    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_10);  
+    /* PB11: ETH_MII_TX_EN */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);     
+    /* PB12: ETH_MII_TXD0 */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);     
+    /* PB13: ETH_MII_TXD1 */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13);  
+
+    /* PC1: ETH_MDC */
+    gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);      
+    /* PC2: ETH_MII_TXD2 */
+    gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);      
+    /* PC3: ETH_MII_TX_CLK */
+    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_3);  
+    /* PC4: ETH_MII_RXD0 */
+    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_4);     
+    /* PC5: ETH_MII_RXD1 */
+    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_5);  
+      
+#elif defined RMII_MODE
+
+    /* PA1: ETH_RMII_REF_CLK */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_1);   
+    /* PA2: ETH_MDIO */
+    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);        
+    /* PA7: ETH_RMII_CRS_DV */
+    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_7);
+        
+    /* PB11: ETH_RMII_TX_EN */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);    
+    /* PB12: ETH_RMII_TXD0 */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);   
+    /* PB13: ETH_RMII_TXD1 */
+    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13);  
+    
+    /* PC1: ETH_MDC */
+    gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);   
+    /* PC4: ETH_RMII_RXD0 */
+    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_4);    
+    /* PC5: ETH_RMII_RXD1 */
+    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_5);
+
+#endif /* MII_MODE */
+}
+

+ 68 - 0
app/HW/source/led.c

@@ -0,0 +1,68 @@
+#include "led.h"
+static uint32_t GPIO_PORT[LEDn] = {LED_DEV_GPIO_PORT,LED_485STATE_GPIO_PORT,LED_NETSTATE_GPIO_PORT};
+static uint32_t GPIO_PIN[LEDn] = {LED_DEV_PIN,LED_485STATE_PIN,LED_NETSTATE_PIN};
+static rcu_periph_enum GPIO_CLK[LEDn] = {LED_DEV_GPIO_CLK,LED_485STATE_GPIO_CLK,LED_NETSTATE_GPIO_CLK};
+
+/*!
+    \brief      configure led GPIO
+    \param[in]  lednum: specify the led to be configured
+      \arg        LED1
+    \param[out] none
+    \retval     none
+*/
+void gd_eval_led_init(led_typedef_enum lednum)
+{
+    /* enable the led clock */
+    rcu_periph_clock_enable(GPIO_CLK[lednum]);
+    /* configure led GPIO port */ 
+    gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN[lednum]);
+
+    GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
+		gpio_bit_set(GPIOB,GPIO_PIN_11);
+}
+
+/*!
+    \brief      turn on selected led
+    \param[in]  lednum: specify the led to be turned on
+      \arg        LED2
+      \arg        LED3
+      \arg        LED4
+      \arg        LED5
+    \param[out] none
+    \retval     none
+*/
+void gd_eval_led_on(led_typedef_enum lednum)
+{
+    GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
+}
+
+/*!
+    \brief      turn off selected led
+    \param[in]  lednum: specify the led to be turned off
+      \arg        LED2
+      \arg        LED3
+      \arg        LED4
+      \arg        LED5
+    \param[out] none
+    \retval     none
+*/
+void gd_eval_led_off(led_typedef_enum lednum)
+{
+    GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
+}
+
+/*!
+    \brief      toggle selected led
+    \param[in]  lednum: specify the led to be toggled
+      \arg        LED2
+      \arg        LED3
+      \arg        LED4
+      \arg        LED5
+    \param[out] none
+    \retval     none
+*/
+void gd_eval_led_toggle(led_typedef_enum lednum)
+{
+    gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], 
+        (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum])));
+}

+ 300 - 0
app/HW/source/netconf.c

@@ -0,0 +1,300 @@
+/*!
+    \file  netconf.c
+    \brief network connection configuration 
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+*/
+
+/*
+    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.
+*/
+
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dhcp.h"
+#include "ethernetif.h"
+#include "main.h"
+#include "netconf.h"
+#include "tcpip.h"
+#include <stdio.h>
+#include "lwip/inet.h"
+#include "hd_eth.h"
+
+#define MAX_DHCP_TRIES       4
+
+typedef enum 
+{ 
+    DHCP_START = 0,
+    DHCP_WAIT_ADDRESS,
+    DHCP_ADDRESS_ASSIGNED,
+    DHCP_TIMEOUT
+}dhcp_state_enum;
+
+
+volatile uint8_t EthLinkStatus = 0;
+#ifdef USE_DHCP
+dhcp_state_enum dhcp_state = DHCP_START;
+#endif /* USE_DHCP */
+
+struct netif g_mynetif;
+
+void ETH_link_callback(struct netif *netif);
+void ETH_CheckLinkStatus(uint16_t PHYAddress);
+void ETH_CheckLinkStatus_timer(void *arg);
+/*!
+    \brief      initializes the LwIP stack
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void lwip_stack_init(void)
+{
+    struct ip_addr ipaddr;
+    struct ip_addr netmask;
+    struct ip_addr gw;
+
+    /* create tcp_ip stack thread */
+    tcpip_init( NULL, NULL );
+
+    /* IP address setting */
+#ifdef USE_DHCP
+    ipaddr.addr = 0;
+    netmask.addr = 0;
+    gw.addr = 0;
+#else
+    IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
+    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+  
+#endif /* USE_DHCP */
+
+    netif_add(&g_mynetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
+
+    /* registers the default network interface */
+    netif_set_default(&g_mynetif);
+
+    /* when the netif is fully configured this function must be called */
+    netif_set_up(&g_mynetif);
+		uint16_t data;
+		enet_phy_write_read(ENET_PHY_READ, DP83848_PHY_ADDRESS,PHY_REG_BSR,&data);
+		if(data & 0x4)
+		{
+			EthStatus |= ETH_LINK_FLAG;
+		}
+		if (EthStatus == (ETH_INIT_FLAG | ETH_LINK_FLAG))
+		{ 
+    /* Set Ethernet link flag */
+    g_mynetif.flags |= NETIF_FLAG_LINK_UP;
+
+    /* When the netif is fully configured this function must be called.*/
+    netif_set_up(&g_mynetif);
+#ifdef USE_DHCP
+    dhcp_state = DHCP_START;
+#else
+#ifdef SERIAL_DEBUG
+		printf("\n  Static IP address   \n");
+		printf("IP: %d.%d.%d.%d\n",IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
+		printf("NETMASK: %d.%d.%d.%d\n",NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
+		printf("Gateway: %d.%d.%d.%d\n",GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
+#endif /* SERIAL_DEBUG */
+#endif /* USE_DHCP */
+  }
+  else
+  {
+    /*  When the netif link is down this function must be called.*/
+    netif_set_down(&g_mynetif);
+#ifdef USE_DHCP
+    dhcp_state = DHCP_TIMEOUT;
+#endif /* USE_DHCP */
+#ifdef SERIAL_DEBUG
+		printf("\n  Network Cable is  \n");
+		printf("    not connected   \n");
+#endif /* SERIAL_DEBUG */
+  }
+  /* Set the link callback function, this function is called on change of link status*/
+  netif_set_link_callback(&g_mynetif, ETH_link_callback);
+	sys_timeout(2000, ETH_CheckLinkStatus_timer, NULL);	
+}
+
+#ifdef USE_DHCP
+/*!
+    \brief      dhcp_task
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dhcp_task(void * pvParameters)
+{
+    struct ip_addr ipaddr;
+    struct ip_addr netmask;
+    struct ip_addr gw;
+    uint32_t ip_address = 0;
+  
+    for(;;){
+        switch(dhcp_state){
+        case DHCP_START:
+            dhcp_start(&g_mynetif);
+            /* IP address should be set to 0 every time we want to assign a new DHCP address*/
+            ip_address = 0;
+            dhcp_state = DHCP_WAIT_ADDRESS;
+            break;
+
+        case DHCP_WAIT_ADDRESS:    
+            /* read the new IP address */
+            ip_address = g_mynetif.ip_addr.addr;
+
+            if(0 != ip_address){ 
+                dhcp_state = DHCP_ADDRESS_ASSIGNED;
+                /* stop DHCP */
+                dhcp_stop(&g_mynetif);
+							char p[100];
+							sprintf(p,"\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), \
+                        ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
+            }else{
+                /* DHCP timeout */
+                if(g_mynetif.dhcp->tries > MAX_DHCP_TRIES){
+                    dhcp_state = DHCP_TIMEOUT;
+                    /* stop DHCP */
+                    dhcp_stop(&g_mynetif);
+
+                    /* static address used */
+                    IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );
+                    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+                    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+                    netif_set_addr(&g_mynetif, &ipaddr , &netmask, &gw);
+                }
+            }
+            break;
+
+        default: 
+            break;
+        }
+    
+        /* wait 250 ms */
+        vTaskDelay(1000);
+    }   
+}
+
+#endif /* USE_DHCP */
+//监测以太网热拔插定时器
+void ETH_CheckLinkStatus_timer(void *arg)
+{
+	LWIP_UNUSED_ARG(arg);
+	ETH_CheckLinkStatus(DP83848_PHY_ADDRESS);
+	sys_timeout(1000, ETH_CheckLinkStatus_timer, NULL);
+}
+/* This function is called periodically each second */
+/* It checks link status for ethernet controller */
+void ETH_CheckLinkStatus(uint16_t PHYAddress) 
+{
+	static uint8_t status = 0;
+	uint16_t data;
+	uint8_t linksta;
+	//读取以太网链接状态
+  if(enet_phy_write_read(ENET_PHY_READ, DP83848_PHY_ADDRESS,PHY_REG_BSR,&data)==1)
+	{
+		linksta=data & 0x4;
+	}
+	if(EthStatus & ETH_INIT_FLAG)
+	{
+		if(EthStatus & ETH_LINK_FLAG)
+		{
+			if(linksta == 0)
+			{
+				netif_set_link_down(&g_mynetif);
+				EthStatus &= ~ETH_LINK_FLAG;
+			}
+		}
+		else 
+		{
+			if(linksta != 0)
+			{
+				netif_set_link_up(&g_mynetif);
+				EthStatus |= ETH_LINK_FLAG;
+			}
+		}
+	}
+	else//处理未初始化的问题
+	{
+		if(linksta != 0)
+		{
+			low_level_init(&g_mynetif);
+			netif_set_link_up(&g_mynetif);
+			EthStatus |= ETH_INIT_FLAG;
+#if LWIP_DHCP == 1
+			dhcp_start(&g_mynetif);
+#endif 			
+		}
+	}
+}
+
+/**
+  * @brief  Link callback function, this function is called on change of link status.
+  * @param  The network interface
+  * @retval None
+  */
+void ETH_link_callback(struct netif *netif)
+{
+	__IO uint32_t timeout = 0;
+	uint32_t tmpreg,RegValue;
+	uint32_t media_temp = 0U;
+	uint16_t phy_value;
+	if(netif_is_link_up(netif))
+	{
+		printf("network is up");
+		//进入自协商模式 
+		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 < PHY_READ_TO));
+/*
+     enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value);  
+        if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){
+            media_temp = ENET_MODE_FULLDUPLEX;
+        }else{
+            media_temp = ENET_MODE_HALFDUPLEX;
+        }
+        if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){
+            media_temp |= ENET_SPEEDMODE_10M;
+        }else{
+            media_temp |= ENET_SPEEDMODE_100M;
+        }
+*/			
+		enet_enable();
+		netif_set_up(&g_mynetif);
+	}
+	else 
+	{
+		printf("network is down");		
+		enet_disable();
+		netif_set_down(&g_mynetif);
+	}
+}

+ 113 - 0
app/HW/source/usart.c

@@ -0,0 +1,113 @@
+#include "usart.h"
+void nvic_config(void);
+void gd_485_DE_pin_init(void)
+{
+    /* enable the 485 DE pin clock */
+    rcu_periph_clock_enable(DE485_GPIO_CLK);
+    /* configure 485 DE GPIO port */ 
+    gpio_init(DE485_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DE485_PIN);
+
+    GPIO_BC(DE485_GPIO_PORT) = DE485_PIN;
+}
+
+/*!
+    \brief      turn 485 to tx
+    \param[out] none
+    \retval     none
+*/
+void gd_485_DE_tx(void)
+{
+    GPIO_BOP(DE485_GPIO_PORT) = DE485_PIN;
+}
+
+/*!
+    \brief      turn 485 to rx
+    \param[out] none
+    \retval     none
+*/
+void gd_485_DE_rx(void)
+{
+    GPIO_BC(DE485_GPIO_PORT) = DE485_PIN;
+}
+
+/*!
+    \brief      COM port to send buff
+    \param[in]  com: COM on the board
+    \arg        COM_485
+    \param[out] none
+    \retval     none
+*/
+void gd_com_485_send(uint8_t *message,uint16_t size){
+	uint16_t i=0;
+	gd_485_DE_tx();
+	for (i = 0; i < size; i++)
+	{
+		usart_data_transmit(COM_485, message[i]);
+		while (RESET == usart_flag_get(COM_485, USART_FLAG_TC));
+	}
+	gd_485_DE_rx();
+}
+
+/*
+ *  函数名:void config_485_port(uint32_t com,uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity, uint8_t flowcontrol)
+ *  输入参数:com 串口,baudrate,databits,stopbits,parity,flowcontol 串口的配置参数
+ *  输出参数:无
+ *  返回值:无
+ *  函数作用:配置485串口参数
+ */
+void config_485_port(uint32_t com,uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity)
+{
+	 uint32_t com_id = 0U;
+	 uint8_t wordLength;
+		if(parity!=0)
+		{
+			wordLength=databits+1;
+		}else wordLength=databits;
+			nvic_irq_enable(COM_485_IT_HANDLER, 0, 0);
+			/* enable GPIO clock */
+			rcu_periph_clock_enable(COM_485_GPIO_CLK);
+			/* enable USART clock */
+			rcu_periph_clock_enable(COM_485_CLK);
+			/* connect port to USARTx_Tx */
+			gpio_init(COM_485_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_485_TX_PIN);
+			/* connect port to USARTx_Rx */
+			gpio_init(COM_485_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_485_RX_PIN);
+			//usart_deinit(com);
+			usart_baudrate_set(com, baudrate);
+			usart_word_length_set(com, (wordLength == 9) ? USART_WL_9BIT : USART_WL_8BIT);
+			usart_stop_bit_set(com, (stopbits == 2) ? USART_STB_2BIT : USART_STB_1BIT);
+			usart_parity_config(com, parity == 1 ? (USART_PM_ODD) : (parity == 2 ? USART_PM_EVEN : USART_PM_NONE));
+			usart_hardware_flow_rts_config(com, USART_RTS_DISABLE);
+			usart_hardware_flow_cts_config(com, USART_CTS_DISABLE);
+			usart_receive_config(com, USART_RECEIVE_ENABLE);
+			usart_transmit_config(com, USART_TRANSMIT_ENABLE);
+			/* 使能串口 */
+			usart_enable(com);
+//			nvic_config();
+//		  usart_interrupt_enable(com, USART_INT_RBNE);
+//			usart_interrupt_enable(com, USART_INT_IDLE);
+			//解决485第一个帧数据第一个字节丢失问题
+			usart_flag_clear(COM_485,USART_FLAG_TC);
+}
+
+void nvic_config(void)
+{
+		nvic_irq_enable(USART0_IRQn, 0, 0);
+}
+void USART0_IRQHandler(void)
+{
+	 if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
+  {
+   usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE);
+  }
+
+  if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE))
+  {
+		usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);
+  }
+  else
+  {
+    usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE);
+  }
+}
+

+ 403 - 0
app/LIB/Include/gd32f30x_adc.h

@@ -0,0 +1,403 @@
+/*!
+    \file    gd32f30x_adc.h
+    \brief   definitions for the ADC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_ADC_H
+#define GD32F30X_ADC_H
+
+#include "gd32f30x.h"
+
+/* ADC definitions */
+#define ADC0                            ADC_BASE
+#define ADC1                            (ADC_BASE + 0x400U)
+#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))
+#define ADC2                            (ADC_BASE + 0x1800U)
+#endif
+
+/* 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 */
+#define ADC_OVSAMPCTL(adcx)             REG32((adcx) + 0x80U)            /*!< ADC oversampling control 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 x 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 */
+#define ADC_RSQX_RSQN                   BITS(0,4)                        /*!< x conversion in regular sequence */
+#define ADC_RSQ0_RL                     BITS(20,23)                      /*!< regular channel sequence length */
+
+/* ADC_ISQ */
+#define ADC_ISQ_ISQN                    BITS(0,4)                        /*!< x conversion in regular 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 x */
+
+/* ADC_RDATA */
+#define ADC_RDATA_RDATA                 BITS(0,15)                       /*!< regular data */
+#define ADC_RDATA_ADC1RDTR              BITS(16,31)                      /*!< ADC1 regular channel data */
+
+/* ADC_OVSAMPCTL */
+#define ADC_OVSAMPCTL_OVSEN             BIT(0)                           /*!< oversampling enable */
+#define ADC_OVSAMPCTL_OVSR              BITS(2,4)                        /*!< oversampling ratio */
+#define ADC_OVSAMPCTL_OVSS              BITS(5,8)                        /*!< oversampling shift */
+#define ADC_OVSAMPCTL_TOVS              BIT(9)                           /*!< triggered oversampling */
+#define ADC_OVSAMPCTL_DRES              BITS(12,13)                      /*!< oversampling shift */
+
+
+/* constants definitions */
+/* ADC status flag */
+#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 */
+
+/* ADC special function definitions */
+#define ADC_SCAN_MODE                   ADC_CTL0_SM                                  /*!< scan mode */
+#define ADC_INSERTED_CHANNEL_AUTO       ADC_CTL0_ICA                                 /*!< inserted channel group convert automatically */
+#define ADC_CONTINUOUS_MODE             ADC_CTL1_CTN                                 /*!< continuous mode */
+
+/* ADC synchronization 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_TRRIGGER_ROTATION                  CTL0_SYNCM(9)           /*!< ADC0 and ADC1 work in trigger rotation mode only */
+
+/* ADC data alignment */
+#define ADC_DATAALIGN_RIGHT              ((uint32_t)0x00000000U)                     /*!< LSB alignment */
+#define ADC_DATAALIGN_LEFT               ADC_CTL1_DAL                                /*!< MSB alignment */
+
+/* ADC 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 */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH0    CTL1_ETSRC(0)                               /*!< timer 0 CC0 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH1    CTL1_ETSRC(1)                               /*!< timer 0 CC1 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T0_CH2    CTL1_ETSRC(2)                               /*!< timer 0 CC2 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T1_CH1    CTL1_ETSRC(3)                               /*!< timer 1 CC1 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO   CTL1_ETSRC(4)                               /*!< timer 2 TRGO event select */
+#define ADC0_1_EXTTRIG_REGULAR_T3_CH3    CTL1_ETSRC(5)                               /*!< timer 3 CC3 event select */
+#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO   CTL1_ETSRC(6)                               /*!< timer 7 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 */
+
+#define ADC2_EXTTRIG_REGULAR_T2_CH0      CTL1_ETSRC(0)                               /*!< timer 2 CC0 event select */
+#define ADC2_EXTTRIG_REGULAR_T1_CH2      CTL1_ETSRC(1)                               /*!< timer 1 CC2 event select */
+#define ADC2_EXTTRIG_REGULAR_T0_CH2      CTL1_ETSRC(2)                               /*!< timer 0 CC2 event select */
+#define ADC2_EXTTRIG_REGULAR_T7_CH0      CTL1_ETSRC(3)                               /*!< timer 7 CC0 event select */
+#define ADC2_EXTTRIG_REGULAR_T7_TRGO     CTL1_ETSRC(4)                               /*!< timer 7 TRGO event select */
+#define ADC2_EXTTRIG_REGULAR_T4_CH0      CTL1_ETSRC(5)                               /*!< timer 4 CC0 event select */
+#define ADC2_EXTTRIG_REGULAR_T4_CH2      CTL1_ETSRC(6)                               /*!< timer 4 CC2 event select */
+
+/* ADC external trigger select for inserted channel */
+#define CTL1_ETSIC(regval)               (BITS(12,14) & ((uint32_t)(regval) << 12))  /*!< write value to ADC_CTL1_ETSIC bit field */
+#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO  CTL1_ETSIC(0)                               /*!< timer 0 TRGO event select */
+#define ADC0_1_EXTTRIG_INSERTED_T0_CH3   CTL1_ETSIC(1)                               /*!< timer 0 CC3 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO  CTL1_ETSIC(2)                               /*!< timer 1 TRGO event select */
+#define ADC0_1_EXTTRIG_INSERTED_T1_CH0   CTL1_ETSIC(3)                               /*!< timer 1 CC0 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T2_CH3   CTL1_ETSIC(4)                               /*!< timer 2 CC3 event select */
+#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO  CTL1_ETSIC(5)                               /*!< timer 3 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)                               /*!< timer 7 CC3 event select */
+#define ADC0_1_2_EXTTRIG_INSERTED_NONE   CTL1_ETSIC(7)                               /*!< software trigger */
+
+#define ADC2_EXTTRIG_INSERTED_T0_TRGO    CTL1_ETSIC(0)                               /*!< timer 0 TRGO event select */
+#define ADC2_EXTTRIG_INSERTED_T0_CH3     CTL1_ETSIC(1)                               /*!< timer 0 CC3 event select */
+#define ADC2_EXTTRIG_INSERTED_T3_CH2     CTL1_ETSIC(2)                               /*!< timer 3 CC2 event select */
+#define ADC2_EXTTRIG_INSERTED_T7_CH1     CTL1_ETSIC(3)                               /*!< timer 7 CC1 event select */
+#define ADC2_EXTTRIG_INSERTED_T7_CH3     CTL1_ETSIC(4)                               /*!< timer 7 CC3 event select */
+#define ADC2_EXTTRIG_INSERTED_T4_TRGO    CTL1_ETSIC(5)                               /*!< timer 4 TRGO event select */
+#define ADC2_EXTTRIG_INSERTED_T4_CH3     CTL1_ETSIC(6)                               /*!< timer 4 CC3 event select */
+
+/* ADC channel sample time */
+#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_ovsampctl register value */
+/* ADC resolution */
+#define OVSAMPCTL_DRES(regval)           (BITS(12,13) & ((uint32_t)(regval) << 12))  /*!< write value to ADC_OVSAMPCTL_DRES bit field */
+#define ADC_RESOLUTION_12B               OVSAMPCTL_DRES(0)                           /*!< 12-bit ADC resolution */
+#define ADC_RESOLUTION_10B               OVSAMPCTL_DRES(1)                           /*!< 10-bit ADC resolution */
+#define ADC_RESOLUTION_8B                OVSAMPCTL_DRES(2)                           /*!< 8-bit ADC resolution */
+#define ADC_RESOLUTION_6B                OVSAMPCTL_DRES(3)                           /*!< 6-bit ADC resolution */
+
+/* oversampling shift */
+#define OVSAMPCTL_OVSS(regval)           (BITS(5,8) & ((uint32_t)(regval) << 5))     /*!< write value to ADC_OVSAMPCTL_OVSS bit field */
+#define ADC_OVERSAMPLING_SHIFT_NONE      OVSAMPCTL_OVSS(0)                           /*!< no oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_1B        OVSAMPCTL_OVSS(1)                           /*!< 1-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_2B        OVSAMPCTL_OVSS(2)                           /*!< 2-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_3B        OVSAMPCTL_OVSS(3)                           /*!< 3-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_4B        OVSAMPCTL_OVSS(4)                           /*!< 4-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_5B        OVSAMPCTL_OVSS(5)                           /*!< 5-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_6B        OVSAMPCTL_OVSS(6)                           /*!< 6-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_7B        OVSAMPCTL_OVSS(7)                           /*!< 7-bit oversampling shift */
+#define ADC_OVERSAMPLING_SHIFT_8B        OVSAMPCTL_OVSS(8)                           /*!< 8-bit oversampling shift */
+
+/* oversampling ratio */
+#define OVSAMPCTL_OVSR(regval)           (BITS(2,4) & ((uint32_t)(regval) << 2))     /*!< write value to ADC_OVSAMPCTL_OVSR bit field */
+#define ADC_OVERSAMPLING_RATIO_MUL2      OVSAMPCTL_OVSR(0)                           /*!< oversampling ratio multiple 2 */
+#define ADC_OVERSAMPLING_RATIO_MUL4      OVSAMPCTL_OVSR(1)                           /*!< oversampling ratio multiple 4 */
+#define ADC_OVERSAMPLING_RATIO_MUL8      OVSAMPCTL_OVSR(2)                           /*!< oversampling ratio multiple 8 */
+#define ADC_OVERSAMPLING_RATIO_MUL16     OVSAMPCTL_OVSR(3)                           /*!< oversampling ratio multiple 16 */
+#define ADC_OVERSAMPLING_RATIO_MUL32     OVSAMPCTL_OVSR(4)                           /*!< oversampling ratio multiple 32 */
+#define ADC_OVERSAMPLING_RATIO_MUL64     OVSAMPCTL_OVSR(5)                           /*!< oversampling ratio multiple 64 */
+#define ADC_OVERSAMPLING_RATIO_MUL128    OVSAMPCTL_OVSR(6)                           /*!< oversampling ratio multiple 128 */
+#define ADC_OVERSAMPLING_RATIO_MUL256    OVSAMPCTL_OVSR(7)                           /*!< oversampling ratio multiple 256 */
+
+/* triggered oversampling */
+#define ADC_OVERSAMPLING_ALL_CONVERT     ((uint32_t)0x00000000U)                     /*!< all oversampled conversions for a channel are done consecutively after a trigger */
+#define ADC_OVERSAMPLING_ONE_CONVERT     ADC_OVSAMPCTL_TOVS                          /*!< each oversampled conversion for a channel needs a trigger */
+
+/* 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 */
+/* reset ADC */
+void adc_deinit(uint32_t adc_periph);
+/* 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 DMA request */
+void adc_dma_mode_enable(uint32_t adc_periph);
+/* disable DMA request */
+void adc_dma_mode_disable(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);
+
+/* configure ADC resolution */
+void adc_resolution_config(uint32_t adc_periph , uint32_t resolution);
+/* configure ADC discontinuous mode */
+void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length);
+
+/* configure the ADC 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);
+/* 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);
+/* enable ADC external trigger */
+void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue);
+/* 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);
+/* enable ADC software trigger */
+void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group);
+
+/* 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);
+
+/* 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 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);
+
+/* 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);
+
+/* configure ADC oversample mode */
+void adc_oversample_mode_config(uint32_t adc_periph , uint32_t mode , uint16_t shift , uint8_t ratio);
+/* enable ADC oversample mode */
+void adc_oversample_mode_enable(uint32_t adc_periph);
+/* disable ADC oversample mode */
+void adc_oversample_mode_disable(uint32_t adc_periph);
+#endif /* GD32F30X_ADC_H */

+ 244 - 0
app/LIB/Include/gd32f30x_bkp.h

@@ -0,0 +1,244 @@
+/*!
+    \file    gd32f30x_bkp.h
+    \brief   definitions for the BKP
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_BKP_H
+#define GD32F30X_BKP_H
+
+#include "gd32f30x.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 */
+#define BKP_OCTL_CCOSEL               BIT(14)                  /*!< RTC clock output selection */
+#define BKP_OCTL_CALDIR               BIT(15)                  /*!< RTC clock calibration direction */
+
+/* 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 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 */
+
+/* RTC clock output selection */
+#define RTC_CLOCK_DIV_64              ((uint16_t)0x0000U)      /*!< RTC clock div 64 */
+#define RTC_CLOCK_DIV_1               ((uint16_t)0x4000U)      /*!< RTC clock div 1 */
+
+/* RTC clock calibration direction */
+#define RTC_CLOCK_SLOWED_DOWN         ((uint16_t)0x0000U)      /*!< RTC clock slow down */
+#define RTC_CLOCK_SPEED_UP            ((uint16_t)0x8000U)      /*!< RTC clock speed up */
+
+/* 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 */
+
+/* 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;
+
+/* function declarations */
+/* reset BKP registers */
+void bkp_deinit(void);
+/* write BKP data register */
+void bkp_write_data(bkp_data_register_enum register_number, uint16_t data);
+/* read BKP data register */
+uint16_t bkp_read_data(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);
+/* RTC output selection */
+void bkp_rtc_output_select(uint16_t outputsel);
+/* RTC clock output selection */
+void bkp_rtc_clock_output_select(uint16_t clocksel);
+/* RTC clock calibration direction */
+void bkp_rtc_clock_calibration_direction(uint16_t direction);
+/* 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);
+/* enable tamper pin interrupt */
+void bkp_tamper_interrupt_enable(void);
+/* disable tamper pin interrupt */
+void bkp_tamper_interrupt_disable(void);
+
+/* flag functions */
+/* get BKP flag state */
+FlagStatus bkp_flag_get(uint16_t flag);
+/* clear BKP flag state */
+void bkp_flag_clear(uint16_t flag);
+/* get BKP interrupt flag state */
+FlagStatus bkp_interrupt_flag_get(uint16_t flag);
+/* clear BKP interrupt flag state */
+void bkp_interrupt_flag_clear(uint16_t flag);
+
+#endif /* GD32F30X_BKP_H */

+ 749 - 0
app/LIB/Include/gd32f30x_can.h

@@ -0,0 +1,749 @@
+/*!
+    \file    gd32f30x_can.h
+    \brief   definitions for the CAN
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2019-11-27, V2.0.1, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_CAN_H
+#define GD32F30X_CAN_H
+
+#include "gd32f30x.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) + 0x00000000U)        /*!< CAN control register */
+#define CAN_STAT(canx)                     REG32((canx) + 0x00000004U)        /*!< CAN status register */
+#define CAN_TSTAT(canx)                    REG32((canx) + 0x00000008U)        /*!< CAN transmit status register*/
+#define CAN_RFIFO0(canx)                   REG32((canx) + 0x0000000CU)        /*!< CAN receive FIFO0 register */
+#define CAN_RFIFO1(canx)                   REG32((canx) + 0x00000010U)        /*!< CAN receive FIFO1 register */
+#define CAN_INTEN(canx)                    REG32((canx) + 0x00000014U)        /*!< CAN interrupt enable register */
+#define CAN_ERR(canx)                      REG32((canx) + 0x00000018U)        /*!< CAN error register */
+#define CAN_BT(canx)                       REG32((canx) + 0x0000001CU)        /*!< CAN bit timing register */
+#define CAN_TMI0(canx)                     REG32((canx) + 0x00000180U)        /*!< CAN transmit mailbox0 identifier register */
+#define CAN_TMP0(canx)                     REG32((canx) + 0x00000184U)        /*!< CAN transmit mailbox0 property register */
+#define CAN_TMDATA00(canx)                 REG32((canx) + 0x00000188U)        /*!< CAN transmit mailbox0 data0 register */
+#define CAN_TMDATA10(canx)                 REG32((canx) + 0x0000018CU)        /*!< CAN transmit mailbox0 data1 register */
+#define CAN_TMI1(canx)                     REG32((canx) + 0x00000190U)        /*!< CAN transmit mailbox1 identifier register */
+#define CAN_TMP1(canx)                     REG32((canx) + 0x00000194U)        /*!< CAN transmit mailbox1 property register */
+#define CAN_TMDATA01(canx)                 REG32((canx) + 0x00000198U)        /*!< CAN transmit mailbox1 data0 register */
+#define CAN_TMDATA11(canx)                 REG32((canx) + 0x0000019CU)        /*!< CAN transmit mailbox1 data1 register */
+#define CAN_TMI2(canx)                     REG32((canx) + 0x000001A0U)        /*!< CAN transmit mailbox2 identifier register */
+#define CAN_TMP2(canx)                     REG32((canx) + 0x000001A4U)        /*!< CAN transmit mailbox2 property register */
+#define CAN_TMDATA02(canx)                 REG32((canx) + 0x000001A8U)        /*!< CAN transmit mailbox2 data0 register */
+#define CAN_TMDATA12(canx)                 REG32((canx) + 0x000001ACU)        /*!< CAN transmit mailbox2 data1 register */
+#define CAN_RFIFOMI0(canx)                 REG32((canx) + 0x000001B0U)        /*!< CAN receive FIFO0 mailbox identifier register */
+#define CAN_RFIFOMP0(canx)                 REG32((canx) + 0x000001B4U)        /*!< CAN receive FIFO0 mailbox property register */
+#define CAN_RFIFOMDATA00(canx)             REG32((canx) + 0x000001B8U)        /*!< CAN receive FIFO0 mailbox data0 register */
+#define CAN_RFIFOMDATA10(canx)             REG32((canx) + 0x000001BCU)        /*!< CAN receive FIFO0 mailbox data1 register */
+#define CAN_RFIFOMI1(canx)                 REG32((canx) + 0x000001C0U)        /*!< CAN receive FIFO1 mailbox identifier register */
+#define CAN_RFIFOMP1(canx)                 REG32((canx) + 0x000001C4U)        /*!< CAN receive FIFO1 mailbox property register */
+#define CAN_RFIFOMDATA01(canx)             REG32((canx) + 0x000001C8U)        /*!< CAN receive FIFO1 mailbox data0 register */
+#define CAN_RFIFOMDATA11(canx)             REG32((canx) + 0x000001CCU)        /*!< CAN receive FIFO1 mailbox data1 register */
+#define CAN_FCTL(canx)                     REG32((canx) + 0x00000200U)        /*!< CAN filter control register */
+#define CAN_FMCFG(canx)                    REG32((canx) + 0x00000204U)        /*!< CAN filter mode register */
+#define CAN_FSCFG(canx)                    REG32((canx) + 0x0000020CU)        /*!< CAN filter scale register */
+#define CAN_FAFIFO(canx)                   REG32((canx) + 0x00000214U)        /*!< CAN filter associated FIFO register */
+#define CAN_FW(canx)                       REG32((canx) + 0x0000021CU)        /*!< CAN filter working register */
+#define CAN_F0DATA0(canx)                  REG32((canx) + 0x00000240U)        /*!< CAN filter 0 data 0 register */
+#define CAN_F1DATA0(canx)                  REG32((canx) + 0x00000248U)        /*!< CAN filter 1 data 0 register */
+#define CAN_F2DATA0(canx)                  REG32((canx) + 0x00000250U)        /*!< CAN filter 2 data 0 register */
+#define CAN_F3DATA0(canx)                  REG32((canx) + 0x00000258U)        /*!< CAN filter 3 data 0 register */
+#define CAN_F4DATA0(canx)                  REG32((canx) + 0x00000260U)        /*!< CAN filter 4 data 0 register */
+#define CAN_F5DATA0(canx)                  REG32((canx) + 0x00000268U)        /*!< CAN filter 5 data 0 register */
+#define CAN_F6DATA0(canx)                  REG32((canx) + 0x00000270U)        /*!< CAN filter 6 data 0 register */
+#define CAN_F7DATA0(canx)                  REG32((canx) + 0x00000278U)        /*!< CAN filter 7 data 0 register */
+#define CAN_F8DATA0(canx)                  REG32((canx) + 0x00000280U)        /*!< CAN filter 8 data 0 register */
+#define CAN_F9DATA0(canx)                  REG32((canx) + 0x00000288U)        /*!< CAN filter 9 data 0 register */
+#define CAN_F10DATA0(canx)                 REG32((canx) + 0x00000290U)        /*!< CAN filter 10 data 0 register */
+#define CAN_F11DATA0(canx)                 REG32((canx) + 0x00000298U)        /*!< CAN filter 11 data 0 register */
+#define CAN_F12DATA0(canx)                 REG32((canx) + 0x000002A0U)        /*!< CAN filter 12 data 0 register */
+#define CAN_F13DATA0(canx)                 REG32((canx) + 0x000002A8U)        /*!< CAN filter 13 data 0 register */
+#define CAN_F14DATA0(canx)                 REG32((canx) + 0x000002B0U)        /*!< CAN filter 14 data 0 register */
+#define CAN_F15DATA0(canx)                 REG32((canx) + 0x000002B8U)        /*!< CAN filter 15 data 0 register */
+#define CAN_F16DATA0(canx)                 REG32((canx) + 0x000002C0U)        /*!< CAN filter 16 data 0 register */
+#define CAN_F17DATA0(canx)                 REG32((canx) + 0x000002C8U)        /*!< CAN filter 17 data 0 register */
+#define CAN_F18DATA0(canx)                 REG32((canx) + 0x000002D0U)        /*!< CAN filter 18 data 0 register */
+#define CAN_F19DATA0(canx)                 REG32((canx) + 0x000002D8U)        /*!< CAN filter 19 data 0 register */
+#define CAN_F20DATA0(canx)                 REG32((canx) + 0x000002E0U)        /*!< CAN filter 20 data 0 register */
+#define CAN_F21DATA0(canx)                 REG32((canx) + 0x000002E8U)        /*!< CAN filter 21 data 0 register */
+#define CAN_F22DATA0(canx)                 REG32((canx) + 0x000002F0U)        /*!< CAN filter 22 data 0 register */
+#define CAN_F23DATA0(canx)                 REG32((canx) + 0x000003F8U)        /*!< CAN filter 23 data 0 register */
+#define CAN_F24DATA0(canx)                 REG32((canx) + 0x00000300U)        /*!< CAN filter 24 data 0 register */
+#define CAN_F25DATA0(canx)                 REG32((canx) + 0x00000308U)        /*!< CAN filter 25 data 0 register */
+#define CAN_F26DATA0(canx)                 REG32((canx) + 0x00000310U)        /*!< CAN filter 26 data 0 register */
+#define CAN_F27DATA0(canx)                 REG32((canx) + 0x00000318U)        /*!< CAN filter 27 data 0 register */
+#define CAN_F0DATA1(canx)                  REG32((canx) + 0x00000244U)        /*!< CAN filter 0 data 1 register */
+#define CAN_F1DATA1(canx)                  REG32((canx) + 0x0000024CU)        /*!< CAN filter 1 data 1 register */
+#define CAN_F2DATA1(canx)                  REG32((canx) + 0x00000254U)        /*!< CAN filter 2 data 1 register */
+#define CAN_F3DATA1(canx)                  REG32((canx) + 0x0000025CU)        /*!< CAN filter 3 data 1 register */
+#define CAN_F4DATA1(canx)                  REG32((canx) + 0x00000264U)        /*!< CAN filter 4 data 1 register */
+#define CAN_F5DATA1(canx)                  REG32((canx) + 0x0000026CU)        /*!< CAN filter 5 data 1 register */
+#define CAN_F6DATA1(canx)                  REG32((canx) + 0x00000274U)        /*!< CAN filter 6 data 1 register */
+#define CAN_F7DATA1(canx)                  REG32((canx) + 0x0000027CU)        /*!< CAN filter 7 data 1 register */
+#define CAN_F8DATA1(canx)                  REG32((canx) + 0x00000284U)        /*!< CAN filter 8 data 1 register */
+#define CAN_F9DATA1(canx)                  REG32((canx) + 0x0000028CU)        /*!< CAN filter 9 data 1 register */
+#define CAN_F10DATA1(canx)                 REG32((canx) + 0x00000294U)        /*!< CAN filter 10 data 1 register */
+#define CAN_F11DATA1(canx)                 REG32((canx) + 0x0000029CU)        /*!< CAN filter 11 data 1 register */
+#define CAN_F12DATA1(canx)                 REG32((canx) + 0x000002A4U)        /*!< CAN filter 12 data 1 register */
+#define CAN_F13DATA1(canx)                 REG32((canx) + 0x000002ACU)        /*!< CAN filter 13 data 1 register */
+#define CAN_F14DATA1(canx)                 REG32((canx) + 0x000002B4U)        /*!< CAN filter 14 data 1 register */
+#define CAN_F15DATA1(canx)                 REG32((canx) + 0x000002BCU)        /*!< CAN filter 15 data 1 register */
+#define CAN_F16DATA1(canx)                 REG32((canx) + 0x000002C4U)        /*!< CAN filter 16 data 1 register */
+#define CAN_F17DATA1(canx)                 REG32((canx) + 0x0000024CU)        /*!< CAN filter 17 data 1 register */
+#define CAN_F18DATA1(canx)                 REG32((canx) + 0x000002D4U)        /*!< CAN filter 18 data 1 register */
+#define CAN_F19DATA1(canx)                 REG32((canx) + 0x000002DCU)        /*!< CAN filter 19 data 1 register */
+#define CAN_F20DATA1(canx)                 REG32((canx) + 0x000002E4U)        /*!< CAN filter 20 data 1 register */
+#define CAN_F21DATA1(canx)                 REG32((canx) + 0x000002ECU)        /*!< CAN filter 21 data 1 register */
+#define CAN_F22DATA1(canx)                 REG32((canx) + 0x000002F4U)        /*!< CAN filter 22 data 1 register */
+#define CAN_F23DATA1(canx)                 REG32((canx) + 0x000002FCU)        /*!< CAN filter 23 data 1 register */
+#define CAN_F24DATA1(canx)                 REG32((canx) + 0x00000304U)        /*!< CAN filter 24 data 1 register */
+#define CAN_F25DATA1(canx)                 REG32((canx) + 0x0000030CU)        /*!< CAN filter 25 data 1 register */
+#define CAN_F26DATA1(canx)                 REG32((canx) + 0x00000314U)        /*!< CAN filter 26 data 1 register */
+#define CAN_F27DATA1(canx)                 REG32((canx) + 0x0000031CU)        /*!< 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 auto_retrans;                                         /*!< automatic retransmission mode */
+    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 standard 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 type */
+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 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 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 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 /* GD32F30X_CAN_H */

+ 81 - 0
app/LIB/Include/gd32f30x_crc.h

@@ -0,0 +1,81 @@
+/*!
+    \file    gd32f30x_crc.h
+    \brief   definitions for the CRC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_CRC_H
+#define GD32F30X_CRC_H
+
+#include "gd32f30x.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(CRC_DATA) to the value of 0xFFFFFFFF */
+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(const uint32_t *array, uint32_t size);
+
+#endif /* GD32F30X_CRC_H */

+ 185 - 0
app/LIB/Include/gd32f30x_ctc.h

@@ -0,0 +1,185 @@
+/*!
+    \file    gd32f30x_ctc.h
+    \brief   definitions for the CTC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_CTC_H
+#define GD32F30X_CTC_H
+
+#include "gd32f30x.h"
+
+/* CTC definitions */
+#define CTC                          CTC_BASE                        /*!< CTC base address */
+
+/* registers definitions */
+#define CTC_CTL0                     REG32((CTC) + 0x00000000U)      /*!< CTC control register 0 */
+#define CTC_CTL1                     REG32((CTC) + 0x00000004U)      /*!< CTC control register 1 */
+#define CTC_STAT                     REG32((CTC) + 0x00000008U)      /*!< CTC status register */
+#define CTC_INTC                     REG32((CTC) + 0x0000000CU)      /*!< CTC interrupt clear register */
+
+/* bits definitions */
+/* CTC_CTL0 */
+#define CTC_CTL0_CKOKIE              BIT(0)                    /*!< clock trim OK(CKOKIF) interrupt enable */ 
+#define CTC_CTL0_CKWARNIE            BIT(1)                    /*!< clock trim warning(CKWARNIF) interrupt enable */
+#define CTC_CTL0_ERRIE               BIT(2)                    /*!< error(ERRIF) interrupt enable */
+#define CTC_CTL0_EREFIE              BIT(3)                    /*!< EREFIF interrupt enable */
+#define CTC_CTL0_CNTEN               BIT(5)                    /*!< CTC counter enable */
+#define CTC_CTL0_AUTOTRIM            BIT(6)                    /*!< hardware automatically trim mode */
+#define CTC_CTL0_SWREFPUL            BIT(7)                    /*!< software reference source sync pulse */
+#define CTC_CTL0_TRIMVALUE           BITS(8,13)                /*!< IRC48M trim value */
+
+/* CTC_CTL1 */
+#define CTC_CTL1_RLVALUE             BITS(0,15)                /*!< CTC counter reload value */
+#define CTC_CTL1_CKLIM               BITS(16,23)               /*!< clock trim base limit value */
+#define CTC_CTL1_REFPSC              BITS(24,26)               /*!< reference signal source prescaler */
+#define CTC_CTL1_REFSEL              BITS(28,29)               /*!< reference signal source selection */
+#define CTC_CTL1_REFPOL              BIT(31)                   /*!< reference signal source polarity */
+
+/* CTC_STAT */
+#define CTC_STAT_CKOKIF              BIT(0)                    /*!< clock trim OK interrupt flag */
+#define CTC_STAT_CKWARNIF            BIT(1)                    /*!< clock trim warning interrupt flag */
+#define CTC_STAT_ERRIF               BIT(2)                    /*!< error interrupt flag */
+#define CTC_STAT_EREFIF              BIT(3)                    /*!< expect reference interrupt flag */
+#define CTC_STAT_CKERR               BIT(8)                    /*!< clock trim error bit */
+#define CTC_STAT_REFMISS             BIT(9)                    /*!< reference sync pulse miss */
+#define CTC_STAT_TRIMERR             BIT(10)                   /*!< trim value error bit */
+#define CTC_STAT_REFDIR              BIT(15)                   /*!< CTC trim counter direction when reference sync pulse occurred */
+#define CTC_STAT_REFCAP              BITS(16,31)               /*!< CTC counter capture when reference sync pulse occurred */
+
+/* CTC_INTC */
+#define CTC_INTC_CKOKIC              BIT(0)                    /*!< CKOKIF interrupt clear bit */
+#define CTC_INTC_CKWARNIC            BIT(1)                    /*!< CKWARNIF interrupt clear bit */
+#define CTC_INTC_ERRIC               BIT(2)                    /*!< ERRIF interrupt clear bit */
+#define CTC_INTC_EREFIC              BIT(3)                    /*!< EREFIF interrupt clear bit */
+
+/* constants definitions */
+/* hardware automatically trim mode definitions */
+#define CTC_HARDWARE_TRIM_MODE_ENABLE                    CTC_CTL0_AUTOTRIM            /*!< hardware automatically trim mode enable*/
+#define CTC_HARDWARE_TRIM_MODE_DISABLE                   ((uint32_t)0x00000000U)      /*!< hardware automatically trim mode disable*/
+
+/* reference signal source polarity definitions */
+#define CTC_REFSOURCE_POLARITY_FALLING                   CTC_CTL1_REFPOL              /*!< reference signal source polarity is falling edge*/
+#define CTC_REFSOURCE_POLARITY_RISING                    ((uint32_t)0x00000000U)      /*!< reference signal source polarity is rising edge*/
+
+/* reference signal source selection definitions */
+#define CTL1_REFSEL(regval)                              (BITS(28,29) & ((uint32_t)(regval) << 28))
+#define CTC_REFSOURCE_GPIO                               CTL1_REFSEL(0)               /*!< GPIO is selected */
+#define CTC_REFSOURCE_LXTAL                              CTL1_REFSEL(1)               /*!< LXTAL is selected */
+
+/* reference signal source prescaler definitions */
+#define CTL1_REFPSC(regval)                              (BITS(24,26) & ((uint32_t)(regval) << 24))
+#define CTC_REFSOURCE_PSC_OFF                            CTL1_REFPSC(0)               /*!< reference signal not divided */
+#define CTC_REFSOURCE_PSC_DIV2                           CTL1_REFPSC(1)               /*!< reference signal divided by 2 */
+#define CTC_REFSOURCE_PSC_DIV4                           CTL1_REFPSC(2)               /*!< reference signal divided by 4 */
+#define CTC_REFSOURCE_PSC_DIV8                           CTL1_REFPSC(3)               /*!< reference signal divided by 8 */
+#define CTC_REFSOURCE_PSC_DIV16                          CTL1_REFPSC(4)               /*!< reference signal divided by 16 */
+#define CTC_REFSOURCE_PSC_DIV32                          CTL1_REFPSC(5)               /*!< reference signal divided by 32 */
+#define CTC_REFSOURCE_PSC_DIV64                          CTL1_REFPSC(6)               /*!< reference signal divided by 64 */
+#define CTC_REFSOURCE_PSC_DIV128                         CTL1_REFPSC(7)               /*!< reference signal divided by 128 */
+
+/* CTC interrupt enable definitions */
+#define CTC_INT_CKOK                                     CTC_CTL0_CKOKIE             /*!< clock trim OK interrupt enable */
+#define CTC_INT_CKWARN                                   CTC_CTL0_CKWARNIE           /*!< clock trim warning interrupt enable */
+#define CTC_INT_ERR                                      CTC_CTL0_ERRIE              /*!< error interrupt enable */
+#define CTC_INT_EREF                                     CTC_CTL0_EREFIE             /*!< expect reference interrupt enable */
+
+/* CTC interrupt source definitions */
+#define CTC_INT_FLAG_CKOK                                CTC_STAT_CKOKIF             /*!< clock trim OK interrupt flag */
+#define CTC_INT_FLAG_CKWARN                              CTC_STAT_CKWARNIF           /*!< clock trim warning interrupt flag */
+#define CTC_INT_FLAG_ERR                                 CTC_STAT_ERRIF              /*!< error interrupt flag */
+#define CTC_INT_FLAG_EREF                                CTC_STAT_EREFIF             /*!< expect reference interrupt flag */
+#define CTC_INT_FLAG_CKERR                               CTC_STAT_CKERR              /*!< clock trim error bit */
+#define CTC_INT_FLAG_REFMISS                             CTC_STAT_REFMISS            /*!< reference sync pulse miss */
+#define CTC_INT_FLAG_TRIMERR                             CTC_STAT_TRIMERR            /*!< trim value error */
+
+/* CTC flag definitions */
+#define CTC_FLAG_CKOK                                    CTC_STAT_CKOKIF             /*!< clock trim OK flag */
+#define CTC_FLAG_CKWARN                                  CTC_STAT_CKWARNIF           /*!< clock trim warning flag */
+#define CTC_FLAG_ERR                                     CTC_STAT_ERRIF              /*!< error flag */
+#define CTC_FLAG_EREF                                    CTC_STAT_EREFIF             /*!< expect reference flag */
+#define CTC_FLAG_CKERR                                   CTC_STAT_CKERR              /*!< clock trim error bit */
+#define CTC_FLAG_REFMISS                                 CTC_STAT_REFMISS            /*!< reference sync pulse miss */
+#define CTC_FLAG_TRIMERR                                 CTC_STAT_TRIMERR            /*!< trim value error bit */
+
+/* function declarations */
+/* reset ctc clock trim controller */
+void ctc_deinit(void);
+/* enable CTC trim counter */
+void ctc_counter_enable(void);
+/* disable CTC trim counter */
+void ctc_counter_disable(void);
+
+/* configure the IRC48M trim value */
+void ctc_irc48m_trim_value_config(uint8_t trim_value);
+/* generate software reference source sync pulse */
+void ctc_software_refsource_pulse_generate(void);
+/* configure hardware automatically trim mode */
+void ctc_hardware_trim_mode_config(uint32_t hardmode);
+
+/* configure reference signal source polarity */
+void ctc_refsource_polarity_config(uint32_t polarity);
+/* select reference signal source */
+void ctc_refsource_signal_select(uint32_t refs);
+/* configure reference signal source prescaler */
+void ctc_refsource_prescaler_config(uint32_t prescaler);
+/* configure clock trim base limit value */
+void ctc_clock_limit_value_config(uint8_t limit_value);
+/* configure CTC counter reload value */
+void ctc_counter_reload_value_config(uint16_t reload_value);
+
+/* read CTC counter capture value when reference sync pulse occurred */
+uint16_t ctc_counter_capture_value_read(void);
+/* read CTC trim counter direction when reference sync pulse occurred */
+FlagStatus ctc_counter_direction_read(void);
+/* read CTC counter reload value */
+uint16_t ctc_counter_reload_value_read(void);
+/* read the IRC48M trim value */
+uint8_t ctc_irc48m_trim_value_read(void);
+
+/* interrupt & flag functions */
+/* get CTC flag */
+FlagStatus ctc_flag_get(uint32_t flag);
+/* clear CTC flag */
+void ctc_flag_clear(uint32_t flag);
+/* enable the CTC interrupt */
+void ctc_interrupt_enable(uint32_t interrupt);
+/* disable the CTC interrupt */
+void ctc_interrupt_disable(uint32_t interrupt);
+/* get CTC interrupt flag */
+FlagStatus ctc_interrupt_flag_get(uint32_t int_flag); 
+/* clear CTC interrupt flag */
+void ctc_interrupt_flag_clear(uint32_t int_flag);
+
+#endif /* GD32F30X_CTC_H */

+ 250 - 0
app/LIB/Include/gd32f30x_dac.h

@@ -0,0 +1,250 @@
+/*!
+    \file    gd32f30x_dac.h
+    \brief   definitions for the DAC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_DAC_H
+#define GD32F30X_DAC_H
+
+#include "gd32f30x.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/turn 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(GD32F30X_HD) || defined(GD32F30X_XD))
+#define DAC_TRIGGER_T7_TRGO          CTL_DTSEL(1)               /*!< TIMER7 TRGO */
+#elif defined(GD32F30X_CL)
+#define DAC_TRIGGER_T2_TRGO          CTL_DTSEL(1)               /*!< TIMER2 TRGO */
+#endif /* GD32F30X_HD and GD32F30X_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 12 bit alignment */
+#define DAC_ALIGN_12B_L              DATA_ALIGN(1)              /*!< data left 12 bit alignment */
+#define DAC_ALIGN_8B_R               DATA_ALIGN(2)              /*!< data right 8 bit 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 /* GD32F30X_DAC_H */

+ 149 - 0
app/LIB/Include/gd32f30x_dbg.h

@@ -0,0 +1,149 @@
+/*!
+    \file    gd32f30x_dbg.h
+    \brief   definitions for the DBG
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_DBG_H
+#define GD32F30X_DBG_H
+
+#include "gd32f30x.h"
+
+/* DBG definitions */
+#define DBG                      DBG_BASE
+
+/* registers definitions */
+#define DBG_ID                   REG32(DBG + 0x00U)         /*!< DBG_ID code register */
+#define DBG_CTL0                 REG32(DBG + 0x04U)         /*!< DBG control register 0 */
+
+/* bits definitions */
+/* DBG_ID */
+#define DBG_ID_ID_CODE           BITS(0,31)                 /*!< DBG ID code values */
+
+/* DBG_CTL0 */
+#define DBG_CTL0_SLP_HOLD        BIT(0)                     /*!< keep debugger connection during sleep mode */
+#define DBG_CTL0_DSLP_HOLD       BIT(1)                     /*!< keep debugger connection during deepsleep mode */
+#define DBG_CTL0_STB_HOLD        BIT(2)                     /*!< keep debugger connection during standby mode */
+#define DBG_CTL0_TRACE_IOEN      BIT(5)                     /*!< enable trace pin assignment */
+#define DBG_CTL0_FWDGT_HOLD      BIT(8)                     /*!< debug FWDGT kept when core is halted */
+#define DBG_CTL0_WWDGT_HOLD      BIT(9)                     /*!< debug WWDGT kept when core is halted */
+#define DBG_CTL0_TIMER0_HOLD     BIT(10)                    /*!< hold TIMER0 counter when core is halted */
+#define DBG_CTL0_TIMER1_HOLD     BIT(11)                    /*!< hold TIMER1 counter when core is halted */
+#define DBG_CTL0_TIMER2_HOLD     BIT(12)                    /*!< hold TIMER2 counter when core is halted */
+#define DBG_CTL0_TIMER3_HOLD     BIT(13)                    /*!< hold TIMER3 counter when core is halted */
+#define DBG_CTL0_CAN0_HOLD       BIT(14)                    /*!< debug CAN0 kept when core is halted */
+#define DBG_CTL0_I2C0_HOLD       BIT(15)                    /*!< hold I2C0 smbus when core is halted */
+#define DBG_CTL0_I2C1_HOLD       BIT(16)                    /*!< hold I2C1 smbus when core is halted */
+#define DBG_CTL0_TIMER7_HOLD     BIT(17)                    /*!< hold TIMER7 counter when core is halted */
+#define DBG_CTL0_TIMER4_HOLD     BIT(18)                    /*!< hold TIMER4 counter when core is halted */
+#define DBG_CTL0_TIMER5_HOLD     BIT(19)                    /*!< hold TIMER5 counter when core is halted */
+#define DBG_CTL0_TIMER6_HOLD     BIT(20)                    /*!< hold TIMER6 counter when core is halted */
+#ifdef GD32F30X_CL
+#define DBG_CTL0_CAN1_HOLD       BIT(21)                    /*!< debug CAN1 kept when core is halted */
+#endif /* GD32F30X_CL */
+#ifndef GD32F30X_HD
+#define DBG_CTL0_TIMER11_HOLD    BIT(25)                    /*!< hold TIMER11 counter when core is halted */
+#define DBG_CTL0_TIMER12_HOLD    BIT(26)                    /*!< hold TIMER12 counter when core is halted */
+#define DBG_CTL0_TIMER13_HOLD    BIT(27)                    /*!< hold TIMER13 counter when core is halted */
+#define DBG_CTL0_TIMER8_HOLD     BIT(28)                    /*!< hold TIMER8 counter when core is halted */
+#define DBG_CTL0_TIMER9_HOLD     BIT(29)                    /*!< hold TIMER9 counter when core is halted */
+#define DBG_CTL0_TIMER10_HOLD    BIT(30)                    /*!< hold TIMER10 counter when core is halted */
+#endif /* GD32F30X_HD */
+
+/* constants definitions */
+#define DBG_LOW_POWER_SLEEP      DBG_CTL0_SLP_HOLD          /*!< keep debugger connection during sleep mode */
+#define DBG_LOW_POWER_DEEPSLEEP  DBG_CTL0_DSLP_HOLD         /*!< keep debugger connection during deepsleep mode */
+#define DBG_LOW_POWER_STANDBY    DBG_CTL0_STB_HOLD          /*!< keep debugger connection during standby mode */
+
+/* define the peripheral debug hold bit position and its register index offset */
+#define DBG_REGIDX_BIT(regidx, bitpos)      (((regidx) << 6) | (bitpos))
+#define DBG_REG_VAL(periph)                 (REG32(DBG + ((uint32_t)(periph) >> 6)))
+#define DBG_BIT_POS(val)                    ((uint32_t)(val) & 0x1FU)
+
+/* register index */
+enum dbg_reg_idx
+{
+    DBG_IDX_CTL0  = 0x04U
+};
+
+typedef enum
+{
+    DBG_FWDGT_HOLD             = DBG_REGIDX_BIT(DBG_IDX_CTL0, 8U),                    /*!< debug FWDGT kept when core is halted */
+    DBG_WWDGT_HOLD             = DBG_REGIDX_BIT(DBG_IDX_CTL0, 9U),                    /*!< debug WWDGT kept when core is halted */
+    DBG_TIMER0_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 10U),                   /*!< hold TIMER0 counter when core is halted */
+    DBG_TIMER1_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 11U),                   /*!< hold TIMER1 counter when core is halted */
+    DBG_TIMER2_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 12U),                   /*!< hold TIMER2 counter when core is halted */
+    DBG_TIMER3_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 13U),                   /*!< hold TIMER3 counter when core is halted */
+    DBG_CAN0_HOLD              = DBG_REGIDX_BIT(DBG_IDX_CTL0, 14U),                   /*!< debug CAN0 kept when core is halted */
+    DBG_I2C0_HOLD              = DBG_REGIDX_BIT(DBG_IDX_CTL0, 15U),                   /*!< hold I2C0 smbus when core is halted */
+    DBG_I2C1_HOLD              = DBG_REGIDX_BIT(DBG_IDX_CTL0, 16U),                   /*!< hold I2C1 smbus when core is halted */
+    DBG_TIMER7_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 17U),                   /*!< hold TIMER7 counter when core is halted */
+    DBG_TIMER4_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 18U),                   /*!< hold TIMER4 counter when core is halted */
+    DBG_TIMER5_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 19U),                   /*!< hold TIMER5 counter when core is halted */
+    DBG_TIMER6_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 20U),                   /*!< hold TIMER6 counter when core is halted */
+#ifdef GD32F30X_CL
+    DBG_CAN1_HOLD              = DBG_REGIDX_BIT(DBG_IDX_CTL0, 21U),                   /*!< debug CAN1 kept when core is halted */
+#endif /* GD32F30X_CL */
+#ifndef GD32F30X_HD
+    DBG_TIMER11_HOLD           = DBG_REGIDX_BIT(DBG_IDX_CTL0, 25U),                   /*!< hold TIMER11 counter when core is halted */
+    DBG_TIMER12_HOLD           = DBG_REGIDX_BIT(DBG_IDX_CTL0, 26U),                   /*!< hold TIMER12 counter when core is halted */
+    DBG_TIMER13_HOLD           = DBG_REGIDX_BIT(DBG_IDX_CTL0, 27U),                   /*!< hold TIMER13 counter when core is halted */
+    DBG_TIMER8_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 28U),                   /*!< hold TIMER8 counter when core is halted */
+    DBG_TIMER9_HOLD            = DBG_REGIDX_BIT(DBG_IDX_CTL0, 29U),                   /*!< hold TIMER9 counter when core is halted */
+    DBG_TIMER10_HOLD           = DBG_REGIDX_BIT(DBG_IDX_CTL0, 30U),                   /*!< hold TIMER10 counter when core is halted */
+#endif /* GD32F30X_HD */
+}dbg_periph_enum;
+
+/* function declarations */
+/* deinitialize the DBG */
+void dbg_deinit(void);
+/* read DBG_ID code register */
+uint32_t dbg_id_get(void);
+
+/* 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);
+
+/* 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);
+
+/* enable trace pin assignment */
+void dbg_trace_pin_enable(void);
+/* disable trace pin assignment */
+void dbg_trace_pin_disable(void);
+
+#endif /* GD32F30X_DBG_H */

+ 285 - 0
app/LIB/Include/gd32f30x_dma.h

@@ -0,0 +1,285 @@
+/*!
+    \file    gd32f30x_dma.h
+    \brief   definitions for the DMA
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_DMA_H
+#define GD32F30X_DMA_H
+
+#include "gd32f30x.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 Channel0 */
+    DMA_CH1,                    /*!< DMA Channel1 */ 
+    DMA_CH2,                    /*!< DMA Channel2 */ 
+    DMA_CH3,                    /*!< DMA Channel3 */ 
+    DMA_CH4,                    /*!< DMA Channel4 */ 
+    DMA_CH5,                    /*!< DMA Channel5 */ 
+    DMA_CH6                     /*!< DMA Channel6 */
+} 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)0x0000U)                              /*!< read from peripheral and write to memory */
+#define DMA_MEMORY_TO_PERIPHERAL            ((uint8_t)0x0001U)                              /*!< read from memory and write to peripheral */
+
+/* peripheral increasing mode */
+#define DMA_PERIPH_INCREASE_DISABLE         ((uint8_t)0x0000U)                              /*!< next address of peripheral is fixed address mode */
+#define DMA_PERIPH_INCREASE_ENABLE          ((uint8_t)0x0001U)                              /*!< next address of peripheral is increasing address mode */
+
+/* memory increasing mode */
+#define DMA_MEMORY_INCREASE_DISABLE         ((uint8_t)0x0000U)                              /*!< next address of memory is fixed address mode */
+#define DMA_MEMORY_INCREASE_ENABLE          ((uint8_t)0x0001U)                              /*!< next address of memory is increasing address mode */
+
+/* transfer data size of peripheral */
+#define CHCTL_PWIDTH(regval)                (BITS(8,9) & ((uint32_t)(regval) << 8))         /*!< transfer data size of peripheral */
+#define DMA_PERIPHERAL_WIDTH_8BIT           CHCTL_PWIDTH(0)                                 /*!< transfer data size of peripheral is 8-bit */
+#define DMA_PERIPHERAL_WIDTH_16BIT          CHCTL_PWIDTH(1)                                 /*!< transfer data size of peripheral is 16-bit */
+#define DMA_PERIPHERAL_WIDTH_32BIT          CHCTL_PWIDTH(2)                                 /*!< transfer data size of peripheral is 32-bit */
+
+/* transfer data size of memory */
+#define CHCTL_MWIDTH(regval)                (BITS(10,11) & ((uint32_t)(regval) << 10))      /*!< transfer data size of memory */
+#define DMA_MEMORY_WIDTH_8BIT               CHCTL_MWIDTH(0)                                 /*!< transfer data size of memory is 8-bit */
+#define DMA_MEMORY_WIDTH_16BIT              CHCTL_MWIDTH(1)                                 /*!< transfer data size of memory is 16-bit */
+#define DMA_MEMORY_WIDTH_32BIT              CHCTL_MWIDTH(2)                                 /*!< transfer data size of memory is 32-bit */
+
+/* channel priority level */
+#define CHCTL_PRIO(regval)                  (BITS(12,13) & ((uint32_t)(regval) << 12))      /*!< DMA channel priority level */
+#define DMA_PRIORITY_LOW                    CHCTL_PRIO(0)                                   /*!< low priority */
+#define DMA_PRIORITY_MEDIUM                 CHCTL_PRIO(1)                                   /*!< medium priority */
+#define DMA_PRIORITY_HIGH                   CHCTL_PRIO(2)                                   /*!< high priority */
+#define DMA_PRIORITY_ULTRA_HIGH             CHCTL_PRIO(3)                                   /*!< ultra high priority */
+
+/* memory to memory mode */
+#define DMA_MEMORY_TO_MEMORY_DISABLE        ((uint32_t)0x00000000U)
+#define DMA_MEMORY_TO_MEMORY_ENABLE         ((uint32_t)0x00000001U)
+
+/* 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, uint32_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 DMA a channel flag */
+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 DMA a channel flag */
+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 /* GD32F30X_DMA_H */

File diff suppressed because it is too large
+ 1702 - 0
app/LIB/Include/gd32f30x_enet.h


+ 446 - 0
app/LIB/Include/gd32f30x_exmc.h

@@ -0,0 +1,446 @@
+/*!
+    \file    gd32f30x_exmc.h
+    \brief   definitions for the EXMC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_EXMC_H
+#define GD32F30X_EXMC_H
+
+#include "gd32f30x.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 register0 */
+#define EXMC_SNTCFG0                      REG32(EXMC + 0x04U)           /*!< EXMC SRAM/NOR flash timing configuration register0 */
+#define EXMC_SNWTCFG0                     REG32(EXMC + 0x104U)          /*!< EXMC SRAM/NOR flash write timing configuration register0 */
+
+#define EXMC_SNCTL1                       REG32(EXMC + 0x08U)           /*!< EXMC SRAM/NOR flash control register1 */
+#define EXMC_SNTCFG1                      REG32(EXMC + 0x0CU)           /*!< EXMC SRAM/NOR flash timing configuration register1 */
+#define EXMC_SNWTCFG1                     REG32(EXMC + 0x10CU)          /*!< EXMC SRAM/NOR flash write timing configuration register1 */
+
+#define EXMC_SNCTL2                       REG32(EXMC + 0x10U)           /*!< EXMC SRAM/NOR flash control register2 */
+#define EXMC_SNTCFG2                      REG32(EXMC + 0x14U)           /*!< EXMC SRAM/NOR flash timing configuration register2 */
+#define EXMC_SNWTCFG2                     REG32(EXMC + 0x114U)          /*!< EXMC SRAM/NOR flash write timing configuration register2 */
+
+#define EXMC_SNCTL3                       REG32(EXMC + 0x18U)           /*!< EXMC SRAM/NOR flash control register3 */
+#define EXMC_SNTCFG3                      REG32(EXMC + 0x1CU)           /*!< EXMC SRAM/NOR flash timing configuration register3 */
+#define EXMC_SNWTCFG3                     REG32(EXMC + 0x11CU)          /*!< EXMC SRAM/NOR flash write timing configuration register3 */
+
+/* NAND/PC card */
+#define EXMC_NPCTL1                       REG32(EXMC + 0x60U)           /*!< EXMC NAND/PC card control register1 */
+#define EXMC_NPINTEN1                     REG32(EXMC + 0x64U)           /*!< EXMC NAND/PC card interrupt enable register1 */
+#define EXMC_NPCTCFG1                     REG32(EXMC + 0x68U)           /*!< EXMC NAND/PC card common space timing configuration register1 */
+#define EXMC_NPATCFG1                     REG32(EXMC + 0x6CU)           /*!< EXMC NAND/PC card attribute space timing configuration register1 */
+#define EXMC_NECC1                        REG32(EXMC + 0x74U)           /*!< EXMC NAND ECC register1 */
+
+#define EXMC_NPCTL2                       REG32(EXMC + 0x80U)           /*!< EXMC NAND/PC card control register2 */
+#define EXMC_NPINTEN2                     REG32(EXMC + 0x84U)           /*!< EXMC NAND/PC card interrupt enable register2 */
+#define EXMC_NPCTCFG2                     REG32(EXMC + 0x88U)           /*!< EXMC NAND/PC card common space timing configuration register2 */
+#define EXMC_NPATCFG2                     REG32(EXMC + 0x8CU)           /*!< EXMC NAND/PC card attribute space timing configuration register2 */
+#define EXMC_NECC2                        REG32(EXMC + 0x94U)           /*!< EXMC NAND ECC register2 */
+
+#define EXMC_NPCTL3                       REG32(EXMC + 0xA0U)           /*!< EXMC NAND/PC card control register3 */
+#define EXMC_NPINTEN3                     REG32(EXMC + 0xA4U)           /*!< EXMC NAND/PC card interrupt enable register3 */
+#define EXMC_NPCTCFG3                     REG32(EXMC + 0xA8U)           /*!< EXMC NAND/PC card common space timing configuration register3 */
+#define EXMC_NPATCFG3                     REG32(EXMC + 0xACU)           /*!< EXMC NAND/PC card attribute space timing configuration register3 */
+#define EXMC_PIOTCFG3                     REG32(EXMC + 0xB0U)           /*!< EXMC PC card I/O space timing configuration register */
+
+/* bits definitions */
+/* 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 enable */
+#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 enable */
+#define EXMC_SNCTL_CPS                    BITS(16,18)                   /*!< CRAM page size */
+#define EXMC_SNCTL_SYNCWR                 BIT(19)                       /*!< synchronous write config */
+
+/* EXMC_SNTCFGx,x=0..3 */
+#define EXMC_SNTCFG_ASET                  BITS(0,3)                     /*!< asynchronous address setup time */
+#define EXMC_SNTCFG_AHLD                  BITS(4,7)                     /*!< asynchronous address hold time */
+#define EXMC_SNTCFG_DSET                  BITS(8,15)                    /*!< asynchronous 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)                   /*!< synchronous 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)                     /*!< asynchronous address setup time */
+#define EXMC_SNWTCFG_WAHLD                BITS(4,7)                     /*!< asynchronous address hold time */
+#define EXMC_SNWTCFG_WDSET                BITS(8,15)                    /*!< asynchronous data setup time */
+#define EXMC_SNWTCFG_WBUSLAT              BITS(16,19)                   /*!< bus latency */
+#define EXMC_SNWTCFG_WASYNCMOD            BITS(28,29)                   /*!< asynchronous access mode */
+
+/* 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;                                              /*!< enable or disable 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;                                              /*!< enable or disable the wait feature */
+    exmc_nand_pccard_timing_parameter_struct*  common_space_timing;     /*!< the timing parameters for PC card common space */
+    exmc_nand_pccard_timing_parameter_struct*  attribute_space_timing;  /*!< the timing parameters for PC card attribute space */  
+    exmc_nand_pccard_timing_parameter_struct*  io_space_timing;         /*!< the timing parameters for PC card IO space */
+}exmc_pccard_parameter_struct;
+
+/* EXMC_register address */
+#define EXMC_SNCTL(region)                REG32(EXMC + 0x08U * (region))                  /*!< EXMC SRAM/NOR flash control registers, region = 0,1,2,3 */
+#define EXMC_SNTCFG(region)               REG32(EXMC + 0x04U + 0x08U * (region))          /*!< EXMC SRAM/NOR flash timing configuration registers, region = 0,1,2,3 */
+#define EXMC_SNWTCFG(region)              REG32(EXMC + 0x104U + 0x08U * (region))         /*!< EXMC SRAM/NOR flash write timing configuration registers, region = 0,1,2,3 */
+
+#define EXMC_NPCTL(bank)                  REG32(EXMC + 0x40U + 0x20U * (bank))            /*!< EXMC NAND/PC card control registers, bank = 1,2,3 */
+#define EXMC_NPINTEN(bank)                REG32(EXMC + 0x44U + 0x20U * (bank))            /*!< EXMC NAND/PC card interrupt enable registers, bank = 1,2,3 */
+#define EXMC_NPCTCFG(bank)                REG32(EXMC + 0x48U + 0x20U * (bank))            /*!< EXMC NAND/PC card common space timing configuration registers, bank = 1,2,3 */
+#define EXMC_NPATCFG(bank)                REG32(EXMC + 0x4CU + 0x20U * (bank))            /*!< EXMC NAND/PC card attribute space timing configuration registers, bank = 1,2,3 */
+#define EXMC_NECC(bank)                   REG32(EXMC + 0x54U + 0x20U * (bank))            /*!< EXMC NAND ECC registers, bank = 1,2 */
+
+/* CRAM page size */
+#define SNCTL_CPS(regval)                 (BITS(16,18) & ((uint32_t)(regval) << 16))
+#define EXMC_CRAM_AUTO_SPLIT              SNCTL_CPS(0)                  /*!< automatic burst split on page boundary crossing */
+#define EXMC_CRAM_PAGE_SIZE_128_BYTES     SNCTL_CPS(1)                  /*!< page size is 128 bytes */
+#define EXMC_CRAM_PAGE_SIZE_256_BYTES     SNCTL_CPS(2)                  /*!< page size is 256 bytes */
+#define EXMC_CRAM_PAGE_SIZE_512_BYTES     SNCTL_CPS(3)                  /*!< page size is 512 bytes */
+#define EXMC_CRAM_PAGE_SIZE_1024_BYTES    SNCTL_CPS(4)                  /*!< page size is 1024 bytes */
+
+/* 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 is 8 bits */
+#define EXMC_NOR_DATABUS_WIDTH_16B        SNCTL_NRW(1)                  /*!< NOR data width is 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 of first burst access is 2 EXMC_CLK */
+#define EXMC_DATALAT_3_CLK                SNTCFG_DLAT(1)                /*!< data latency of first burst access is 3 EXMC_CLK */
+#define EXMC_DATALAT_4_CLK                SNTCFG_DLAT(2)                /*!< data latency of first burst access is 4 EXMC_CLK */
+#define EXMC_DATALAT_5_CLK                SNTCFG_DLAT(3)                /*!< data latency of first burst access is 5 EXMC_CLK */
+#define EXMC_DATALAT_6_CLK                SNTCFG_DLAT(4)                /*!< data latency of first burst access is 6 EXMC_CLK */
+#define EXMC_DATALAT_7_CLK                SNTCFG_DLAT(5)                /*!< data latency of first burst access is 7 EXMC_CLK */
+#define EXMC_DATALAT_8_CLK                SNTCFG_DLAT(6)                /*!< data latency of first burst access is 8 EXMC_CLK */
+#define EXMC_DATALAT_9_CLK                SNTCFG_DLAT(7)                /*!< data latency of first burst access is 9 EXMC_CLK */
+#define EXMC_DATALAT_10_CLK               SNTCFG_DLAT(8)                /*!< data latency of first burst access is 10 EXMC_CLK */
+#define EXMC_DATALAT_11_CLK               SNTCFG_DLAT(9)                /*!< data latency of first burst access is 11 EXMC_CLK */
+#define EXMC_DATALAT_12_CLK               SNTCFG_DLAT(10)               /*!< data latency of first burst access is 12 EXMC_CLK */
+#define EXMC_DATALAT_13_CLK               SNTCFG_DLAT(11)               /*!< data latency of first burst access is 13 EXMC_CLK */
+#define EXMC_DATALAT_14_CLK               SNTCFG_DLAT(12)               /*!< data latency of first burst access is 14 EXMC_CLK */
+#define EXMC_DATALAT_15_CLK               SNTCFG_DLAT(13)               /*!< data latency of first burst access is 15 EXMC_CLK */
+#define EXMC_DATALAT_16_CLK               SNTCFG_DLAT(14)               /*!< data latency of first burst access is 16 EXMC_CLK */
+#define EXMC_DATALAT_17_CLK               SNTCFG_DLAT(15)               /*!< data latency of first burst access is 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)               /*!< EXMC_CLK = HCLK/2 */
+#define EXMC_SYN_CLOCK_RATIO_3_CLK        SNTCFG_CKDIV(2)               /*!< EXMC_CLK = HCLK/3 */
+#define EXMC_SYN_CLOCK_RATIO_4_CLK        SNTCFG_CKDIV(3)               /*!< EXMC_CLK = HCLK/4 */
+#define EXMC_SYN_CLOCK_RATIO_5_CLK        SNTCFG_CKDIV(4)               /*!< EXMC_CLK = HCLK/5 */
+#define EXMC_SYN_CLOCK_RATIO_6_CLK        SNTCFG_CKDIV(5)               /*!< EXMC_CLK = HCLK/6 */
+#define EXMC_SYN_CLOCK_RATIO_7_CLK        SNTCFG_CKDIV(6)               /*!< EXMC_CLK = HCLK/7 */
+#define EXMC_SYN_CLOCK_RATIO_8_CLK        SNTCFG_CKDIV(7)               /*!< EXMC_CLK = HCLK/8 */
+#define EXMC_SYN_CLOCK_RATIO_9_CLK        SNTCFG_CKDIV(8)               /*!< EXMC_CLK = HCLK/9 */
+#define EXMC_SYN_CLOCK_RATIO_10_CLK       SNTCFG_CKDIV(9)               /*!< EXMC_CLK = HCLK/10 */
+#define EXMC_SYN_CLOCK_RATIO_11_CLK       SNTCFG_CKDIV(10)              /*!< EXMC_CLK = HCLK/11 */
+#define EXMC_SYN_CLOCK_RATIO_12_CLK       SNTCFG_CKDIV(11)              /*!< EXMC_CLK = HCLK/12 */
+#define EXMC_SYN_CLOCK_RATIO_13_CLK       SNTCFG_CKDIV(12)              /*!< EXMC_CLK = HCLK/13 */
+#define EXMC_SYN_CLOCK_RATIO_14_CLK       SNTCFG_CKDIV(13)              /*!< EXMC_CLK = HCLK/14 */
+#define EXMC_SYN_CLOCK_RATIO_15_CLK       SNTCFG_CKDIV(14)              /*!< EXMC_CLK = HCLK/15 */
+#define EXMC_SYN_CLOCK_RATIO_16_CLK       SNTCFG_CKDIV(15)              /*!< 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)                /* ECC size is 256 bytes */
+#define EXMC_ECC_SIZE_512BYTES            NPCTL_ECCSZ(1)                /* ECC size is 512 bytes */
+#define EXMC_ECC_SIZE_1024BYTES           NPCTL_ECCSZ(2)                /* ECC size is 1024 bytes */
+#define EXMC_ECC_SIZE_2048BYTES           NPCTL_ECCSZ(3)                /* ECC size is 2048 bytes */
+#define EXMC_ECC_SIZE_4096BYTES           NPCTL_ECCSZ(4)                /* ECC size is 4096 bytes */
+#define EXMC_ECC_SIZE_8192BYTES           NPCTL_ECCSZ(5)                /* ECC size is 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 is 8 bits */
+#define EXMC_NAND_DATABUS_WIDTH_16B       NPCTL_NDW(1)                  /*!< NAND data width is 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                    EXMC_SNCTL_SYNCWR             /*!< 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          EXMC_SNCTL_NRWTCFG            /*!< 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          EXMC_SNCTL_NRWTPOL            /*!< 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_FLAG_RISE    EXMC_NPINTEN_INTREN           /*!< rising edge interrupt and flag */
+#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL   EXMC_NPINTEN_INTHEN           /*!< high-level interrupt and flag */
+#define EXMC_NAND_PCCARD_INT_FLAG_FALL    EXMC_NPINTEN_INTFEN           /*!< falling edge interrupt and flag */
+
+/* function declarations */
+/* initialization functions */
+/* NOR/SRAM */
+/* deinitialize EXMC NOR/SRAM region */
+void exmc_norsram_deinit(uint32_t exmc_norsram_region);
+/* initialize exmc_norsram_parameter_struct with the default values */
+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);
+/* enable EXMC NOR/SRAM region */
+void exmc_norsram_enable(uint32_t exmc_norsram_region);
+/* disable EXMC NOR/SRAM region */
+void exmc_norsram_disable(uint32_t exmc_norsram_region);
+/* NAND */
+/* deinitialize EXMC NAND bank */
+void exmc_nand_deinit(uint32_t exmc_nand_bank);
+/* initialize exmc_norsram_parameter_struct with the default values */
+void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct);
+/* initialize EXMC NAND bank */
+void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct);
+/* enable EXMC NAND bank */
+void exmc_nand_enable(uint32_t exmc_nand_bank);
+/* disable EXMC NAND bank */
+void exmc_nand_disable(uint32_t exmc_nand_bank);
+/* PC card */
+/* deinitialize EXMC PC card bank */
+void exmc_pccard_deinit(void);
+/* initialize exmc_pccard_parameter_struct parameter with the default values */
+void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct);
+/* initialize EXMC PC card bank */
+void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct);
+/* enable EXMC PC card bank */
+void exmc_pccard_enable(void);
+/* disable EXMC PC card bank */
+void exmc_pccard_disable(void);
+
+/* function configuration */
+/* NOR/SRAM */
+/* configure CRAM page size */
+void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size);
+/* NAND */
+/* enable or disable the EXMC NAND ECC function */
+void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue);
+/* get the EXMC ECC value */
+uint32_t exmc_ecc_get(uint32_t exmc_nand_bank);
+
+/* interrupt & flag functions */
+/* enable EXMC interrupt */
+void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt);
+/* disable EXMC interrupt */
+void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt);
+/* get EXMC flag status */
+FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag);
+/* clear EXMC flag status */
+void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag);
+/* get EXMC interrupt flag */
+FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt);
+/* clear EXMC interrupt flag */
+void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt);
+
+#endif /* GD32F30X_EXMC_H */

+ 258 - 0
app/LIB/Include/gd32f30x_exti.h

@@ -0,0 +1,258 @@
+/*!
+    \file    gd32f30x_exti.h
+    \brief   definitions for the EXTI
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_EXTI_H
+#define GD32F30X_EXTI_H
+
+#include "gd32f30x.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 pending status from line 0 */
+#define EXTI_PD_PD1                  BIT(1)                   /*!< interrupt pending status from line 1 */
+#define EXTI_PD_PD2                  BIT(2)                   /*!< interrupt pending status from line 2 */
+#define EXTI_PD_PD3                  BIT(3)                   /*!< interrupt pending status from line 3 */
+#define EXTI_PD_PD4                  BIT(4)                   /*!< interrupt pending status from line 4 */
+#define EXTI_PD_PD5                  BIT(5)                   /*!< interrupt pending status from line 5 */
+#define EXTI_PD_PD6                  BIT(6)                   /*!< interrupt pending status from line 6 */
+#define EXTI_PD_PD7                  BIT(7)                   /*!< interrupt pending status from line 7 */
+#define EXTI_PD_PD8                  BIT(8)                   /*!< interrupt pending status from line 8 */
+#define EXTI_PD_PD9                  BIT(9)                   /*!< interrupt pending status from line 9 */
+#define EXTI_PD_PD10                 BIT(10)                  /*!< interrupt pending status from line 10 */
+#define EXTI_PD_PD11                 BIT(11)                  /*!< interrupt pending status from line 11 */
+#define EXTI_PD_PD12                 BIT(12)                  /*!< interrupt pending status from line 12 */
+#define EXTI_PD_PD13                 BIT(13)                  /*!< interrupt pending status from line 13 */
+#define EXTI_PD_PD14                 BIT(14)                  /*!< interrupt pending status from line 14 */
+#define EXTI_PD_PD15                 BIT(15)                  /*!< interrupt pending status from line 15 */
+#define EXTI_PD_PD16                 BIT(16)                  /*!< interrupt pending status from line 16 */
+#define EXTI_PD_PD17                 BIT(17)                  /*!< interrupt pending status from line 17 */
+#define EXTI_PD_PD18                 BIT(18)                  /*!< interrupt pending status from line 18 */
+#define EXTI_PD_PD19                 BIT(19)                  /*!< interrupt 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);
+/* initialize the EXTI line x */
+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);
+/* disable the interrupts from EXTI line x */
+void exti_interrupt_disable(exti_line_enum linex);
+/* enable the events from EXTI line x */
+void exti_event_enable(exti_line_enum linex);
+/* disable the events from EXTI line x */
+void exti_event_disable(exti_line_enum linex);
+/* enable the software interrupt event from EXTI line x */
+void exti_software_interrupt_enable(exti_line_enum linex);
+/* disable the software interrupt event from EXTI line x */
+void exti_software_interrupt_disable(exti_line_enum linex);
+
+/* interrupt & flag functions */
+/* get EXTI line x interrupt pending flag */
+FlagStatus exti_flag_get(exti_line_enum linex);
+/* clear EXTI line x interrupt pending flag */
+void exti_flag_clear(exti_line_enum linex);
+/* get EXTI line x interrupt pending flag */
+FlagStatus exti_interrupt_flag_get(exti_line_enum linex);
+/* clear EXTI line x interrupt pending flag */
+void exti_interrupt_flag_clear(exti_line_enum linex);
+
+#endif /* GD32F30X_EXTI_H */

+ 375 - 0
app/LIB/Include/gd32f30x_fmc.h

@@ -0,0 +1,375 @@
+/*!
+    \file    gd32f30x_fmc.h
+    \brief   definitions for the FMC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_FMC_H
+#define GD32F30X_FMC_H
+
+#include "gd32f30x.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_DATA1                   REG16((OB) + 0x04U)            /*!< option byte data1 value*/
+#define OB_DATA2                   REG16((OB) + 0x06U)            /*!< option byte data2 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 */
+#define FMC_WSEN_BPEN              BIT(1)                         /*!< FMC bit program 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)0x0FFF0000U)        /*!< 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 reprogram a word at the corresponding address without erasing */
+fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_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 /* GD32F30X_FMC_H */

+ 114 - 0
app/LIB/Include/gd32f30x_fwdgt.h

@@ -0,0 +1,114 @@
+/*!
+    \file    gd32f30x_fwdgt.h
+    \brief   definitions for the FWDGT
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_FWDGT_H
+#define GD32F30X_FWDGT_H
+
+#include "gd32f30x.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 */
+
+/* write value to FWDGT_RLD_RLD bit field */
+#define RLD_RLD(regval)             (BITS(0,11) & ((uint32_t)(regval) << 0))
+
+/* 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);
+
+/* configure the free watchdog timer counter prescaler value */
+ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value);
+/* configure the free watchdog timer counter reload value */
+ErrStatus fwdgt_reload_value_config(uint16_t reload_value);
+/* 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 /* GD32F30X_FWDGT_H */

+ 537 - 0
app/LIB/Include/gd32f30x_gpio.h

@@ -0,0 +1,537 @@
+/*!
+    \file    gd32f30x_gpio.h
+    \brief   definitions for the GPIO
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_GPIO_H
+#define GD32F30X_GPIO_H
+
+#include "gd32f30x.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 */
+#define GPIOx_SPD(gpiox)           REG32((gpiox) + 0x3CU)    /*!< GPIO port bit speed 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 */
+#define AFIO_CPSCTL                REG32(AFIO + 0x20U)       /*!< IO compensation control register */
+
+/* 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 */
+
+/* GPIO_SPD */
+#define GPIO_SPD_SPD0              BIT(0)                    /*!< pin 0 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD1              BIT(1)                    /*!< pin 1 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD2              BIT(2)                    /*!< pin 2 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD3              BIT(3)                    /*!< pin 3 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD4              BIT(4)                    /*!< pin 4 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD5              BIT(5)                    /*!< pin 5 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD6              BIT(6)                    /*!< pin 6 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD7              BIT(7)                    /*!< pin 7 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD8              BIT(8)                    /*!< pin 8 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD9              BIT(9)                    /*!< pin 9 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD10             BIT(10)                   /*!< pin 10 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD11             BIT(11)                   /*!< pin 11 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD12             BIT(12)                   /*!< pin 12 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD13             BIT(13)                   /*!< pin 13 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD14             BIT(14)                   /*!< pin 14 set very high output speed when MDx is 0b11 */
+#define GPIO_SPD_SPD15             BIT(15)                   /*!< pin 15 set very high output speed when MDx is 0b11 */
+
+/* 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 GD32F30X_CL
+/* memory map and bit definitions for GD32F30X_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)             /*!< TIMER4 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_TIMER1ITR0_REMAP       BIT(29)             /*!< TIMER1 internal trigger 0 remapping */
+#define AFIO_PCF0_TIMER1ITI1_REMAP       BIT(29)             /*!< TIMER1 internal trigger 0 remapping */
+#define AFIO_PCF0_PTP_PPS_REMAP          BIT(30)             /*!< ethernet PTP PPS remapping */
+
+#else 
+/* memory map and bit definitions for GD32F30X_HD devices and GD32F30X_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_IREMAP       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 */
+#define AFIO_PCF0_SPI2_REMAP             BIT(28)             /*!< SPI2/I2S2 remapping */
+#endif /* GD32F30X_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 */
+#define AFIO_PCF1_CTC_REMAP              BITS(11,12)         /*!< CTC remapping */
+
+/* AFIO_CPSCTL */
+#define AFIO_CPSCTL_CPS_EN               BIT(0)              /*!< I/O compensation cell enable */
+#define AFIO_CPSCTL_CPS_RDY              BIT(8)              /*!< I/O compensation cell is ready or not */
+
+/* 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 */
+#define GPIO_OSPEED_MAX                  ((uint8_t)0x04U)          /*!< GPIO very high output speed, max speed more than 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 */
+
+/* AFIO remap mask */
+#define PCF0_USART2_REMAP(regval)       (BITS(4,5) & ((uint32_t)(regval) << 4))                           /*!< USART2 remapping */        
+#define PCF0_TIMER0_REMAP(regval)       (BITS(6,7) & ((uint32_t)(regval) << 6))                           /*!< TIMER0 remapping */
+#define PCF0_TIMER1_REMAP(regval)       (BITS(8,9) & ((uint32_t)(regval) << 8))                           /*!< TIMER1 remapping */
+#define PCF0_TIMER2_REMAP(regval)       (BITS(10,11) & ((uint32_t)(regval) << 10))                        /*!< TIMER2 remapping */
+#define PCF0_CAN_REMAP(regval)          (BITS(13,14) & ((uint32_t)(regval) << 13))                        /*!< CAN remapping */
+#define PCF0_SWJ_CFG(regval)            (BITS(24,26) & ((uint32_t)(regval) << 24))                        /*!< serial wire JTAG configuration */
+#define PCF1_CTC_REMAP(regval)          (BITS(11,12) & ((uint32_t)(regval) << 11))                        /*!< CTC remapping */
+
+/* GPIO remap definitions */
+#define GPIO_SPI0_REMAP                  AFIO_PCF0_SPI0_REMAP                                             /*!< SPI0 remapping */
+#define GPIO_I2C0_REMAP                  AFIO_PCF0_I2C0_REMAP                                             /*!< I2C0 remapping */
+#define GPIO_USART0_REMAP                AFIO_PCF0_USART0_REMAP                                           /*!< USART0 remapping */
+#define GPIO_USART1_REMAP                AFIO_PCF0_USART1_REMAP                                           /*!< USART1 remapping */
+#define GPIO_USART2_PARTIAL_REMAP        ((uint32_t)0x00140000U | PCF0_USART2_REMAP(1))                   /*!< USART2 partial remapping */
+#define GPIO_USART2_FULL_REMAP           ((uint32_t)0x00140000U | PCF0_USART2_REMAP(3))                   /*!< USART2 full remapping */
+#define GPIO_TIMER0_PARTIAL_REMAP        ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(1))                   /*!< TIMER0 partial remapping */
+#define GPIO_TIMER0_FULL_REMAP           ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(3))                   /*!< TIMER0 full remapping */
+#define GPIO_TIMER1_PARTIAL_REMAP0       ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(1))                   /*!< TIMER1 partial remapping */
+#define GPIO_TIMER1_PARTIAL_REMAP1       ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(2))                   /*!< TIMER1 partial remapping */
+#define GPIO_TIMER1_FULL_REMAP           ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(3))                   /*!< TIMER1 full remapping */
+#define GPIO_TIMER2_PARTIAL_REMAP        ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(2))                   /*!< TIMER2 partial remapping */
+#define GPIO_TIMER2_FULL_REMAP           ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(3))                   /*!< TIMER2 full remapping */
+#define GPIO_TIMER3_REMAP                AFIO_PCF0_TIMER3_REMAP                                           /*!< TIMER3 remapping */
+#define GPIO_PD01_REMAP                  AFIO_PCF0_PD01_REMAP                                             /*!< PD01 remapping */
+#define GPIO_TIMER4CH3_IREMAP            ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER4CH3_IREMAP >> 16))     /*!< TIMER4 channel3 internal remapping */
+#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))
+#define GPIO_CAN_PARTIAL_REMAP           ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2))                      /*!< CAN partial remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#define GPIO_CAN_FULL_REMAP              ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3))                      /*!< CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#endif /* GD32F30X_HD||GD32F30X_XD */
+#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))
+#define GPIO_ADC0_ETRGINS_REMAP          ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGINS_REMAP >> 16))   /*!< ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#define GPIO_ADC0_ETRGREG_REMAP          ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGREG_REMAP >> 16))   /*!< ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#define GPIO_ADC1_ETRGINS_REMAP          ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGINS_REMAP >> 16))   /*!< ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#define GPIO_ADC1_ETRGREG_REMAP          ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGREG_REMAP >> 16))   /*!< ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */
+#endif /* GD32F30X_HD||GD32F30X_XD */
+#define GPIO_SWJ_NONJTRST_REMAP          ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(1) >> 16))                /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */
+#define GPIO_SWJ_SWDPENABLE_REMAP        ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(2) >> 16))                /*!< JTAG-DP disabled and SW-DP enabled */
+#define GPIO_SWJ_DISABLE_REMAP           ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(4) >> 16))                /*!< JTAG-DP disabled and SW-DP disabled */
+#define GPIO_SPI2_REMAP                  ((uint32_t)0x00200000U | (AFIO_PCF0_SPI2_REMAP >> 16))           /*!< SPI2 remapping*/
+#ifdef GD32F30X_CL
+#define GPIO_CAN0_PARTIAL_REMAP          ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2))                      /*!< CAN0 partial remapping(only for GD32F30X_CL devices) */
+#define GPIO_CAN0_FULL_REMAP             ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3))                      /*!< CAN0 full remapping(only for GD32F30X_CL devices) */
+#define GPIO_ENET_REMAP                  ((uint32_t)0x00200000U | (AFIO_PCF0_ENET_REMAP >> 16))           /*!< ENET remapping(only for GD32F30X_CL devices) */
+#define GPIO_CAN1_REMAP                  ((uint32_t)0x00200000U | (AFIO_PCF0_CAN1_REMAP >> 16))           /*!< CAN1 remapping(only for GD32F30X_CL devices) */
+#define GPIO_TIMER1ITR0_REMAP            ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER1ITR0_REMAP >> 16))     /*!< TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices) */
+#define GPIO_PTP_PPS_REMAP               ((uint32_t)0x00200000U | (AFIO_PCF0_PTP_PPS_REMAP >> 16))        /*!< ethernet PTP PPS remapping(only for GD32F30X_CL devices) */
+#endif /* GD32F30X_CL */
+#define GPIO_TIMER8_REMAP                ((uint32_t)0x80000000U | AFIO_PCF1_TIMER8_REMAP)                 /*!< TIMER8 remapping */
+#define GPIO_TIMER9_REMAP                ((uint32_t)0x80000000U | AFIO_PCF1_TIMER9_REMAP)                 /*!< TIMER9 remapping */
+#define GPIO_TIMER10_REMAP               ((uint32_t)0x80000000U | AFIO_PCF1_TIMER10_REMAP)                /*!< TIMER10 remapping */
+#define GPIO_TIMER12_REMAP               ((uint32_t)0x80000000U | AFIO_PCF1_TIMER12_REMAP)                /*!< TIMER12 remapping */
+#define GPIO_TIMER13_REMAP               ((uint32_t)0x80000000U | AFIO_PCF1_TIMER13_REMAP)                /*!< TIMER13 remapping */
+#define GPIO_EXMC_NADV_REMAP             ((uint32_t)0x80000000U | AFIO_PCF1_EXMC_NADV)                    /*!< EXMC_NADV connect/disconnect */
+#define GPIO_CTC_REMAP0                  ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(1))                      /*!< CTC remapping(PD15) */
+#define GPIO_CTC_REMAP1                  ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(2))                      /*!< CTC remapping(PF0) */
+
+#ifdef GD32F30X_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 /* GD32F30X_CL */
+
+/* I/O compensation cell enable/disable */
+#define GPIO_COMPENSATION_ENABLE         AFIO_CPSCTL_CPS_EN                                               /*!< I/O compensation cell is enable */
+#define GPIO_COMPENSATION_DISABLE        ((uint32_t)0x00000000U)                                          /*!< I/O compensation cell is disable */
+
+/* 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);
+
+#ifdef GD32F30X_CL
+/* select ethernet MII or RMII PHY */
+void gpio_ethernet_phy_select(uint32_t enet_sel);
+#endif /* GD32F30X_CL */
+
+/* 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);
+/* configure the I/O compensation cell */
+void gpio_compensation_config(uint32_t compensation); 
+/* check the I/O compensation cell is ready or not */
+FlagStatus gpio_compensation_flag_get(void);
+
+#endif /* GD32F30X_GPIO_H */

+ 357 - 0
app/LIB/Include/gd32f30x_i2c.h

@@ -0,0 +1,357 @@
+/*!
+    \file    gd32f30x_i2c.h
+    \brief   definitions for the I2C
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2019-04-16, V2.0.1, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_I2C_H
+#define GD32F30X_I2C_H
+
+#include "gd32f30x.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) + 0x00000000U)      /*!< I2C control register 0 */
+#define I2C_CTL1(i2cx)                REG32((i2cx) + 0x00000004U)      /*!< I2C control register 1 */
+#define I2C_SADDR0(i2cx)              REG32((i2cx) + 0x00000008U)      /*!< I2C slave address register 0*/
+#define I2C_SADDR1(i2cx)              REG32((i2cx) + 0x0000000CU)      /*!< I2C slave address register */
+#define I2C_DATA(i2cx)                REG32((i2cx) + 0x00000010U)      /*!< I2C transfer buffer register */
+#define I2C_STAT0(i2cx)               REG32((i2cx) + 0x00000014U)      /*!< I2C transfer status register 0 */
+#define I2C_STAT1(i2cx)               REG32((i2cx) + 0x00000018U)      /*!< I2C transfer status register */
+#define I2C_CKCFG(i2cx)               REG32((i2cx) + 0x0000001CU)      /*!< I2C clock configure register */
+#define I2C_RT(i2cx)                  REG32((i2cx) + 0x00000020U)      /*!< I2C rise time register */
+#define I2C_FMPCFG(i2cx)              REG32((i2cx) + 0x00000090U)      /*!< I2C fast-mode-plus configure 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,6)     /*!< I2CCLK[6:0] bits (peripheral clock frequency) */
+#define I2C_CTL1_ERRIE                BIT(8)        /*!< error interrupt inable */
+#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 or fast mode plus(master mode) */
+#define I2C_CKCFG_DTCY                BIT(14)       /*!< duty cycle of fast mode or fast mode plus */
+#define I2C_CKCFG_FAST                BIT(15)       /*!< I2C speed selection in master mode */
+
+/* I2Cx_RT */
+#define I2C_RT_RISETIME               BITS(0,6)     /*!< maximum rise time in fast/standard mode or fast mode plus(master mode) */
+
+/* I2Cx_FMPCFG */
+#define I2C_FMPCFG_FMPEN              BIT(0)        /*!< fast mode plus enable bit */
+
+/* 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                I2C_CTL0_ACKEN                           /*!< ACK will be sent */
+
+/* I2C POAP position*/
+#define I2C_ACKPOS_CURRENT            ((uint32_t)0x00000000U)                  /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */
+#define I2C_ACKPOS_NEXT               I2C_CTL0_POAP                            /*!< ACKEN bit decides whether or not to send ACK for the next 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 enable */
+#define I2C_ARP_DISABLE               ((uint32_t)0x00000000U)                  /*!< ARP disable */
+
+/* fast mode plus enable */
+#define I2C_FAST_MODE_PLUS_ENABLE     I2C_FMPCFG_FMPEN                         /*!< fast mode plus enable */
+#define I2C_FAST_MODE_PLUS_DISABLE    ((uint32_t)0x00000000U)                  /*!< fast mode plus disable */
+
+/* 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 or fast mode plus */
+#define I2C_DTCY_2                    ((uint32_t)0x00000000U)                  /*!< in I2C fast mode or fast mode plus Tlow/Thigh = 2 */
+#define I2C_DTCY_16_9                 I2C_CKCFG_DTCY                           /*!< in I2C fast mode or fast mode plus 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 */
+/* initialization functions */
+/* 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);
+
+/* application function declarations */
+/* select SMBus type */
+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 dualaddr);
+/* 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);
+/* configure I2C DMA mode */
+void i2c_dma_config(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);
+/* configure software reset of I2C */
+void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset);
+/* configure I2C PEC calculation */
+void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate);
+/* configure whether to transfer PEC value */
+void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara);
+/* get packet error checking value */
+uint8_t i2c_pec_value_get(uint32_t i2c_periph);
+/* configure I2C alert through SMBA pin */
+void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara);
+/* configure I2C ARP protocol in SMBus */
+void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate);
+
+/* interrupt & flag functions */
+/* get I2C flag status */
+FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag);
+/* clear I2C flag status */
+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);
+/* get I2C interrupt flag status */
+FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag);
+/* clear I2C interrupt flag status */
+void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag);
+
+#endif /* GD32F30X_I2C_H */

+ 94 - 0
app/LIB/Include/gd32f30x_misc.h

@@ -0,0 +1,94 @@
+/*!
+    \file    gd32f30x_misc.h
+    \brief   definitions for the MISC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_MISC_H
+#define GD32F30X_MISC_H
+
+#include "gd32f30x.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 /* GD32F30X_MISC_H */

+ 192 - 0
app/LIB/Include/gd32f30x_pmu.h

@@ -0,0 +1,192 @@
+/*!
+    \file    gd32f30x_pmu.h
+    \brief   definitions for the PMU
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_PMU_H
+#define GD32F30X_PMU_H
+
+#include "gd32f30x.h"
+
+/* PMU definitions */
+#define PMU                           PMU_BASE                      /*!< PMU base address */
+
+/* registers definitions */
+#define PMU_CTL                       REG32((PMU) + 0x00000000U)    /*!< PMU control register */
+#define PMU_CS                        REG32((PMU) + 0x00000004U)    /*!< 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 */
+#define PMU_CTL_LDLP                  BIT(10)                       /*!< low-driver mode when use low power LDO */
+#define PMU_CTL_LDNP                  BIT(11)                       /*!< low-driver mode when use normal power LDO */
+#define PMU_CTL_LDOVS                 BITS(14,15)                   /*!< LDO output voltage select */
+#define PMU_CTL_HDEN                  BIT(16)                       /*!< high-driver mode enable */
+#define PMU_CTL_HDS                   BIT(17)                       /*!< high-driver mode switch */
+#define PMU_CTL_LDEN                  BITS(18,19)                   /*!< low-driver mode enable in deep-sleep mode */
+
+/* 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 */
+#define PMU_CS_LDOVSRF                BIT(14)                       /*!< LDO voltage select ready flag */
+#define PMU_CS_HDRF                   BIT(16)                       /*!< high-driver ready flag */
+#define PMU_CS_HDSRF                  BIT(17)                       /*!< high-driver switch ready flag */
+#define PMU_CS_LDRF                   BITS(18,19)                   /*!< Low-driver mode ready flag */
+
+/* constants definitions */
+/* 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 in low power status when PMU enter deepsleep mode */
+
+/* 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.1V */
+#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.6V */
+#define PMU_LVDT_4                    CTL_LVDT(4)                   /*!< voltage threshold is 2.7V */
+#define PMU_LVDT_5                    CTL_LVDT(5)                   /*!< voltage threshold is 2.9V */
+#define PMU_LVDT_6                    CTL_LVDT(6)                   /*!< voltage threshold is 3.0V */
+#define PMU_LVDT_7                    CTL_LVDT(7)                   /*!< voltage threshold is 3.1V */
+
+/* PMU low-driver mode when use low power LDO */
+#define CTL_LDLP(regval)              (BIT(10)&((uint32_t)(regval)<<10))
+#define PMU_NORMALDR_LOWPWR           CTL_LDLP(0)                   /*!< normal driver when use low power LDO */
+#define PMU_LOWDR_LOWPWR              CTL_LDLP(1)                   /*!< low-driver mode enabled when LDEN is 11 and use low power LDO */
+
+/* PMU low-driver mode when use normal power LDO */
+#define CTL_LDNP(regval)              (BIT(11)&((uint32_t)(regval)<<11))
+#define PMU_NORMALDR_NORMALPWR        CTL_LDNP(0)                   /*!< normal driver when use normal power LDO */
+#define PMU_LOWDR_NORMALPWR           CTL_LDNP(1)                   /*!< low-driver mode enabled when LDEN is 11 and use normal power LDO */
+
+/* PMU LDO output voltage select definitions */
+#define CTL_LDOVS(regval)             (BITS(14,15)&((uint32_t)(regval)<<14))
+#define PMU_LDOVS_LOW                 CTL_LDOVS(1)                  /*!< LDO output voltage low mode */
+#define PMU_LDOVS_MID                 CTL_LDOVS(2)                  /*!< LDO output voltage mid mode */
+#define PMU_LDOVS_HIGH                CTL_LDOVS(3)                  /*!< LDO output voltage high mode */
+
+/* PMU high-driver mode switch */
+#define CTL_HDS(regval)               (BIT(17)&((uint32_t)(regval)<<17))
+#define PMU_HIGHDR_SWITCH_NONE        CTL_HDS(0)                    /*!< no high-driver mode switch */
+#define PMU_HIGHDR_SWITCH_EN          CTL_HDS(1)                    /*!< high-driver mode switch */
+
+/* low-driver mode in deep-sleep mode */
+#define PMU_LOWDRIVER_DISABLE         ((uint32_t)0x00000000U)       /*!< low-driver mode disable in deep-sleep mode */
+#define PMU_LOWDRIVER_ENABLE          PMU_CTL_LDEN                  /*!< low-driver mode enable in deep-sleep mode */
+
+/* PMU low power mode ready flag definitions */
+#define CS_LDRF(regval)               (BITS(18,19)&((uint32_t)(regval)<<18))
+#define PMU_LDRF_NORMAL               CS_LDRF(0)                    /*!< normal driver in deep-sleep mode */
+#define PMU_LDRF_LOWDRIVER            CS_LDRF(3)                    /*!< low-driver mode in deep-sleep mode */
+
+/* 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 */
+#define PMU_FLAG_LDOVSRF              PMU_CS_LDOVSRF                /*!< LDO voltage select ready flag */
+#define PMU_FLAG_HDRF                 PMU_CS_HDRF                   /*!< high-driver ready flag */
+#define PMU_FLAG_HDSRF                PMU_CS_HDSRF                  /*!< high-driver switch ready flag */
+#define PMU_FLAG_LDRF                 PMU_CS_LDRF                   /*!< low-driver mode ready flag */
+
+/* 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);
+
+/* LVD functions */
+/* select low voltage detector threshold */
+void pmu_lvd_select(uint32_t lvdt_n);
+/* select LDO output voltage */
+void pmu_ldo_output_select(uint32_t ldo_output);
+/* disable PMU lvd */
+void pmu_lvd_disable(void);
+
+/* functions of low-driver mode and high-driver mode in deep-sleep mode */
+/* switch high-driver mode */
+void pmu_highdriver_switch_select(uint32_t highdr_switch);
+/* enable high-driver mode */
+void pmu_highdriver_mode_enable(void);
+/* disable high-driver mode */
+void pmu_highdriver_mode_disable(void);
+/* enable low-driver mode in deep-sleep mode */
+void pmu_lowdriver_mode_enable(void);
+/* disable low-driver mode in deep-sleep mode */
+void pmu_lowdriver_mode_disable(void);
+/* in deep-sleep mode, driver mode when use low power LDO */
+void pmu_lowpower_driver_config(uint32_t mode);
+/* in deep-sleep mode, driver mode when use normal power LDO */
+void pmu_normalpower_driver_config(uint32_t mode);
+
+/* set PMU mode */
+/* PMU work in sleep mode */
+void pmu_to_sleepmode(uint8_t sleepmodecmd);
+/* PMU work in deepsleep mode */
+void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd);
+/* PMU work in standby mode */
+void pmu_to_standbymode(void);
+/* enable PMU wakeup pin */
+void pmu_wakeup_pin_enable(void);
+/* disable PMU wakeup pin */
+void pmu_wakeup_pin_disable(void);
+
+/* backup related functions */
+/* enable backup domain write */
+void pmu_backup_write_enable(void);
+/* disable backup domain write */
+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);
+
+#endif /* GD32F30X_PMU_H */

File diff suppressed because it is too large
+ 1070 - 0
app/LIB/Include/gd32f30x_rcu.h


+ 138 - 0
app/LIB/Include/gd32f30x_rtc.h

@@ -0,0 +1,138 @@
+/*!
+    \file    gd32f30x_rtc.h
+    \brief   definitions for the RTC
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_RTC_H
+#define GD32F30X_RTC_H
+
+#include "gd32f30x.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_PSC */
+#define RTC_PSCH_PSC                 BITS(0, 3)               /*!< prescaler high value */
+#define RTC_PSCL_PSC                 BITS(0, 15)              /*!< prescaler low value */
+
+/* RTC_DIV */
+#define RTC_DIVH_DIV                 BITS(0, 3)               /*!< divider high value */
+#define RTC_DIVL_DIV                 BITS(0, 15)              /*!< divider low value */
+
+/* RTC_CNT */
+#define RTC_CNTH_CNT                 BITS(0, 15)              /*!< counter high value */
+#define RTC_CNTL_CNT                 BITS(0, 15)              /*!< counter low value */
+
+/* RTC_ALRM */
+#define RTC_ALRMH_ALRM               BITS(0, 15)              /*!< alarm high value */
+#define RTC_ALRML_ALRM               BITS(0, 15)              /*!< alarm low value */
+
+/* constants definitions */
+#define RTC_HIGH_VALUE               0x000F0000U              /*!< RTC high value */
+#define RTC_LOW_VALUE                0x0000FFFFU              /*!< RTC low value */
+
+/* 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 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 */
+/* enable RTC interrupt */
+void rtc_interrupt_enable(uint32_t interrupt);
+/* disable RTC interrupt */
+void rtc_interrupt_disable(uint32_t interrupt);
+
+/* enter RTC configuration mode */
+void rtc_configuration_mode_enter(void);
+/* exit RTC configuration mode */
+void rtc_configuration_mode_exit(void);
+
+/* 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);
+
+/* get RTC counter value */
+uint32_t rtc_counter_get(void);
+/* set RTC counter value */
+void rtc_counter_set(uint32_t cnt);
+
+/* set RTC prescaler value */
+void rtc_prescaler_set(uint32_t psc);
+/* set RTC alarm value */
+void rtc_alarm_config(uint32_t alarm);
+/* get RTC divider value */
+uint32_t rtc_divider_get(void);
+
+/* get RTC flag status */
+FlagStatus rtc_flag_get(uint32_t flag);
+/* clear RTC flag status */
+void rtc_flag_clear(uint32_t flag);
+
+#endif /* GD32F30X_RTC_H */

+ 434 - 0
app/LIB/Include/gd32f30x_sdio.h

@@ -0,0 +1,434 @@
+/*!
+    \file    gd32f30x_sdio.h
+    \brief   definitions for the SDIO
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_SDIO_H
+#define GD32F30X_SDIO_H
+
+#include "gd32f30x.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 */
+#define SDIO_CLKCTL_DIV8                BIT(31)                /*!< MSB of clock division */
+
+/* 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 /* GD32F30X_SDIO_H */

+ 368 - 0
app/LIB/Include/gd32f30x_spi.h

@@ -0,0 +1,368 @@
+/*!
+    \file    gd32f30x_spi.h
+    \brief   definitions for the SPI
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_SPI_H
+#define GD32F30X_SPI_H
+
+#include "gd32f30x.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 */
+#define SPI_QCTL(spix)                  REG32((spix) + 0x80U)                   /*!< SPI quad mode control register(only SPI0) */
+
+/* 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_NSSP                   BIT(3)                                  /*!< SPI NSS pulse mode enable */
+#define SPI_CTL1_TMOD                   BIT(4)                                  /*!< SPI TI mode enable */
+#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 */
+#define SPI_STAT_FERR                   BIT(8)                                  /*!< format error bit */
+
+/* SPI_DATA */
+#define SPI_DATA_DATA                   BITS(0,15)                              /*!< data transfer register */
+
+/* SPI_CRCPOLY */
+#define SPI_CRCPOLY_CPR                 BITS(0,15)                              /*!< CRC polynomial register */
+
+/* SPI_RCRC */
+#define SPI_RCRC_RCR                    BITS(0,15)                              /*!< RX CRC register */
+
+/* SPI_TCRC */
+#define SPI_TCRC_TCR                    BITS(0,15)                              /*!< TX CRC register */
+
+/* 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 */
+
+/* SPI_QCTL(only for SPI0) */
+#define SPI_QCTL_QMOD                   BIT(0)                                  /*!< quad-SPI mode enable */
+#define SPI_QCTL_QRD                    BIT(1)                                  /*!< quad-SPI mode read select */
+#define SPI_QCTL_IO23_DRV               BIT(2)                                  /*!< drive SPI_IO2 and SPI_IO3 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 sofrware */
+#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 */
+#define SPI_I2S_INT_FLAG_FERR           ((uint8_t)0x06U)                        /*!< format 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 SPI_FLAG_FERR                   SPI_STAT_FERR                           /*!< format error 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 */
+#define I2S_FLAG_FERR                   SPI_STAT_FERR                           /*!< format error 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 i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl);
+/* configure I2S prescaler */
+void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_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);
+
+/* SPI DMA functions */
+/* 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);
+
+/* SPI/I2S transfer functions */
+/* 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);
+/* clear TI Mode Format Error flag status */
+void spi_i2s_format_error_clear(uint32_t spi_periph, uint32_t flag);
+
+
+/* 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);
+/* clear SPI CRC error flag status */
+void spi_crc_error_clear(uint32_t spi_periph);
+
+/* SPI TI mode functions */
+/* enable SPI TI mode */
+void spi_ti_mode_enable(uint32_t spi_periph);
+/* disable SPI TI mode */
+void spi_ti_mode_disable(uint32_t spi_periph);
+
+/* SPI NSS pulse mode functions */
+/* enable SPI NSS pulse mode */
+void spi_nssp_mode_enable(uint32_t spi_periph);
+/* disable SPI NSS pulse mode */
+void spi_nssp_mode_disable(uint32_t spi_periph);
+
+/* quad wire SPI functions */
+/* enable quad wire SPI */
+void spi_quad_enable(uint32_t spi_periph);
+/* disable quad wire SPI */
+void spi_quad_disable(uint32_t spi_periph);
+/* enable quad wire SPI write */
+void spi_quad_write_enable(uint32_t spi_periph);
+/* enable quad wire SPI read */
+void spi_quad_read_enable(uint32_t spi_periph);
+/* enable quad wire SPI_IO2 and SPI_IO3 pin output */
+void spi_quad_io23_output_enable(uint32_t spi_periph);
+/* disable quad wire SPI_IO2 and SPI_IO3 pin output */
+void spi_quad_io23_output_disable(uint32_t spi_periph);
+
+/* 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);
+
+#endif /* GD32F30X_SPI_H */

+ 752 - 0
app/LIB/Include/gd32f30x_timer.h

@@ -0,0 +1,752 @@
+/*!
+    \file    gd32f30x_timer.h
+    \brief   definitions for the TIMER
+    
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_TIMER_H
+#define GD32F30X_TIMER_H
+
+#include "gd32f30x.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 complementary channel 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 */
+#define TIMER_IRMP(timerx)               REG32((timerx) + 0x50U)           /*!< TIMER channel input remap register */
+#define TIMER_CFG(timerx)                REG32((timerx) + 0xFCU)           /*!< TIMER configuration 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 DMA request enable */
+#define TIMER_DMAINTEN_CH1DEN            BIT(10)             /*!< channel 1 DMA request enable */
+#define TIMER_DMAINTEN_CH2DEN            BIT(11)             /*!< channel 2 DMA request enable */
+#define TIMER_DMAINTEN_CH3DEN            BIT(12)             /*!< channel 3 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 overcapture flag */
+#define TIMER_INTF_CH1OF                 BIT(10)             /*!< channel 1 overcapture flag */
+#define TIMER_INTF_CH2OF                 BIT(11)             /*!< channel 2 overcapture flag */
+#define TIMER_INTF_CH3OF                 BIT(12)             /*!< channel 3 overcapture 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 mode */
+#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 mode */
+#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 mode */
+#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 mode */
+#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 */
+
+/* TIMER_IRMP */
+#define TIMER10_IRMP_ITI1_RMP            BITS(0,1)           /*!< TIMER10 internal trigger input 1 remap */
+
+/* TIMER_CFG */
+#define TIMER_CFG_OUTSEL                 BIT(0)              /*!< the output value selection */
+#define TIMER_CFG_CHVSEL                 BIT(1)              /*!< write CHxVAL register selection */
+
+/* constants definitions */
+/* TIMER init parameter struct definitions*/
+typedef struct
+{ 
+    uint16_t prescaler;                         /*!< prescaler value */
+    uint16_t alignedmode;                       /*!< aligned mode */
+    uint16_t counterdirection;                  /*!< counter direction */
+    uint16_t clockdivision;                     /*!< clock division value */
+    uint32_t period;                            /*!< period 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 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 interrupt flag */
+#define TIMER_INT_FLAG_UP                   TIMER_INTF_UPIF                         /*!< update interrupt flag */
+#define TIMER_INT_FLAG_CH0                  TIMER_INTF_CH0IF                        /*!< channel 0 interrupt flag */
+#define TIMER_INT_FLAG_CH1                  TIMER_INTF_CH1IF                        /*!< channel 1 interrupt flag */
+#define TIMER_INT_FLAG_CH2                  TIMER_INTF_CH2IF                        /*!< channel 2 interrupt flag */
+#define TIMER_INT_FLAG_CH3                  TIMER_INTF_CH3IF                        /*!< channel 3 interrupt flag */
+#define TIMER_INT_FLAG_CMT                  TIMER_INTF_CMTIF                        /*!< channel commutation interrupt flag */
+#define TIMER_INT_FLAG_TRG                  TIMER_INTF_TRGIF                        /*!< trigger interrupt flag */
+#define TIMER_INT_FLAG_BRK                  TIMER_INTF_BRKIF
+
+
+
+/* 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        ((uint8_t)0x00U)                        /*!< DMA request of channel y is sent when update event occurs */
+#define TIMER_DMAREQUEST_CHANNELEVENT       ((uint8_t)0x01U)                        /*!< DMA request of channel y is sent when channel y 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 */
+#define TIMER_DMACFG_DMATA_DMATB            DMACFG_DMATA(19)                        /*!< DMA transfer address is TIMER_DMATB */
+
+/* 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                ((uint32_t)0x00000000U)                        /*!< the prescaler is loaded right now */
+#define TIMER_PSC_RELOAD_UPDATE             ((uint32_t)0x00000001U)                        /*!< 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                ((uint32_t)0x00000000U)                        /*!< single pulse mode */
+#define TIMER_SP_MODE_REPETITIVE            ((uint32_t)0x00000001U)                        /*!< repetitive pulse mode */
+
+/* update source */
+#define TIMER_UPDATE_SRC_REGULAR            ((uint32_t)0x00000000U)                        /*!< update generate only by counter overflow/underflow */
+#define TIMER_UPDATE_SRC_GLOBAL             ((uint32_t)0x00000001U)                        /*!< 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                    ((uint32_t)0x00000001U)                 /*!< channel enable */
+#define TIMER_CCX_DISABLE                   ((uint32_t)0x00000000U)                 /*!< 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)                     /*!< timing mode */
+#define TIMER_OC_MODE_ACTIVE                ((uint16_t)0x0010U)                     /*!< active mode */
+#define TIMER_OC_MODE_INACTIVE              ((uint16_t)0x0020U)                     /*!< inactive mode */
+#define TIMER_OC_MODE_TOGGLE                ((uint16_t)0x0030U)                     /*!< toggle mode */
+#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 are updated when CMTG bit is set */
+#define TIMER_UPDATECTL_CCUTRI              ((uint32_t)0x00000001U)                        /*!< 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 channal0 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      ((uint32_t)0x00000000U)                        /*!< master slave mode enable */
+#define TIMER_MASTER_SLAVE_MODE_DISABLE     ((uint32_t)0x00000001U)                        /*!< 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          ((uint32_t)0x00000000U)                        /*!< TIMER hall sensor mode enable */
+#define TIMER_HALLINTERFACE_DISABLE         ((uint32_t)0x00000001U)                        /*!< TIMER hall sensor mode disable */
+
+/* TIMERx(x=0,1,2,13,14,15,16) write cc register selection */
+#define TIMER_CHVSEL_ENABLE                  ((uint16_t)0x0002U)                     /*!< write CHxVAL register selection enable  */
+#define TIMER_CHVSEL_DISABLE                 ((uint16_t)0x0000U)                     /*!< write CHxVAL register selection disable */
+
+/* the output value selection */
+#define TIMER_OUTSEL_ENABLE                 ((uint16_t)0x0001U)                     /*!< output value selection enable */
+#define TIMER_OUTSEL_DISABLE                ((uint16_t)0x0000U)                     /*!< output value 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, uint8_t pscreload);
+/* configure TIMER repetition register value */
+void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition);
+/* configure TIMER autoreload register value */
+void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload);
+/* configure TIMER counter register value */
+void timer_counter_value_config(uint32_t timer_periph , uint16_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 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 flags */
+FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag);
+/* clear TIMER flags */
+void timer_flag_clear(uint32_t timer_periph, uint32_t flag);
+
+/* 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, uint8_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, uint8_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, uint32_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, uint32_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,uint32_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, uint32_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, uint32_t extfilter);
+/* disable TIMER the external clock mode 1 */
+void timer_external_clock_mode1_disable(uint32_t timer_periph);
+
+/* TIMER configure */
+/* configure TIMER write CHxVAL register selection */
+void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel);
+/* configure TIMER output value selection */
+void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel);
+
+#endif /* GD32F30X_TIMER_H */

+ 444 - 0
app/LIB/Include/gd32f30x_usart.h

@@ -0,0 +1,444 @@
+/*!
+    \file    gd32f30x_usart.h
+    \brief   definitions for the USART
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_USART_H
+#define GD32F30X_USART_H
+
+#include "gd32f30x.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_STAT0(usartx)           REG32((usartx) + 0x00000000U)          /*!< USART status register 0 */
+#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 */
+#define USART_CTL3(usartx)            REG32((usartx) + 0x00000080U)          /*!< USART control register 3 */
+#define USART_RT(usartx)              REG32((usartx) + 0x00000084U)          /*!< USART receiver timeout register */
+#define USART_STAT1(usartx)           REG32((usartx) + 0x00000088U)          /*!< USART status register 1 */
+
+/* bits definitions */
+/* USARTx_STAT0 */
+#define USART_STAT0_PERR              BIT(0)                                 /*!< parity error flag */
+#define USART_STAT0_FERR              BIT(1)                                 /*!< frame error flag */
+#define USART_STAT0_NERR              BIT(2)                                 /*!< noise error flag */
+#define USART_STAT0_ORERR             BIT(3)                                 /*!< overrun error */
+#define USART_STAT0_IDLEF             BIT(4)                                 /*!< IDLE frame detected flag */
+#define USART_STAT0_RBNE              BIT(5)                                 /*!< read data buffer not empty */
+#define USART_STAT0_TC                BIT(6)                                 /*!< transmission complete */
+#define USART_STAT0_TBE               BIT(7)                                 /*!< transmit data buffer empty */
+#define USART_STAT0_LBDF              BIT(8)                                 /*!< LIN break detected flag */
+#define USART_STAT0_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)                                 /*!< enable receiver */
+#define USART_CTL0_TEN                BIT(3)                                 /*!< enable transmitter */
+#define USART_CTL0_IDLEIE             BIT(4)                                 /*!< enable idle line detected interrupt */
+#define USART_CTL0_RBNEIE             BIT(5)                                 /*!< enable read data buffer not empty interrupt and overrun error interrupt */
+#define USART_CTL0_TCIE               BIT(6)                                 /*!< enable transmission complete interrupt */
+#define USART_CTL0_TBEIE              BIT(7)                                 /*!< enable transmitter buffer empty interrupt */
+#define USART_CTL0_PERRIE             BIT(8)                                 /*!< enable parity error interrupt */
+#define USART_CTL0_PM                 BIT(9)                                 /*!< parity mode */
+#define USART_CTL0_PCEN               BIT(10)                                /*!< enable parity check function */
+#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)                                /*!< enable USART */
+
+/* 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)                                 /*!< eanble LIN break detected interrupt */
+#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)                                /*!< enable CK pin */
+#define USART_CTL1_STB                BITS(12,13)                            /*!< STOP bits length */
+#define USART_CTL1_LMEN               BIT(14)                                /*!< enable LIN mode */
+
+/* USARTx_CTL2 */
+#define USART_CTL2_ERRIE              BIT(0)                                 /*!< enable error interrupt */
+#define USART_CTL2_IREN               BIT(1)                                 /*!< enable IrDA mode */
+#define USART_CTL2_IRLP               BIT(2)                                 /*!< IrDA low-power */
+#define USART_CTL2_HDEN               BIT(3)                                 /*!< enable half-duplex */
+#define USART_CTL2_NKEN               BIT(4)                                 /*!< mode NACK enable in smartcard */
+#define USART_CTL2_SCEN               BIT(5)                                 /*!< senable martcard mode */
+#define USART_CTL2_DENR               BIT(6)                                 /*!< enable DMA request for reception */
+#define USART_CTL2_DENT               BIT(7)                                 /*!< enable DMA request for transmission */
+#define USART_CTL2_RTSEN              BIT(8)                                 /*!< enable RTS */
+#define USART_CTL2_CTSEN              BIT(9)                                 /*!< enable CTS */
+#define USART_CTL2_CTSIE              BIT(10)                                /*!< enable CTS interrupt */
+
+/* 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 */
+ 
+/* USARTx_CTL3 */
+#define USART_CTL3_RTEN               BIT(0)                                 /*!< enable receiver timeout */
+#define USART_CTL3_SCRTNUM            BITS(1,3)                              /*!< smartcard auto-retry number */
+#define USART_CTL3_RTIE               BIT(4)                                 /*!< interrupt enable bit of receive timeout event */
+#define USART_CTL3_EBIE               BIT(5)                                 /*!< interrupt enable bit of end of block event */
+#define USART_CTL3_RINV               BIT(8)                                 /*!< RX pin level inversion */
+#define USART_CTL3_TINV               BIT(9)                                 /*!< TX pin level inversion */
+#define USART_CTL3_DINV               BIT(10)                                /*!< data bit level inversion */
+#define USART_CTL3_MSBF               BIT(11)                                /*!< most significant bit first */
+
+/* USARTx_RT */
+#define USART_RT_RT                   BITS(0,23)                             /*!< receiver timeout threshold */
+#define USART_RT_BL                   BITS(24,31)                            /*!< block length */
+
+/* USARTx_STAT1 */
+#define USART_STAT1_RTF               BIT(11)                                /*!< receiver timeout flag */
+#define USART_STAT1_EBF               BIT(12)                                /*!< end of block flag */
+#define USART_STAT1_BSY               BIT(16)                                /*!< busy flag */
+
+/* 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) & 0xFFFFU) >> 6)))
+#define USART_BIT_POS(val)                  ((uint32_t)(val) & 0x1FU)
+#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) & 0x1F0000U) >> 16)
+
+/* register offset */
+#define USART_STAT0_REG_OFFSET              ((uint32_t)0x00000000U)          /*!< STAT0 register offset */
+#define USART_STAT1_REG_OFFSET              ((uint32_t)0x00000088U)          /*!< STAT1 register offset */
+#define USART_CTL0_REG_OFFSET               ((uint32_t)0x0000000CU)          /*!< CTL0 register offset */
+#define USART_CTL1_REG_OFFSET               ((uint32_t)0x00000010U)          /*!< CTL1 register offset */
+#define USART_CTL2_REG_OFFSET               ((uint32_t)0x00000014U)          /*!< CTL2 register offset */
+#define USART_CTL3_REG_OFFSET               ((uint32_t)0x00000080U)          /*!< CTL3 register offset */
+
+/* USART flags */
+typedef enum
+{
+    /* flags in STAT0 register */
+    USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U),           /*!< CTS change flag */
+    USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U),           /*!< LIN break detected flag */
+    USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U),           /*!< transmit data buffer empty */
+    USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U),            /*!< transmission complete */
+    USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U),          /*!< read data buffer not empty */
+    USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U),          /*!< IDLE frame detected flag */
+    USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U),         /*!< overrun error */
+    USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U),          /*!< noise error flag */
+    USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U),          /*!< frame error flag */
+    USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U),          /*!< parity error flag */
+    /* flags in STAT1 register */
+    USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U),          /*!< busy flag */
+    USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U),           /*!< end of block flag */
+    USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U)            /*!< receiver timeout 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_STAT0_REG_OFFSET, 0U),       /*!< parity error interrupt and flag */
+    USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U),        /*!< transmitter buffer empty interrupt and flag */
+    USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U),         /*!< transmission complete interrupt and flag */
+    USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_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_STAT0_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_STAT0_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_STAT0_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_STAT0_REG_OFFSET, 9U),       /*!< CTS interrupt and flag */
+    USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U),  /*!< error interrupt and overrun error */
+    USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U),   /*!< error interrupt and noise error flag */
+    USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U),   /*!< error interrupt and frame error flag */
+    /* interrupt flags in CTL3 register */
+    USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U),        /*!< interrupt enable bit of end of block event and flag */
+    USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U)         /*!< interrupt enable bit of receive timeout event and 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 */
+    /* interrupt in CTL3 register */
+    USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U),              /*!< end of block interrupt */
+    USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U)               /*!< receive timeout interrupt */
+}usart_interrupt_enum;
+
+/* configure USART invert */
+typedef enum
+{
+    /* data bit level inversion */
+    USART_DINV_ENABLE,                                                       /*!< data bit level inversion */
+    USART_DINV_DISABLE,                                                      /*!< data bit level not inversion */
+    /* TX pin level inversion */
+    USART_TXPIN_ENABLE,                                                      /*!< TX pin level inversion */
+    USART_TXPIN_DISABLE,                                                     /*!< TX pin level not inversion */
+    /* RX pin level inversion */
+    USART_RXPIN_ENABLE,                                                      /*!< RX pin level inversion */
+    USART_RXPIN_DISABLE                                                      /*!< RX pin level not inversion */
+}usart_invert_enum;
+
+/* configure USART receiver */
+#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 */
+
+/* configure USART transmitter */
+#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 */
+
+/* configure USART DMA request for reception */
+#define CTL2_DENR(regval)             (BIT(6) & ((uint32_t)(regval) << 6))
+#define USART_RECEIVE_DMA_ENABLE      CTL2_DENR(1)                           /*!< enable DAM request for reception */
+#define USART_RECEIVE_DMA_DISABLE     CTL2_DENR(0)                           /*!< disable DAM request for reception */
+
+/* configure USART DMA request for transmission */
+#define CTL2_DENT(regval)             (BIT(7) & ((uint32_t)(regval) << 7))
+#define USART_TRANSMIT_DMA_ENABLE     CTL2_DENT(1)                           /*!< enable DAM request for transmission */
+#define USART_TRANSMIT_DMA_DISABLE    CTL2_DENT(0)                           /*!< disable DAM request for transmission */
+
+/* configure USART RTS */
+#define CLT2_RTSEN(regval)            (BIT(8) & ((uint32_t)(regval) << 8))
+#define USART_RTS_ENABLE              CLT2_RTSEN(1)                          /*!< enable RTS  */
+#define USART_RTS_DISABLE             CLT2_RTSEN(0)                          /*!< disable RTS */
+
+/* configure USART CTS */
+#define CLT2_CTSEN(regval)            (BIT(9) & ((uint32_t)(regval) << 9))
+#define USART_CTS_ENABLE              CLT2_CTSEN(1)                          /*!< enable CTS */
+#define USART_CTS_DISABLE             CLT2_CTSEN(0)                          /*!< disable CTS  */
+
+/* enable USART IrDA low-power */
+#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 */
+
+/* USART data is transmitted/received with the LSB/MSB first */
+#define CTL3_MSBF(regval)             (BIT(11) & ((uint32_t)(regval) << 11))
+#define USART_MSBF_LSB                CTL3_MSBF(0)                           /*!< LSB first */
+#define USART_MSBF_MSB                CTL3_MSBF(1)                           /*!< MSB first */
+
+/* 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);
+/* 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 normal mode communication */
+/* data is transmitted/received with the LSB/MSB first */
+void usart_data_first_config(uint32_t usart_periph, uint32_t msbf);
+/* configure USART inverted */
+void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara);
+/* enable receiver timeout */
+void usart_receiver_timeout_enable(uint32_t usart_periph);
+/* disable receiver timeout */
+void usart_receiver_timeout_disable(uint32_t usart_periph);
+/* configure receiver timeout threshold */
+void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout);
+/* 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);
+/* LIN break detection 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 mode */
+void usart_halfduplex_enable(uint32_t usart_periph);
+/* disable half-duplex mode */
+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,uint8_t guat);
+/* 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);
+/* configure smartcard auto-retry number */
+void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum);
+/* configure block length */
+void usart_block_length_config(uint32_t usart_periph, uint8_t bl);
+
+/* 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);
+
+/* DMA communication */
+/* configure USART DMA reception */
+void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmacmd);
+/* configure USART DMA transmission */
+void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmacmd);
+
+/* flag & interrupt functions */
+/* get flag in STAT0/STAT1 register */
+FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag);
+/* clear flag in STAT0/STAT1 register */
+void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag);
+/* enable USART interrupt */
+void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt);
+/* disable USART interrupt */
+void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt);
+/* get USART interrupt and flag status */
+FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag);
+/* clear interrupt flag in STAT0/STAT1 register */
+void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag);
+
+#endif /* GD32F30x_USART_H */ 

+ 95 - 0
app/LIB/Include/gd32f30x_wwdgt.h

@@ -0,0 +1,95 @@
+/*!
+    \file    gd32f30x_wwdgt.h
+    \brief   definitions for the WWDGT
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 GD32F30X_WWDGT_H
+#define GD32F30X_WWDGT_H
+
+#include "gd32f30x.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 */
+
+/* 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))    
+
+/* 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);
+
+/* check early wakeup interrupt state of WWDGT */
+FlagStatus wwdgt_flag_get(void);
+/* clear early wakeup interrupt state of WWDGT */
+void wwdgt_flag_clear(void);
+/* enable early wakeup interrupt of WWDGT */
+void wwdgt_interrupt_enable(void);
+
+#endif /* GD32F30X_WWDGT_H */

+ 941 - 0
app/LIB/Source/gd32f30x_adc.c

@@ -0,0 +1,941 @@
+/*!
+    \file    gd32f30x_adc.c
+    \brief   ADC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_adc.h"
+
+/*!
+    \brief      reset ADC 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_deinit(uint32_t adc_periph)
+{
+    switch(adc_periph){
+    case ADC0:
+        rcu_periph_reset_enable(RCU_ADC0RST);
+        rcu_periph_reset_disable(RCU_ADC0RST);
+        break;
+    case ADC1:
+        rcu_periph_reset_enable(RCU_ADC1RST);
+        rcu_periph_reset_disable(RCU_ADC1RST);
+        break;
+#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))    
+    case ADC2:
+        rcu_periph_reset_enable(RCU_ADC2RST);
+        rcu_periph_reset_disable(RCU_ADC2RST);
+        break;
+#endif    
+    default:
+        break;      
+    }
+}
+
+/*!
+    \brief      enable ADC interface
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_enable(uint32_t adc_periph)
+{
+    if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){
+        ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
+    }       
+}
+
+/*!
+    \brief      disable ADC interface
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_disable(uint32_t adc_periph)
+{
+    ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON);
+}
+
+/*!
+    \brief      ADC calibration and reset calibration
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_calibration_enable(uint32_t adc_periph)
+{
+    /* reset the selected ADC calibration registers */
+    ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB;
+    /* check the RSTCLB bit state */
+    while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){
+    }
+    /* enable ADC calibration process */
+    ADC_CTL1(adc_periph) |= ADC_CTL1_CLB;
+    /* check the CLB bit state */
+    while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){
+    }
+}
+
+/*!
+    \brief      enable DMA request 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_dma_mode_enable(uint32_t adc_periph)
+{
+    ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA);
+}
+
+/*!
+    \brief      disable DMA request 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_dma_mode_disable(uint32_t adc_periph)
+{
+    ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA);
+}
+
+/*!
+    \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      configure ADC resolution 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  resolution: ADC resolution
+                only one among these parameters can be selected
+      \arg        ADC_RESOLUTION_12B: 12-bit ADC resolution
+      \arg        ADC_RESOLUTION_10B: 10-bit ADC resolution
+      \arg        ADC_RESOLUTION_8B: 8-bit ADC resolution
+      \arg        ADC_RESOLUTION_6B: 6-bit ADC resolution
+    \param[out] none
+    \retval     none
+*/
+void adc_resolution_config(uint32_t adc_periph , uint32_t resolution)
+{
+    ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES);
+    ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution;
+}
+
+/*!
+    \brief      configure ADC discontinuous mode 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: select the channel group
+                only one among these parameters can be selected
+      \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)
+{
+    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 - 1U));
+    
+        ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC;
+        break;
+    case ADC_CHANNEL_DISCON_DISABLE:
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure the ADC sync mode
+    \param[in]  mode: ADC mode
+                only one among these parameters can be selected
+      \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_TRRIGGER_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
+                only one among these parameters can be selected
+    \param[in]  function: the function to config
+                one or more parameters can be selected 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)){
+            ADC_CTL0(adc_periph) |= ADC_SCAN_MODE;
+        }
+        if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
+            ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO;
+        } 
+        if(0U != (function & ADC_CONTINUOUS_MODE)){
+            ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE;
+        }        
+    }else{
+        if(0U != (function & ADC_SCAN_MODE)){
+            ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE;
+        }
+        if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
+            ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO;
+        } 
+        if(0U != (function & ADC_CONTINUOUS_MODE)){
+            ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE;
+        }       
+    }
+}
+
+/*!
+    \brief      configure ADC data alignment 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  data_alignment: data alignment select
+                only one parameter can be selected
+      \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){
+        ADC_CTL1(adc_periph) |= ADC_CTL1_DAL;
+    }else{
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL);
+    }
+}
+
+/*!
+    \brief      configure the length of regular channel group or inserted channel group
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: select the channel group
+                only one parameter can be selected
+      \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:
+        ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL);
+        ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-1U));
+
+        break;
+    case ADC_INSERTED_CHANNEL:
+        ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL);
+        ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-1U));
+    
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      configure ADC regular channel 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \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 among these parameters can be selected
+      \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
+      \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 < 6U){
+        rsq = ADC_RSQ2(adc_periph);
+        rsq &=  ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank)));
+        rsq |= ((uint32_t)adc_channel << (5U*rank));
+        ADC_RSQ2(adc_periph) = rsq;
+    }else if(rank < 12U){
+        rsq = ADC_RSQ1(adc_periph);
+        rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U))));
+        rsq |= ((uint32_t)adc_channel << (5U*(rank-6U)));
+        ADC_RSQ1(adc_periph) = rsq;
+    }else if(rank < 16U){
+        rsq = ADC_RSQ0(adc_periph);
+        rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U))));
+        rsq |= ((uint32_t)adc_channel << (5U*(rank-12U)));
+        ADC_RSQ0(adc_periph) = rsq;
+    }else{
+    }
+    
+    /* ADC sampling time config */
+    if(adc_channel < 10U){
+        sampt = ADC_SAMPT1(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel)));
+        sampt |= (uint32_t)(sample_time << (3U*adc_channel));
+        ADC_SAMPT1(adc_periph) = sampt;
+    }else if(adc_channel < 18U){
+        sampt = ADC_SAMPT0(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U))));
+        sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U)));
+        ADC_SAMPT0(adc_periph) = sampt;
+    }else{
+    }
+}
+
+/*!
+    \brief      configure ADC inserted channel 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \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 among these parameters can be selected
+      \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
+      \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;
+    
+    inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
+    
+    isq = ADC_ISQ(adc_periph);
+    isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3 + rank) - inserted_length))));
+    isq |= ((uint32_t)adc_channel << (5U * ((3 + rank) - inserted_length)));
+    ADC_ISQ(adc_periph) = isq;
+
+    /* ADC sampling time config */  
+    if(adc_channel < 10U){
+        sampt = ADC_SAMPT1(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel)));
+        sampt |= (uint32_t) sample_time << (3U*adc_channel);
+        ADC_SAMPT1(adc_periph) = sampt;
+    }else if(adc_channel < 18U){
+        sampt = ADC_SAMPT0(adc_periph);
+        sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U))));
+        sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U)));
+        ADC_SAMPT0(adc_periph) = sampt;
+    }else{
+    }
+}
+
+/*!
+    \brief      configure ADC inserted channel offset 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \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 = 3U - (inserted_length - inserted_channel);
+    
+    if(num <= 3U){
+        /* calculate the offset of the register */
+        num = num * 4U;
+        /* config the offset of the selected channels */
+        REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset);
+    }  
+}
+
+/*!
+    \brief      enable ADC external trigger 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: select the channel group
+                one or more parameters can be selected
+      \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)){
+            ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC;
+        }
+        if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+            ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC;
+        }        
+    }else{
+        if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
+            ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC;
+        }
+        if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+            ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC;
+        }      
+    }
+}
+
+/*!
+    \brief      configure ADC external trigger source 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: select the channel group
+                only one parameter can be selected
+      \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: timer 0 CC0 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T0_CH1: timer 0 CC1 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T1_CH1: timer 1 CC1 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T2_TRGO: timer 2 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T3_CH3: timer 3 CC3 event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11 
+      \arg        ADC2_EXTTRIG_REGULAR_T2_CH0: timer 2 CC0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T1_CH2: timer 1 CC2 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T7_CH0: timer 7 CC0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T4_CH0: timer 4 CC0 event select 
+      \arg        ADC2_EXTTRIG_REGULAR_T4_CH2: timer 4 CC2 event select
+      \arg        ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger      
+                for inserted channel:
+      \arg        ADC0_1_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T1_TRGO: timer 1 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T1_CH0: timer 1 CC0 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T2_CH3: timer 2 CC3 event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T3_TRGO: timer 3 TRGO event select 
+      \arg        ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 
+      \arg        ADC0_1_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T3_CH2: timer 3 CC2 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T7_CH1: timer 7 CC1 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select 
+      \arg        ADC2_EXTTRIG_INSERTED_T4_TRGO: timer 4 TRGO event select
+      \arg        ADC2_EXTTRIG_INSERTED_T4_CH3: timer 4 CC3 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:
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC);
+        ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC);
+        ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
+        break;
+    default:
+        break;
+    }
+}
+
+/*!
+    \brief      enable ADC software trigger 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: select the channel group
+                one or more parameters can be selected
+      \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)){
+        ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST;
+    }
+    if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
+        ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST;
+    }
+}
+
+/*!
+    \brief      read ADC regular group data register 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \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
+                only one among these parameters can be selected
+    \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:
+        idata = ADC_IDATA0(adc_periph);
+        break;
+    case ADC_INSERTED_CHANNEL_1:
+        idata = ADC_IDATA1(adc_periph);
+        break;
+    case ADC_INSERTED_CHANNEL_2:
+        idata = ADC_IDATA2(adc_periph);
+        break;
+    case ADC_INSERTED_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      get the ADC flag bits
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_flag: the adc flag bits
+                only one parameter can be selected
+      \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
+                only one among these parameters can be selected
+    \param[in]  adc_flag: the adc flag bits
+                one or more parameters can be selected
+      \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 ADC interrupt bits
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_interrupt: the adc interrupt bits
+                only oneparameter can be selected
+      \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:
+        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:
+        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:
+        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
+                only one among these parameters can be selected
+    \param[in]  adc_interrupt: the adc status flag
+                one or more parameters can be selected
+      \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
+                only one among these parameters can be selected
+    \param[in]  adc_interrupt: the adc interrupt
+                one or more parameters can be selected
+      \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)
+{
+    if(0U != (adc_interrupt & ADC_INT_WDE)){  
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE;
+    }  
+
+    if(0U != (adc_interrupt & ADC_INT_EOC)){      
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE;
+    }  
+
+    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
+                only one among these parameters can be selected
+    \param[in]  adc_interrupt: the adc interrupt flag
+                one or more parameters can be selected
+      \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)
+{  
+    if(0U != (adc_interrupt & ADC_INT_WDE)){  
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE;
+    }  
+
+    if(0U != (adc_interrupt & ADC_INT_EOC)){      
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE;
+    }  
+
+    if(0U != (adc_interrupt & ADC_INT_EOIC)){      
+        ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE;
+    }
+}
+
+/*!
+    \brief      configure ADC analog watchdog single channel 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  adc_channel: the selected ADC channel
+                only one among these parameters can be selected
+      \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);
+
+    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
+                only one among these parameters can be selected
+    \param[in]  adc_channel_group: the channel group use analog watchdog
+                only one parameter can be selected 
+      \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:
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN;
+        break;
+    case ADC_INSERTED_CHANNEL:
+        ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN;
+        break;
+    case ADC_REGULAR_INSERTED_CHANNEL:
+        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
+                only one among these parameters can be selected
+    \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
+                only one among these parameters can be selected
+    \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      configure ADC oversample mode 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[in]  mode: ADC oversampling mode
+                only oneparameter can be selected
+      \arg        ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger
+      \arg        ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger
+    \param[in]  shift: ADC oversampling shift
+                only oneparameter can be selected
+      \arg        ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift
+      \arg        ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift
+    \param[in]  ratio: ADC oversampling ratio
+                only oneparameter can be selected
+      \arg        ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2
+      \arg        ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4
+      \arg        ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8
+      \arg        ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16
+      \arg        ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32
+      \arg        ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64
+      \arg        ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128
+      \arg        ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256
+    \param[out] none
+    \retval     none
+*/
+void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio)
+{
+    if(ADC_OVERSAMPLING_ONE_CONVERT == mode){
+        ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS;
+    }else{
+        ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS);
+    }
+    /* config the shift and ratio */
+    ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS));
+    ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio);
+}
+
+/*!
+    \brief      enable ADC oversample mode 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_oversample_mode_enable(uint32_t adc_periph)
+{
+    ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN;
+}
+
+/*!
+    \brief      disable ADC oversample mode 
+    \param[in]  adc_periph: ADCx,x=0,1,2
+                only one among these parameters can be selected
+    \param[out] none
+    \retval     none
+*/
+void adc_oversample_mode_disable(uint32_t adc_periph)
+{
+    ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN);
+}

+ 328 - 0
app/LIB/Source/gd32f30x_bkp.c

@@ -0,0 +1,328 @@
+/*!
+    \file    gd32f30x_bkp.c
+    \brief   BKP driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_bkp.h"
+
+#define TAMPER_FLAG_SHIFT          ((uint8_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
+      \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_write_data(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
+      \arg        BKP_DATA_x(x = 0..41): bkp data register number x
+    \param[out] none
+    \retval     data of BKP data register
+*/
+uint16_t bkp_read_data(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
+      \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;
+    
+    ctl = BKP_OCTL;
+    ctl &= (uint16_t)~BKP_OCTL_ROSEL;
+    ctl |= outputsel;
+    BKP_OCTL = ctl;
+}
+
+/*!
+    \brief      select RTC clock output
+    \param[in]  clocksel: RTC clock output selection
+      \arg        RTC_CLOCK_DIV_64: RTC clock div 64
+      \arg        RTC_CLOCK_DIV_1: RTC clock
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_clock_output_select(uint16_t clocksel)
+{
+    uint16_t ctl = 0U;
+    
+    ctl = BKP_OCTL;
+    ctl &= (uint16_t)~BKP_OCTL_CCOSEL;
+    ctl |= clocksel;
+    BKP_OCTL = ctl;
+}
+
+/*!
+    \brief      RTC clock calibration direction
+    \param[in]  direction: RTC clock calibration direction
+      \arg        RTC_CLOCK_SLOWED_DOWN: RTC clock slow down
+      \arg        RTC_CLOCK_SPEED_UP: RTC clock speed up
+    \param[out] none
+    \retval     none
+*/
+void bkp_rtc_clock_calibration_direction(uint16_t direction)
+{
+    uint16_t ctl = 0U;
+    
+    ctl = BKP_OCTL;
+    ctl &= (uint16_t)~BKP_OCTL_CALDIR;
+    ctl |= direction;
+    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;
+    
+    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
+      \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;
+    
+    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_tamper_interrupt_enable(void)
+{
+    BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE;
+}
+
+/*!
+    \brief      disable tamper interrupt
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void bkp_tamper_interrupt_disable(void)
+{
+    BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE;
+}
+
+/*!
+    \brief      get bkp flag state
+    \param[in]  flag
+      \arg        BKP_FLAG_TAMPER: tamper event flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus bkp_flag_get(uint16_t flag)
+{
+    if(RESET != (BKP_TPCS & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear bkp flag state
+    \param[in]  flag
+      \arg        BKP_FLAG_TAMPER: tamper event flag
+    \param[out] none
+    \retval     none
+*/
+void bkp_flag_clear(uint16_t flag)
+{
+        BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT);
+}
+
+/*!
+    \brief      get bkp interrupt flag state
+    \param[in]  flag
+      \arg        BKP_INT_FLAG_TAMPER: tamper interrupt flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus bkp_interrupt_flag_get(uint16_t flag)
+{
+    if(RESET != (BKP_TPCS & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear bkp interrupt flag state
+    \param[in]  flag
+      \arg        BKP_INT_FLAG_TAMPER: tamper interrupt flag
+    \param[out] none
+    \retval     none
+*/
+void bkp_interrupt_flag_clear(uint16_t flag)
+{
+    BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT);
+}
+

File diff suppressed because it is too large
+ 1043 - 0
app/LIB/Source/gd32f30x_can.c


+ 130 - 0
app/LIB/Source/gd32f30x_crc.c

@@ -0,0 +1,130 @@
+/*!
+    \file    gd32f30x_crc.c
+    \brief   CRC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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(CRC_DATA) to the value of 0xFFFFFFFF
+    \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: specified 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(const uint32_t *array, uint32_t size)
+{
+    uint32_t index;
+    for(index = 0U; index < size; index++){
+        CRC_DATA = *(array+index);
+    }
+    return (CRC_DATA);
+}

+ 391 - 0
app/LIB/Source/gd32f30x_ctc.c

@@ -0,0 +1,391 @@
+/*!
+    \file    gd32f30x_ctc.c
+    \brief   CTC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_ctc.h"
+
+#define CTC_FLAG_MASK            ((uint32_t)0x00000700U)
+
+/* CTC register bit offset */
+#define CTC_TRIMVALUE_OFFSET     ((uint32_t)8U)
+#define CTC_TRIM_VALUE_OFFSET    ((uint32_t)8U)
+#define CTC_REFCAP_OFFSET        ((uint32_t)16U)
+#define CTC_LIMIT_VALUE_OFFSET   ((uint32_t)16U)
+
+/*!
+    \brief      reset CTC clock trim controller
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ctc_deinit(void)
+{
+    /* reset CTC */
+    rcu_periph_reset_enable(RCU_CTCRST);
+    rcu_periph_reset_disable(RCU_CTCRST);
+}
+
+/*!
+    \brief      enable CTC trim counter
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ctc_counter_enable(void)
+{
+    CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
+}
+
+/*!
+    \brief      disable CTC trim counter
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ctc_counter_disable(void)
+{
+    CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
+}
+
+/*!
+    \brief      configure the IRC48M trim value
+    \param[in]  trim_value: 6-bit IRC48M trim value
+      \arg        0x00 - 0x3F
+    \param[out] none
+    \retval     none
+*/
+void ctc_irc48m_trim_value_config(uint8_t trim_value)
+{
+    /* clear TRIMVALUE bits */
+    CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
+    /* set TRIMVALUE bits */
+    CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET);
+}
+
+/*!
+    \brief      generate software reference source sync pulse
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void ctc_software_refsource_pulse_generate(void)
+{
+    CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
+}
+
+/*!
+    \brief      configure hardware automatically trim mode
+    \param[in]  hardmode:
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
+      \arg        CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
+    \param[out] none
+    \retval     none
+*/
+void ctc_hardware_trim_mode_config(uint32_t hardmode)
+{
+    CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
+    CTC_CTL0 |= (uint32_t)hardmode;
+}
+/*!
+    \brief      configure reference signal source polarity
+    \param[in]  polarity:
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
+      \arg        CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
+    \param[out] none
+    \retval     none
+*/
+void ctc_refsource_polarity_config(uint32_t polarity)
+{
+    CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
+    CTC_CTL1 |= (uint32_t)polarity;
+}
+
+/*!
+    \brief      select reference signal source
+    \param[in]  refs:
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_REFSOURCE_GPIO: GPIO is selected
+      \arg        CTC_REFSOURCE_LXTAL: LXTAL is selected
+    \param[out] none
+    \retval     none
+*/
+void ctc_refsource_signal_select(uint32_t refs)
+{
+    CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
+    CTC_CTL1 |= (uint32_t)refs;
+}
+
+/*!
+    \brief      configure reference signal source prescaler
+    \param[in]  prescaler:
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_REFSOURCE_PSC_OFF: reference signal not divided
+      \arg        CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
+      \arg        CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
+      \arg        CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
+      \arg        CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
+      \arg        CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
+      \arg        CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
+      \arg        CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
+    \param[out] none
+    \retval     none
+*/
+void ctc_refsource_prescaler_config(uint32_t prescaler)
+{
+    CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
+    CTC_CTL1 |= (uint32_t)prescaler;
+}
+
+/*!
+    \brief      configure clock trim base limit value
+    \param[in]  limit_value: 8-bit clock trim base limit value
+      \arg        0x00 - 0xFF
+    \param[out] none
+    \retval     none
+*/
+void ctc_clock_limit_value_config(uint8_t limit_value)
+{
+    CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
+    CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
+}
+
+/*!
+    \brief      configure CTC counter reload value
+    \param[in]  reload_value: 16-bit CTC counter reload value
+      \arg        0x0000 - 0xFFFF
+    \param[out] none
+    \retval     none
+*/
+void ctc_counter_reload_value_config(uint16_t reload_value)
+{
+    CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
+    CTC_CTL1 |= (uint32_t)reload_value;
+}
+
+/*!
+    \brief      read CTC counter capture value when reference sync pulse occurred
+    \param[in]  none
+    \param[out] none
+    \retval     the 16-bit CTC counter capture value
+*/
+uint16_t ctc_counter_capture_value_read(void)
+{
+    uint16_t capture_value = 0U;
+    capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET);
+    return (capture_value);
+}
+
+/*!
+    \brief      read CTC trim counter direction when reference sync pulse occurred
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+      \arg        SET: CTC trim counter direction is down-counting
+      \arg        RESET: CTC trim counter direction is up-counting
+*/
+FlagStatus ctc_counter_direction_read(void)
+{
+    if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      read CTC counter reload value
+    \param[in]  none
+    \param[out] none
+    \retval     the 16-bit CTC counter reload value
+*/
+uint16_t ctc_counter_reload_value_read(void)
+{
+    uint16_t reload_value = 0U;
+    reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
+    return (reload_value);
+}
+
+/*!
+    \brief      read the IRC48M trim value
+    \param[in]  none
+    \param[out] none
+    \retval     the 6-bit IRC48M trim value
+*/
+uint8_t ctc_irc48m_trim_value_read(void)
+{
+    uint8_t trim_value = 0U;
+    trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
+    return (trim_value);
+}
+
+/*!
+    \brief      get CTC flag
+    \param[in]  flag: the CTC flag
+                only one parameter can be selected which is shown as below: 
+      \arg        CTC_FLAG_CKOK: clock trim OK flag
+      \arg        CTC_FLAG_CKWARN: clock trim warning flag 
+      \arg        CTC_FLAG_ERR: error flag 
+      \arg        CTC_FLAG_EREF: expect reference flag
+      \arg        CTC_FLAG_CKERR: clock trim error bit
+      \arg        CTC_FLAG_REFMISS: reference sync pulse miss
+      \arg        CTC_FLAG_TRIMERR: trim value error bit
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus ctc_flag_get(uint32_t flag)
+{
+    if(RESET != (CTC_STAT & flag)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear CTC flag
+    \param[in]  flag: the CTC flag
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_FLAG_CKOK: clock trim OK flag
+      \arg        CTC_FLAG_CKWARN: clock trim warning flag 
+      \arg        CTC_FLAG_ERR: error flag 
+      \arg        CTC_FLAG_EREF: expect reference flag
+      \arg        CTC_FLAG_CKERR: clock trim error bit
+      \arg        CTC_FLAG_REFMISS: reference sync pulse miss
+      \arg        CTC_FLAG_TRIMERR: trim value error bit
+    \param[out] none
+    \retval     none
+*/
+void ctc_flag_clear(uint32_t flag)
+{
+    if(RESET != (flag & CTC_FLAG_MASK)){
+        CTC_INTC |= CTC_INTC_ERRIC;
+    }else{
+        CTC_INTC |= flag;
+    }
+}
+
+/*!
+    \brief      enable the CTC interrupt
+    \param[in]  interrupt: CTC interrupt enable
+                one or more parameters can be selected which are shown as below:
+      \arg        CTC_INT_CKOK: clock trim OK interrupt enable
+      \arg        CTC_INT_CKWARN: clock trim warning interrupt enable
+      \arg        CTC_INT_ERR: error interrupt enable
+      \arg        CTC_INT_EREF: expect reference interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void ctc_interrupt_enable(uint32_t interrupt)
+{
+    CTC_CTL0 |= (uint32_t)interrupt; 
+}
+
+/*!
+    \brief      disable the CTC interrupt
+    \param[in]  interrupt: CTC interrupt enable source
+                one or more parameters can be selected which are shown as below:
+      \arg        CTC_INT_CKOK: clock trim OK interrupt enable
+      \arg        CTC_INT_CKWARN: clock trim warning interrupt enable
+      \arg        CTC_INT_ERR: error interrupt enable
+      \arg        CTC_INT_EREF: expect reference interrupt enable
+    \param[out] none
+    \retval     none
+*/
+void ctc_interrupt_disable(uint32_t interrupt)
+{
+    CTC_CTL0 &= (uint32_t)(~interrupt); 
+}
+
+/*!
+    \brief      get CTC interrupt flag
+    \param[in]  int_flag: the CTC interrupt flag
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_INT_FLAG_CKOK: clock trim OK interrupt
+      \arg        CTC_INT_FLAG_CKWARN: clock trim warning interrupt 
+      \arg        CTC_INT_FLAG_ERR: error interrupt 
+      \arg        CTC_INT_FLAG_EREF: expect reference interrupt
+      \arg        CTC_INT_FLAG_CKERR: clock trim error bit interrupt
+      \arg        CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt 
+      \arg        CTC_INT_FLAG_TRIMERR: trim value error interrupt
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus ctc_interrupt_flag_get(uint32_t int_flag)
+{
+    uint32_t interrupt_flag = 0U, intenable = 0U;
+    
+    /* check whether the interrupt is enabled */
+    if(RESET != (int_flag & CTC_FLAG_MASK)){
+        intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
+    }else{
+        intenable = CTC_CTL0 & int_flag;
+    }
+    
+    /* get interrupt flag status */
+    interrupt_flag = CTC_STAT & int_flag;
+
+    if(interrupt_flag && intenable){
+        return SET;
+    }else{
+        return RESET;
+    }
+}
+
+/*!
+    \brief      clear CTC interrupt flag
+    \param[in]  int_flag: the CTC interrupt flag
+                only one parameter can be selected which is shown as below:
+      \arg        CTC_INT_FLAG_CKOK: clock trim OK interrupt
+      \arg        CTC_INT_FLAG_CKWARN: clock trim warning interrupt 
+      \arg        CTC_INT_FLAG_ERR: error interrupt 
+      \arg        CTC_INT_FLAG_EREF: expect reference interrupt 
+      \arg        CTC_INT_FLAG_CKERR: clock trim error bit interrupt
+      \arg        CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt 
+      \arg        CTC_INT_FLAG_TRIMERR: trim value error interrupt
+    \param[out] none
+    \retval     none
+*/ 
+void ctc_interrupt_flag_clear(uint32_t int_flag)
+{
+    if(RESET != (int_flag & CTC_FLAG_MASK)){
+        CTC_INTC |= CTC_INTC_ERRIC;
+    }else{
+        CTC_INTC |= int_flag;
+    }
+}
+

+ 541 - 0
app/LIB/Source/gd32f30x_dac.c

@@ -0,0 +1,541 @@
+/*!
+    \file    gd32f30x_dac.c
+    \brief   DAC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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: 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: 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: 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: 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: 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: 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: 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: DACx(x = 0,1)
+    \param[in]  dac_align: data alignment
+                only one parameter can be selected which is shown as below:
+      \arg        DAC_ALIGN_8B_R: data right 8 bit alignment
+      \arg        DAC_ALIGN_12B_R: data right 12 bit alignment
+      \arg        DAC_ALIGN_12B_L: data left 12 bit 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 12 bit alignment */
+        case DAC_ALIGN_12B_R:
+            DAC0_R12DH = data;
+            break;
+        /* data left 12 bit alignment */
+        case DAC_ALIGN_12B_L:
+            DAC0_L12DH = data;
+            break;
+        /* data right 8 bit alignment */
+        case DAC_ALIGN_8B_R:
+            DAC0_R8DH = data;
+            break;
+        default:
+            break;
+        }
+    }else{
+        switch(dac_align){
+        /* data right 12 bit alignment */
+        case DAC_ALIGN_12B_R:
+            DAC1_R12DH = data;
+            break;
+        /* data left 12 bit alignment */
+        case DAC_ALIGN_12B_L:
+            DAC1_L12DH = data;
+            break;
+        /* data right 8 bit alignment */
+        case DAC_ALIGN_8B_R:
+            DAC1_R8DH = data;
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+/*!
+    \brief      enable DAC trigger
+    \param[in]  dac_periph: 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: 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: 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 GD32F30X_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 GD32F30X_HD and GD32F30X_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: 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: 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: DACx(x = 0,1)
+    \param[in]  wave_mode: noise 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: DACx(x = 0,1)
+    \param[in]  bit_width: noise wave 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: DACx(x = 0,1)
+    \param[in]  unmask_bits: unmask LFSR bits in DAC LFSR noise mode
+                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: DACx(x = 0,1)
+    \param[in]  amplitude: triangle amplitude in DAC triangle noise mode
+                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: data alignment
+                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;
+    }
+}

+ 148 - 0
app/LIB/Source/gd32f30x_dbg.c

@@ -0,0 +1,148 @@
+/*!
+    \file    gd32f30x_dbg.c
+    \brief   DBG driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_dbg.h"
+
+#define DBG_RESET_VAL       0x00000000U
+
+/*!
+    \brief      deinitialize the DBG
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dbg_deinit(void)
+{
+    DBG_CTL0 = DBG_RESET_VAL;
+}
+
+/*!
+    \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:
+                this parameter can be any combination of the following values:
+      \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_CTL0 |= dbg_low_power;
+}
+
+/*!
+    \brief      disable low power behavior when the mcu is in debug mode
+    \param[in]  dbg_low_power:
+                this parameter can be any combination of the following values:
+      \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_CTL0 &= ~dbg_low_power;
+}
+
+/*!
+    \brief      enable peripheral behavior when the mcu is in debug mode
+    \param[in]  dbg_periph: refer to dbg_periph_enum
+                only one parameter can be selected which is 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_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph));
+}
+
+/*!
+    \brief      disable peripheral behavior when the mcu is in debug mode
+    \param[in]  dbg_periph: refer to dbg_periph_enum
+                only one parameter can be selected which is 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 not available for HD series): hold TIMERx counter when core is halted
+    \param[out] none
+    \retval     none
+*/
+void dbg_periph_disable(dbg_periph_enum dbg_periph)
+{
+    DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph));
+}
+
+/*!
+    \brief      enable trace pin assignment
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dbg_trace_pin_enable(void)
+{
+    DBG_CTL0 |= DBG_CTL0_TRACE_IOEN;
+}
+
+/*!
+    \brief      disable trace pin assignment
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void dbg_trace_pin_disable(void)
+{
+    DBG_CTL0 &= ~DBG_CTL0_TRACE_IOEN;
+}

+ 735 - 0
app/LIB/Source/gd32f30x_dma.c

@@ -0,0 +1,735 @@
+/*!
+    \file    gd32f30x_dma.c
+    \brief   DMA driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_dma.h"
+#include <stdlib.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)
+{
+    if(NULL == init_struct){
+        DMA_WRONG_HANDLE
+    }
+
+    /* 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 and priority */
+    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
+    \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, uint32_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;
+
+    if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
+        reval = SET;
+    }else{
+        reval = RESET;
+    }
+
+    return reval;
+}
+
+/*!
+    \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_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:
+            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:
+            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:
+            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
+        }
+
+    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     none
+*/
+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;
+}

File diff suppressed because it is too large
+ 3680 - 0
app/LIB/Source/gd32f30x_enet.c


+ 677 - 0
app/LIB/Source/gd32f30x_exmc.c

@@ -0,0 +1,677 @@
+/*!
+    \file    gd32f30x_exmc.c
+    \brief   EXMC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_exmc.h"
+
+/* EXMC bank0 register reset value */
+#define BANK0_SNCTL_REGION0_RESET         ((uint32_t)0x000030DBU)
+#define BANK0_SNCTL_REGION1_2_3_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)0x00000042U)
+#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)0x00000043U)
+#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]  exmc_norsram_region: select the region of bank0
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_deinit(uint32_t exmc_norsram_region)
+{
+    /* reset the registers */
+    if(EXMC_BANK0_NORSRAM_REGION0 == exmc_norsram_region){
+        EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION0_RESET;
+    }else{
+        EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION1_2_3_RESET;
+    }
+    EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET;
+    EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET;
+}
+
+/*!
+    \brief      initialize exmc_norsram_parameter_struct with the default values
+    \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 values */
+    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      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_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | 
+                          EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | 
+                          EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | 
+                          EXMC_SNCTL_SYNCWR ));
+
+    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 ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
+                           (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
+                           (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
+                            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      enable EXMC NOR/PSRAM bank region
+    \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_enable(uint32_t exmc_norsram_region)
+{
+    EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
+}
+
+/*!
+    \brief      disable EXMC NOR/PSRAM bank region
+    \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM Bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_disable(uint32_t exmc_norsram_region)
+{
+    EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
+}
+
+/*!
+    \brief      deinitialize EXMC NAND bank
+    \param[in]  exmc_nand_bank: select the bank of NAND
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANKx_NAND(x=1..2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_deinit(uint32_t exmc_nand_bank)
+{
+    /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */
+    EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET;
+    EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET;
+    EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET;
+    EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET;
+}
+
+/*!
+    \brief      initialize exmc_norsram_parameter_struct with the default values
+    \param[in]  none
+    \param[out] the initialized struct exmc_norsram_parameter_struct pointer
+    \retval     none
+*/
+void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
+{
+    /* configure the structure with default values */
+    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      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      enable NAND bank
+    \param[in]  exmc_nand_bank: specifie the NAND bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_enable(uint32_t exmc_nand_bank)
+{
+    EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN;
+}
+
+/*!
+    \brief      disable NAND bank
+    \param[in]  exmc_nand_bank: specifie the NAND bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     none
+*/
+void exmc_nand_disable(uint32_t exmc_nand_bank)
+{
+    EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_NDBKEN);
+}
+
+/*!
+    \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_pccard_parameter_struct parameter with the default values
+    \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 values */
+    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      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      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      configure CRAM page size
+    \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
+    \param[in]  page_size: CRAM page size
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
+      \arg        EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
+      \arg        EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
+      \arg        EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
+      \arg        EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
+    \param[out] none
+    \retval     none
+*/
+void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size)
+{
+    /* reset the bits */
+    EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS;
+
+    /* set the CPS bits */
+    EXMC_SNCTL(exmc_norsram_region) |= page_size;
+}
+
+/*!
+    \brief      enable or disable the EXMC NAND ECC function
+    \param[in]  exmc_nand_bank: specifie the NAND bank
+                only one parameter can be selected which is shown as below:
+      \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 exmc_nand_bank, ControlStatus newvalue)
+{
+    if (ENABLE == newvalue){
+        /* enable the selected NAND bank ECC function */
+        EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN;
+    }else{
+        /* disable the selected NAND bank ECC function */
+        EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_ECCEN);
+    }
+}
+
+/*!
+    \brief      get the EXMC ECC value
+    \param[in]  exmc_nand_bank: specifie the NAND bank
+                only one parameter can be selected which is shown as below:
+      \arg        EXMC_BANKx_NAND(x=1,2)
+    \param[out] none
+    \retval     the error correction code(ECC) value
+*/
+uint32_t exmc_ecc_get(uint32_t exmc_nand_bank)
+{
+    return (EXMC_NECC(exmc_nand_bank));
+}
+
+/*!
+    \brief      enable EXMC interrupt
+    \param[in]  exmc_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: EXMC interrupt flag
+                only one parameter can be selected which are shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(exmc_bank) |= interrupt;
+}
+
+/*!
+    \brief      disable EXMC interrupt
+    \param[in]  exmc_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: EXMC interrupt flag
+                only one parameter can be selected which are shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(exmc_bank) &= (~interrupt);
+}
+
+/*!
+    \brief      get EXMC flag status
+    \param[in]  exmc_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: EXMC status and flag
+                only one parameter can be selected which are 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 exmc_bank,uint32_t flag)
+{
+    uint32_t status = 0x00000000U;
+
+    /* NAND bank1,bank2 or PC card bank3 */
+    status = EXMC_NPINTEN(exmc_bank);
+    
+    if ((status & flag) != (uint32_t)flag ){
+        /* flag is reset */
+        return RESET;
+    }else{
+        /* flag is set */
+        return SET;
+    }
+}
+
+/*!
+    \brief      clear EXMC flag status
+    \param[in]  exmc_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: EXMC status and flag
+                only one parameter can be selected which are 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 exmc_bank,uint32_t flag)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(exmc_bank) &= (~flag);
+}
+
+/*!
+    \brief      get EXMC interrupt flag
+    \param[in]  exmc_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: EXMC interrupt flag
+                only one parameter can be selected which are shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+*/
+FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt)
+{
+    uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U;
+
+    /* NAND bank1,bank2 or PC card bank3 */
+    status = EXMC_NPINTEN(exmc_bank);
+    interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET));
+
+    interrupt_enable = (status & interrupt);
+
+    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]  exmc_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: EXMC interrupt flag
+                only one parameter can be selected which are shown as below:
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
+      \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
+    \param[out] none
+    \retval     none
+*/
+void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt)
+{
+    /* NAND bank1,bank2 or PC card bank3 */
+    EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET);
+}

+ 252 - 0
app/LIB/Source/gd32f30x_exti.c

@@ -0,0 +1,252 @@
+/*!
+    \file    gd32f30x_exti.c
+    \brief   EXTI driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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 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[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      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      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 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      enable the software interrupt event 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_software_interrupt_enable(exti_line_enum linex)
+{
+    EXTI_SWIEV |= (uint32_t)linex;
+}
+
+/*!
+    \brief      disable the software interrupt event 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_software_interrupt_disable(exti_line_enum linex)
+{
+    EXTI_SWIEV &= ~(uint32_t)linex;
+}
+
+/*!
+    \brief      get EXTI line x interrupt 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     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 line x interrupt 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 line x interrupt 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     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 line x interrupt 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;
+}

File diff suppressed because it is too large
+ 1009 - 0
app/LIB/Source/gd32f30x_fmc.c


+ 223 - 0
app/LIB/Source/gd32f30x_fwdgt.c

@@ -0,0 +1,223 @@
+/*!
+    \file    gd32f30x_fwdgt.c
+    \brief   FWDGT driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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      configure the free watchdog timer counter prescaler value
+    \param[in]  prescaler_value: specify 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_prescaler_value_config(uint16_t prescaler_value)
+{
+    uint32_t timeout = FWDGT_PSC_TIMEOUT;
+    uint32_t flag_status = RESET;
+
+    /* enable write access to FWDGT_PSC */
+    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_value;
+
+    return SUCCESS;
+}
+
+/*!
+    \brief      configure the free watchdog timer counter reload value
+    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
+    \param[out] none
+    \retval     ErrStatus: ERROR or SUCCESS
+*/
+ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
+{
+    uint32_t timeout = FWDGT_RLD_TIMEOUT;
+    uint32_t flag_status = RESET;
+
+    /* enable write access to FWDGT_RLD */
+    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
+
+    /* 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);
+
+    return SUCCESS;
+}
+
+/*!
+    \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;
+}

+ 583 - 0
app/LIB/Source/gd32f30x_gpio.c

@@ -0,0 +1,583 @@
+/*!
+    \file    gd32f30x_gpio.c
+    \brief   GPIO driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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)0xF8FFFFFFU)  /*!< 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
+      \arg        GPIO_OSPEED_MAX: output max speed more than 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 */
+        if(GPIO_OSPEED_MAX == (uint32_t)speed){
+            temp_mode |= (uint32_t)0x03U;
+            /* set the corresponding SPD bit */
+            GPIOx_SPD(gpio_periph) |= (uint32_t)pin ;
+        }else{
+            /* 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
+                only one parameter 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
+                only one parameter 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
+                only one parameter can be selected which are shown as below:
+      \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_REMAP0: TIMER1 partial remapping
+      \arg        GPIO_TIMER1_PARTIAL_REMAP1: 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 GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F30X_CL devices)
+      \arg        GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F30X_CL devices)
+      \arg        GPIO_PD01_REMAP: PD01 remapping
+      \arg        GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
+      \arg        GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices)
+      \arg        GPIO_ENET_REMAP: ENET remapping(only for GD32F30X_CL devices) 
+      \arg        GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F30X_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 
+      \arg        GPIO_TIMER1ITR0_REMAP: TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices)
+      \arg        GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F30X_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
+      \arg        GPIO_CTC_REMAP0: CTC remapping(PD15)
+      \arg        GPIO_CTC_REMAP1: CTC remapping(PF0)
+    \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(((uint32_t)0x80000000U) == (remap & 0x80000000U)){
+        /* 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;
+    }
+}
+
+#ifdef GD32F30X_CL
+/*!
+    \brief      select ethernet MII or RMII PHY
+    \param[in]  enet_sel: 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 enet_sel)
+{
+    /* 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)enet_sel;
+}
+#endif /* GD32F30X_CL */
+
+/*!
+    \brief      select GPIO pin exti sources
+    \param[in]  output_port: gpio event output port
+                only one parameter can be selected which are shown as below:
+      \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]  output_pin: GPIO output pin source
+                only one parameter can be selected which are shown as below:
+      \arg        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
+    \param[in]  output_pin: GPIO event 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);
+}
+
+/*!
+    \brief      configure the I/O compensation cell
+    \param[in]  compensation: specifies the I/O compensation cell mode
+                only one parameter can be selected which are shown as below:
+      \arg        GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled
+      \arg        GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled
+    \param[out] none
+    \retval     none
+*/
+void gpio_compensation_config(uint32_t compensation)
+{
+    uint32_t reg;
+    reg = AFIO_CPSCTL;
+
+    /* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */
+    reg &= ~AFIO_CPSCTL_CPS_EN;
+    AFIO_CPSCTL = (reg | compensation);
+}
+
+/*!
+    \brief      check the I/O compensation cell is ready or not
+    \param[in]  none
+    \param[out] none
+    \retval     FlagStatus: SET or RESET
+  */
+FlagStatus gpio_compensation_flag_get(void)
+{
+    if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
+        return SET;
+    }else{
+        return RESET;
+    }
+}

+ 738 - 0
app/LIB/Source/gd32f30x_i2c.c

@@ -0,0 +1,738 @@
+/*!
+    \file    gd32f30x_i2c.c
+    \brief   I2C driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2019-04-16, V2.0.1, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_i2c.h"
+
+#define I2C_ERROR_HANDLE(s)           do{}while(1)
+
+#define I2CCLK_MAX                    ((uint32_t)0x0000003CU)             /*!< 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)0x00000008U)             /* 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)
+                          and fast mode plus (up to 1MHz)
+    \param[in]  dutycyc: duty cycle in fast mode or fast mode plus
+                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;
+    
+    /* check the clkspeed value */
+    if(0U == clkspeed){
+        I2C_ERROR_HANDLE("the parameter can not be 0 \r\n");
+    }
+    
+    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{
+        /* fast mode plus, the maximum SCL rise time is 120ns */
+        I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(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;
+        }
+        /* enable fast mode */
+        I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
+        I2C_CKCFG(i2c_periph) |= clkc;
+        /* enable I2C fast mode plus */
+        I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN;
+    }
+}
+
+/*!
+    \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: address format is 7bits
+      \arg        I2C_ADDFORMAT_10BITS: address format is 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      select SMBus type
+    \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)
+{
+    uint32_t ctl = 0U;
+
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_ACKEN);
+    ctl |= ack;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \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: ACKEN bit decides whether or not to send ACK or not for the current byte
+      \arg        I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte
+    \param[out] none
+    \retval     none
+*/
+void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
+{
+    uint32_t ctl = 0U;
+    /* configure I2C POAP position */
+    ctl = I2C_CTL0(i2c_periph);
+    ctl &= ~(I2C_CTL0_POAP);
+    ctl |= pos;
+    I2C_CTL0(i2c_periph) = ctl;
+}
+
+/*!
+    \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]  dualaddr: the second address in dual-address mode
+    \param[out] none
+    \retval     none
+*/
+void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr)
+{
+    /* configure address */
+    dualaddr = dualaddr & I2C_ADDRESS2_MASK;
+    I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | dualaddr);
+}
+
+/*!
+    \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      configure 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: enable DMA mode
+      \arg        I2C_DMA_OFF: disable DMA mode
+    \param[out] none
+    \retval     none
+*/
+void i2c_dma_config(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: enable SCL stretching
+      \arg        I2C_SCLSTRETCH_DISABLE: disable SCL stretching
+    \param[out] none
+    \retval     none
+*/
+void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
+{
+    /* configure I2C SCL strerching */
+    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      configure software reset of 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      configure I2C PEC calculation
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  pecpara:
+                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_config(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      configure 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_config(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      configure I2C 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_alert_config(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      configure I2C ARP protocol in SMBus
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  smbuspara:
+                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_config(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      get I2C flag status
+    \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 sent out in master mode 
+      \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 status
+    \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 occurs indication a unexpected start or stop condition on I2C bus
+      \arg       I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
+    \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
+      \arg        I2C_INT_EV: event interrupt
+      \arg        I2C_INT_BUF: buffer interrupt
+    \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      get I2C interrupt flag status
+    \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 status 
+    \param[in]  i2c_periph: I2Cx(x=0,1)
+    \param[in]  intflag: 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));
+    }
+}

+ 176 - 0
app/LIB/Source/gd32f30x_misc.c

@@ -0,0 +1,176 @@
+/*!
+    \file    gd32f30x_misc.c
+    \brief   MISC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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 */
+    if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE0_SUB4){
+        temp_pre=0U;
+        temp_sub=0x4U;
+    }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE1_SUB3){
+        temp_pre=1U;
+        temp_sub=0x3U;
+    }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE2_SUB2){
+        temp_pre=2U;
+        temp_sub=0x2U;
+    }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE3_SUB1){
+        temp_pre=3U;
+        temp_sub=0x1U;
+    }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE4_SUB0){
+        temp_pre=4U;
+        temp_sub=0x0U;
+    }else{
+        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
+        temp_pre=2U;
+        temp_sub=0x2U;
+    }
+    /* 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 >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F);
+}
+
+/*!
+    \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;
+    }
+}

+ 400 - 0
app/LIB/Source/gd32f30x_pmu.c

@@ -0,0 +1,400 @@
+/*!
+    \file    gd32f30x_pmu.c
+    \brief   PMU driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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:
+      \arg        PMU_LVDT_0: voltage threshold is 2.1V
+      \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.6V
+      \arg        PMU_LVDT_4: voltage threshold is 2.7V
+      \arg        PMU_LVDT_5: voltage threshold is 2.9V
+      \arg        PMU_LVDT_6: voltage threshold is 3.0V
+      \arg        PMU_LVDT_7: voltage threshold is 3.1V
+    \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      select LDO output voltage
+                this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL
+    \param[in]  ldo_output:
+      \arg        PMU_LDOVS_LOW: LDO output voltage low mode
+      \arg        PMU_LDOVS_MID: LDO output voltage mid mode
+      \arg        PMU_LDOVS_HIGH: LDO output voltage high mode
+    \param[out] none
+    \retval     none
+*/
+void pmu_ldo_output_select(uint32_t ldo_output)
+{
+    PMU_CTL &= ~PMU_CTL_LDOVS;
+    PMU_CTL |= ldo_output;
+}
+
+/*!
+    \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      switch high-driver mode
+                this bit set by software only when IRC16M or HXTAL used as system clock
+    \param[in]  highdr_switch:
+      \arg        PMU_HIGHDR_SWITCH_NONE: disable high-driver mode switch
+      \arg        PMU_HIGHDR_SWITCH_EN: enable high-driver mode switch
+    \param[out] none
+    \retval     none
+*/
+void pmu_highdriver_switch_select(uint32_t highdr_switch)
+{
+    /* wait for HDRF flag set */
+    while(SET != pmu_flag_get(PMU_FLAG_HDRF)) {
+    }
+    PMU_CTL &= ~PMU_CTL_HDS;
+    PMU_CTL |= highdr_switch;
+}
+
+/*!
+    \brief      enable high-driver mode
+                this bit set by software only when IRC16M or HXTAL used as system clock
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_highdriver_mode_enable(void)
+{
+    PMU_CTL |= PMU_CTL_HDEN;
+}
+
+/*!
+    \brief      disable high-driver mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_highdriver_mode_disable(void)
+{
+    PMU_CTL &= ~PMU_CTL_HDEN;
+}
+
+/*!
+    \brief      enable low-driver mode in deep-sleep mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_lowdriver_mode_enable(void)
+{
+    PMU_CTL |= PMU_CTL_LDEN;
+}
+
+/*!
+    \brief      disable low-driver mode in deep-sleep mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_lowdriver_mode_disable(void)
+{
+    PMU_CTL &= ~PMU_CTL_LDEN;
+}
+
+/*!
+    \brief      driver mode when use low power LDO
+    \param[in]  mode:
+      \arg        PMU_NORMALDR_LOWPWR:  normal driver when use low power LDO
+      \arg        PMU_LOWDR_LOWPWR:  low-driver mode enabled when LDEN is 11 and use low power LDO
+    \param[out] none
+    \retval     none
+*/
+void pmu_lowpower_driver_config(uint32_t mode)
+{
+    PMU_CTL &= ~PMU_CTL_LDLP;
+    PMU_CTL |= mode;
+}
+
+/*!
+    \brief      driver mode when use normal power LDO
+    \param[in]  mode:
+      \arg        PMU_NORMALDR_NORMALPWR:  normal driver when use normal power LDO
+      \arg        PMU_LOWDR_NORMALPWR:  low-driver mode enabled when LDEN is 11 and use normal power LDO
+    \param[out] none
+    \retval     none
+*/
+void pmu_normalpower_driver_config(uint32_t mode)
+{
+    PMU_CTL &= ~PMU_CTL_LDNP;
+    PMU_CTL |= mode;
+}
+
+/*!
+    \brief      PMU work in sleep mode
+    \param[in]  sleepmodecmd:
+      \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-M4 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 in deepsleep mode
+    \param[in]  ldo:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_LDO_NORMAL: LDO work in normal power mode when pmu enter deepsleep mode
+      \arg        PMU_LDO_LOWPOWER: LDO work in low power mode when pmu enter deepsleep mode
+    \param[in]  lowdrive:
+                only one parameter can be selected which is shown as below:
+      \arg        PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep mode
+      \arg        PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep 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, uint32_t lowdrive, uint8_t deepsleepmodecmd)
+{
+    static uint32_t reg_snap[ 4 ];
+    /* clear stbmod and ldolp bits */
+    PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP | PMU_CTL_LDEN | PMU_CTL_LDNP | PMU_CTL_LDLP));
+
+    /* set ldolp bit according to pmu_ldo */
+    PMU_CTL |= ldo;
+
+    /* low drive mode config in deep-sleep mode */
+    if(PMU_LOWDRIVER_ENABLE == lowdrive) {
+        if(PMU_LDO_NORMAL == ldo) {
+            PMU_CTL |= (uint32_t)(PMU_CTL_LDEN | PMU_CTL_LDNP);
+        } else {
+            PMU_CTL |= (uint32_t)(PMU_CTL_LDEN | PMU_CTL_LDLP);
+        }
+    }
+
+    /* set sleepdeep bit of Cortex-M4 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)  = 0XFFFFF8FFU;
+    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-M4 system control register */
+    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
+}
+
+/*!
+    \brief      pmu work in standby mode
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_to_standbymode(void)
+{
+    /* set stbmod bit */
+    PMU_CTL |= PMU_CTL_STBMOD;
+
+    /* reset wakeup flag */
+    PMU_CTL |= PMU_CTL_WURST;
+
+    /* set sleepdeep bit of Cortex-M4 system control register */
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    REG32(0xE000E010U) &= 0x00010004U;
+    REG32(0xE000E180U)  = 0XFFFFFFF7U;
+    REG32(0xE000E184U)  = 0XFFFFFDFFU;
+    REG32(0xE000E188U)  = 0xFFFFFFFFU;
+
+    /* select WFI or WFE command to enter standby mode */
+    __WFI();
+}
+
+/*!
+    \brief      enable backup domain write
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_backup_write_enable(void)
+{
+    PMU_CTL |= PMU_CTL_BKPWEN;
+}
+
+/*!
+    \brief      disable backup domain write
+    \param[in]  none
+    \param[out] none
+    \retval     none
+*/
+void pmu_backup_write_disable(void)
+{
+    PMU_CTL &= ~PMU_CTL_BKPWEN;
+}
+
+/*!
+    \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      get flag state
+    \param[in]  flag:
+      \arg        PMU_FLAG_WAKEUP: wakeup flag
+      \arg        PMU_FLAG_STANDBY: standby flag
+      \arg        PMU_FLAG_LVD: lvd flag
+      \arg        PMU_FLAG_LDOVSRF: LDO voltage select ready flag
+      \arg        PMU_FLAG_HDRF: high-driver ready flag
+      \arg        PMU_FLAG_HDSRF: high-driver switch ready flag
+      \arg        PMU_FLAG_LDRF: low-driver mode ready 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:
+      \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)
+{
+    switch(flag) {
+    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;
+    }
+}

File diff suppressed because it is too large
+ 1332 - 0
app/LIB/Source/gd32f30x_rcu.c


+ 230 - 0
app/LIB/Source/gd32f30x_rtc.c

@@ -0,0 +1,230 @@
+/*!
+    \file    gd32f30x_rtc.c
+    \brief   RTC driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_rtc.h"
+
+/*!
+    \brief      enable RTC interrupt
+    \param[in]  interrupt: specify which interrupt to enbale
+          \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
+          \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;
+}
+
+/*!
+    \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      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      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 << 16);
+    return temp;
+}
+
+/*!
+    \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 >> 16;
+    /* set the RTC counter low bits */
+    RTC_CNTL = (cnt & RTC_LOW_VALUE);
+    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_VALUE) >> 16;
+    /* set the RTC prescaler low bits */
+    RTC_PSCL = (psc & RTC_LOW_VALUE);
+    rtc_configuration_mode_exit();
+}
+
+/*!
+    \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 >> 16;
+    /* set the alarm low bits */
+    RTC_ALRML = (alarm & RTC_LOW_VALUE);
+    rtc_configuration_mode_exit();
+}
+
+/*!
+    \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) << 16;
+    temp |= RTC_DIVL;
+    return temp;
+}
+
+/*!
+    \brief      get RTC flag status 
+    \param[in]  flag: specify which flag status to get
+          \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
+          \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;
+}
+

+ 809 - 0
app/LIB/Source/gd32f30x_sdio.c

@@ -0,0 +1,809 @@
+/*!
+    \file    gd32f30x_sdio.c
+    \brief   SDIO driver
+
+    \version 2017-02-10, V1.0.0, firmware for GD32F30x
+    \version 2018-10-10, V1.1.0, firmware for GD32F30x
+    \version 2018-12-25, V2.0.0, firmware for GD32F30x
+    \version 2020-09-30, V2.1.0, firmware for GD32F30x
+*/
+
+/*
+    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 "gd32f30x_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 512
+    \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_DIV8 | SDIO_CLKCTL_DIV);
+    /* if the clock division is greater or equal to 256, set the DIV[8] */
+    if(clock_division >= 256U){
+        clock_config |= SDIO_CLKCTL_DIV8;
+        clock_division -= 256U;
+    }
+    /* 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
+      \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)
+{
+    if(RESET != (SDIO_STAT & flag)){
+        return SET;
+    }
+    return RESET;
+}
+
+/*!
+    \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;
+}

+ 0 - 0
app/LIB/Source/gd32f30x_spi.c


Some files were not shown because too many files changed in this diff