haitao hace 11 meses
padre
commit
24c6dd89d8
Se han modificado 100 ficheros con 78439 adiciones y 1 borrados
  1. 1 1
      .gitignore
  2. 1236 0
      app/CORE/core_cm3.h
  3. 609 0
      app/CORE/core_cmFunc.h
  4. 585 0
      app/CORE/core_cmInstr.h
  5. 424 0
      app/CORE/startup_stm32f2xx.s
  6. 300 0
      app/HARDWARE/includes/cJSONbak.h
  7. 77 0
      app/HARDWARE/includes/delay.h
  8. 49 0
      app/HARDWARE/includes/hd_eth.h
  9. 54 0
      app/HARDWARE/includes/led.h
  10. 28 0
      app/HARDWARE/includes/log.h
  11. 74 0
      app/HARDWARE/includes/malloc.h
  12. 317 0
      app/HARDWARE/includes/nandflash.h
  13. 7 0
      app/HARDWARE/includes/spi.h
  14. 252 0
      app/HARDWARE/includes/sram.h
  15. 95 0
      app/HARDWARE/includes/usart.h
  16. 3156 0
      app/HARDWARE/sources/cJSONbak.c
  17. 268 0
      app/HARDWARE/sources/delay.c
  18. 361 0
      app/HARDWARE/sources/hd_eth.c
  19. 129 0
      app/HARDWARE/sources/led.c
  20. 61 0
      app/HARDWARE/sources/log.c
  21. 226 0
      app/HARDWARE/sources/malloc.c
  22. 2190 0
      app/HARDWARE/sources/nandflash.c
  23. 69 0
      app/HARDWARE/sources/spi.c
  24. 452 0
      app/HARDWARE/sources/sram.c
  25. 453 0
      app/HARDWARE/sources/usart.c
  26. 170 0
      app/Libraries/inc/misc.h
  27. 1884 0
      app/Libraries/inc/stm32f2x7_eth.h
  28. 98 0
      app/Libraries/inc/stm32f2x7_eth_conf.h
  29. 641 0
      app/Libraries/inc/stm32f2xx_adc.h
  30. 636 0
      app/Libraries/inc/stm32f2xx_can.h
  31. 75 0
      app/Libraries/inc/stm32f2xx_crc.h
  32. 336 0
      app/Libraries/inc/stm32f2xx_cryp.h
  33. 296 0
      app/Libraries/inc/stm32f2xx_dac.h
  34. 101 0
      app/Libraries/inc/stm32f2xx_dbgmcu.h
  35. 304 0
      app/Libraries/inc/stm32f2xx_dcmi.h
  36. 601 0
      app/Libraries/inc/stm32f2xx_dma.h
  37. 175 0
      app/Libraries/inc/stm32f2xx_exti.h
  38. 332 0
      app/Libraries/inc/stm32f2xx_flash.h
  39. 667 0
      app/Libraries/inc/stm32f2xx_fsmc.h
  40. 403 0
      app/Libraries/inc/stm32f2xx_gpio.h
  41. 242 0
      app/Libraries/inc/stm32f2xx_hash.h
  42. 690 0
      app/Libraries/inc/stm32f2xx_i2c.h
  43. 123 0
      app/Libraries/inc/stm32f2xx_iwdg.h
  44. 158 0
      app/Libraries/inc/stm32f2xx_pwr.h
  45. 507 0
      app/Libraries/inc/stm32f2xx_rcc.h
  46. 112 0
      app/Libraries/inc/stm32f2xx_rng.h
  47. 642 0
      app/Libraries/inc/stm32f2xx_rtc.h
  48. 528 0
      app/Libraries/inc/stm32f2xx_sdio.h
  49. 518 0
      app/Libraries/inc/stm32f2xx_spi.h
  50. 171 0
      app/Libraries/inc/stm32f2xx_syscfg.h
  51. 1142 0
      app/Libraries/inc/stm32f2xx_tim.h
  52. 421 0
      app/Libraries/inc/stm32f2xx_usart.h
  53. 103 0
      app/Libraries/inc/stm32f2xx_wwdg.h
  54. 241 0
      app/Libraries/src/misc.c
  55. 2709 0
      app/Libraries/src/stm32f2x7_eth.c
  56. 1740 0
      app/Libraries/src/stm32f2xx_adc.c
  57. 1696 0
      app/Libraries/src/stm32f2xx_can.c
  58. 125 0
      app/Libraries/src/stm32f2xx_crc.c
  59. 848 0
      app/Libraries/src/stm32f2xx_cryp.c
  60. 636 0
      app/Libraries/src/stm32f2xx_cryp_aes.c
  61. 289 0
      app/Libraries/src/stm32f2xx_cryp_des.c
  62. 306 0
      app/Libraries/src/stm32f2xx_cryp_tdes.c
  63. 699 0
      app/Libraries/src/stm32f2xx_dac.c
  64. 172 0
      app/Libraries/src/stm32f2xx_dbgmcu.c
  65. 532 0
      app/Libraries/src/stm32f2xx_dcmi.c
  66. 1281 0
      app/Libraries/src/stm32f2xx_dma.c
  67. 304 0
      app/Libraries/src/stm32f2xx_exti.c
  68. 1052 0
      app/Libraries/src/stm32f2xx_flash.c
  69. 979 0
      app/Libraries/src/stm32f2xx_fsmc.c
  70. 558 0
      app/Libraries/src/stm32f2xx_gpio.c
  71. 698 0
      app/Libraries/src/stm32f2xx_hash.c
  72. 312 0
      app/Libraries/src/stm32f2xx_hash_md5.c
  73. 315 0
      app/Libraries/src/stm32f2xx_hash_sha1.c
  74. 1402 0
      app/Libraries/src/stm32f2xx_i2c.c
  75. 261 0
      app/Libraries/src/stm32f2xx_iwdg.c
  76. 612 0
      app/Libraries/src/stm32f2xx_pwr.c
  77. 1811 0
      app/Libraries/src/stm32f2xx_rcc.c
  78. 397 0
      app/Libraries/src/stm32f2xx_rng.c
  79. 2236 0
      app/Libraries/src/stm32f2xx_rtc.c
  80. 1002 0
      app/Libraries/src/stm32f2xx_sdio.c
  81. 1175 0
      app/Libraries/src/stm32f2xx_spi.c
  82. 202 0
      app/Libraries/src/stm32f2xx_syscfg.c
  83. 3350 0
      app/Libraries/src/stm32f2xx_tim.c
  84. 1461 0
      app/Libraries/src/stm32f2xx_usart.c
  85. 301 0
      app/Libraries/src/stm32f2xx_wwdg.c
  86. 2113 0
      app/MDKProject/lora_gateway.uvoptx
  87. 1192 0
      app/MDKProject/lora_gateway.uvprojx
  88. BIN
      app/OBJ/lora_gateway.axf
  89. 18443 0
      app/OBJ/lora_gateway.hex
  90. 87 0
      app/SX1278/platform/platform.h
  91. 130 0
      app/SX1278/platform/sx12xxEiger.c
  92. 94 0
      app/SX1278/platform/sx12xxEiger.h
  93. 65 0
      app/SX1278/radio/radio.c
  94. 67 0
      app/SX1278/radio/radio.h
  95. 606 0
      app/SX1278/radio/sx1276-Fsk.c
  96. 1460 0
      app/SX1278/radio/sx1276-Fsk.h
  97. 521 0
      app/SX1278/radio/sx1276-FskMisc.c
  98. 241 0
      app/SX1278/radio/sx1276-FskMisc.h
  99. 169 0
      app/SX1278/radio/sx1276-Hal.c
  100. 0 0
      app/SX1278/radio/sx1276-Hal.h

+ 1 - 1
.gitignore

@@ -68,4 +68,4 @@ Examples/
 !*.hex
 
 .vscode/        
-
+JLinkLog.txt 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1236 - 0
app/CORE/core_cm3.h


+ 609 - 0
app/CORE/core_cmFunc.h

@@ -0,0 +1,609 @@
+/**************************************************************************//**
+ * @file     core_cmFunc.h
+ * @brief    CMSIS Cortex-M Core Function Access Header File
+ * @version  V2.10
+ * @date     26. July 2011
+ *
+ * @note
+ * Copyright (C) 2009-2011 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 ISPR Register
+
+    This function returns the content of the ISPR Register.
+
+    \return               ISPR 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 ( __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 ISPR Register
+
+    This function returns the content of the ISPR Register.
+
+    \return               ISPR 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 */

+ 585 - 0
app/CORE/core_cmInstr.h

@@ -0,0 +1,585 @@
+/**************************************************************************//**
+ * @file     core_cmInstr.h
+ * @brief    CMSIS Cortex-M Core Instruction Access Header File
+ * @version  V2.10
+ * @date     19. July 2011
+ *
+ * @note
+ * Copyright (C) 2009-2011 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
+ */
+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
+ */
+static __INLINE __ASM int32_t __REVSH(int32_t value)
+{
+  revsh r0, r0
+  bx lr
+}
+
+
+#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 ( __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);
+}
+
+
+#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 */

+ 424 - 0
app/CORE/startup_stm32f2xx.s

@@ -0,0 +1,424 @@
+;******************** (C) COPYRIGHT 2012 STMicroelectronics ********************
+;* File Name          : startup_stm32f2xx.s
+;* Author             : MCD Application Team
+;* Version            : V1.1.5
+;* Date               : 31-December-2021
+;* Description        : STM32F2xx devices vector table for MDK-ARM toolchain. 
+;*                      This module performs:
+;*                      - Set the initial SP
+;*                      - Set the initial PC == Reset_Handler
+;*                      - Set the vector table entries with the exceptions ISR address
+;*                      - Configure the system clock and the external SRAM mounted on 
+;*                        STM322xG-EVAL board to be used as data memory (optional, 
+;*                        to be enabled by user)
+;*                      - Branches to main in the C library (which eventually
+;*                        calls main()).
+;*                      After Reset the CortexM3 processor is in Thread mode,
+;*                      priority is Privileged, and the Stack is set to Main.
+;* <<< Use Configuration Wizard in Context Menu >>>   
+;*******************************************************************************
+;
+; Copyright (c) 2012 STMicroelectronics.
+; All rights reserved.
+;
+; This software is licensed under terms that can be found in the LICENSE file
+; in the root directory of this software component.
+; If no LICENSE file comes with this software, it is provided AS-IS.
+;
+;*******************************************************************************
+
+; Amount of memory (in bytes) allocated for Stack
+; Tailor this value to your application needs
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Stack_Size      EQU     0x0001000
+
+                AREA    STACK, NOINIT, READWRITE, ALIGN=3
+Stack_Mem       SPACE   Stack_Size
+__initial_sp    ;EQU     0x20000000 + Stack_Size
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size       EQU     0x00002000
+
+                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+Heap_Mem        SPACE   Heap_Size
+__heap_limit
+
+                PRESERVE8
+                THUMB
+
+
+; Vector Table Mapped to Address 0 at Reset
+                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
+                DCD     WWDG_IRQHandler                   ; Window WatchDog                                        
+                DCD     PVD_IRQHandler                    ; PVD through EXTI Line detection                        
+                DCD     TAMP_STAMP_IRQHandler             ; Tamper and TimeStamps through the EXTI line            
+                DCD     RTC_WKUP_IRQHandler               ; RTC Wakeup through the EXTI line                       
+                DCD     FLASH_IRQHandler                  ; FLASH                                           
+                DCD     RCC_IRQHandler                    ; RCC                                             
+                DCD     EXTI0_IRQHandler                  ; EXTI Line0                                             
+                DCD     EXTI1_IRQHandler                  ; EXTI Line1                                             
+                DCD     EXTI2_IRQHandler                  ; EXTI Line2                                             
+                DCD     EXTI3_IRQHandler                  ; EXTI Line3                                             
+                DCD     EXTI4_IRQHandler                  ; EXTI Line4                                             
+                DCD     DMA1_Stream0_IRQHandler           ; DMA1 Stream 0                                   
+                DCD     DMA1_Stream1_IRQHandler           ; DMA1 Stream 1                                   
+                DCD     DMA1_Stream2_IRQHandler           ; DMA1 Stream 2                                   
+                DCD     DMA1_Stream3_IRQHandler           ; DMA1 Stream 3                                   
+                DCD     DMA1_Stream4_IRQHandler           ; DMA1 Stream 4                                   
+                DCD     DMA1_Stream5_IRQHandler           ; DMA1 Stream 5                                   
+                DCD     DMA1_Stream6_IRQHandler           ; DMA1 Stream 6                                   
+                DCD     ADC_IRQHandler                    ; ADC1, ADC2 and ADC3s                            
+                DCD     CAN1_TX_IRQHandler                ; CAN1 TX                                                
+                DCD     CAN1_RX0_IRQHandler               ; CAN1 RX0                                               
+                DCD     CAN1_RX1_IRQHandler               ; CAN1 RX1                                               
+                DCD     CAN1_SCE_IRQHandler               ; CAN1 SCE                                               
+                DCD     EXTI9_5_IRQHandler                ; External Line[9:5]s                                    
+                DCD     TIM1_BRK_TIM9_IRQHandler          ; TIM1 Break and TIM9                   
+                DCD     TIM1_UP_TIM10_IRQHandler          ; TIM1 Update and TIM10                 
+                DCD     TIM1_TRG_COM_TIM11_IRQHandler     ; TIM1 Trigger and Commutation and TIM11
+                DCD     TIM1_CC_IRQHandler                ; TIM1 Capture Compare                                   
+                DCD     TIM2_IRQHandler                   ; TIM2                                            
+                DCD     TIM3_IRQHandler                   ; TIM3                                            
+                DCD     TIM4_IRQHandler                   ; TIM4                                            
+                DCD     I2C1_EV_IRQHandler                ; I2C1 Event                                             
+                DCD     I2C1_ER_IRQHandler                ; I2C1 Error                                             
+                DCD     I2C2_EV_IRQHandler                ; I2C2 Event                                             
+                DCD     I2C2_ER_IRQHandler                ; I2C2 Error                                               
+                DCD     SPI1_IRQHandler                   ; SPI1                                            
+                DCD     SPI2_IRQHandler                   ; SPI2                                            
+                DCD     USART1_IRQHandler                 ; USART1                                          
+                DCD     USART2_IRQHandler                 ; USART2                                          
+                DCD     USART3_IRQHandler                 ; USART3                                          
+                DCD     EXTI15_10_IRQHandler              ; External Line[15:10]s                                  
+                DCD     RTC_Alarm_IRQHandler              ; RTC Alarm (A and B) through EXTI Line                  
+                DCD     OTG_FS_WKUP_IRQHandler            ; USB OTG FS Wakeup through EXTI line                        
+                DCD     TIM8_BRK_TIM12_IRQHandler         ; TIM8 Break and TIM12                  
+                DCD     TIM8_UP_TIM13_IRQHandler          ; TIM8 Update and TIM13                 
+                DCD     TIM8_TRG_COM_TIM14_IRQHandler     ; TIM8 Trigger and Commutation and TIM14
+                DCD     TIM8_CC_IRQHandler                ; TIM8 Capture Compare                                   
+                DCD     DMA1_Stream7_IRQHandler           ; DMA1 Stream7                                           
+                DCD     FSMC_IRQHandler                   ; FSMC                                            
+                DCD     SDIO_IRQHandler                   ; SDIO                                            
+                DCD     TIM5_IRQHandler                   ; TIM5                                            
+                DCD     SPI3_IRQHandler                   ; SPI3                                            
+                DCD     UART4_IRQHandler                  ; UART4                                           
+                DCD     UART5_IRQHandler                  ; UART5                                           
+                DCD     TIM6_DAC_IRQHandler               ; TIM6 and DAC1&2 underrun errors                   
+                DCD     TIM7_IRQHandler                   ; TIM7                   
+                DCD     DMA2_Stream0_IRQHandler           ; DMA2 Stream 0                                   
+                DCD     DMA2_Stream1_IRQHandler           ; DMA2 Stream 1                                   
+                DCD     DMA2_Stream2_IRQHandler           ; DMA2 Stream 2                                   
+                DCD     DMA2_Stream3_IRQHandler           ; DMA2 Stream 3                                   
+                DCD     DMA2_Stream4_IRQHandler           ; DMA2 Stream 4                                   
+                DCD     ETH_IRQHandler                    ; Ethernet                                        
+                DCD     ETH_WKUP_IRQHandler               ; Ethernet Wakeup through EXTI line                      
+                DCD     CAN2_TX_IRQHandler                ; CAN2 TX                                                
+                DCD     CAN2_RX0_IRQHandler               ; CAN2 RX0                                               
+                DCD     CAN2_RX1_IRQHandler               ; CAN2 RX1                                               
+                DCD     CAN2_SCE_IRQHandler               ; CAN2 SCE                                               
+                DCD     OTG_FS_IRQHandler                 ; USB OTG FS                                      
+                DCD     DMA2_Stream5_IRQHandler           ; DMA2 Stream 5                                   
+                DCD     DMA2_Stream6_IRQHandler           ; DMA2 Stream 6                                   
+                DCD     DMA2_Stream7_IRQHandler           ; DMA2 Stream 7                                   
+                DCD     USART6_IRQHandler                 ; USART6                                           
+                DCD     I2C3_EV_IRQHandler                ; I2C3 event                                             
+                DCD     I2C3_ER_IRQHandler                ; I2C3 error                                             
+                DCD     OTG_HS_EP1_OUT_IRQHandler         ; USB OTG HS End Point 1 Out                      
+                DCD     OTG_HS_EP1_IN_IRQHandler          ; USB OTG HS End Point 1 In                       
+                DCD     OTG_HS_WKUP_IRQHandler            ; USB OTG HS Wakeup through EXTI                         
+                DCD     OTG_HS_IRQHandler                 ; USB OTG HS                                      
+                DCD     DCMI_IRQHandler                   ; DCMI                                            
+                DCD     CRYP_IRQHandler                   ; CRYP crypto                                     
+                DCD     HASH_RNG_IRQHandler               ; Hash and Rng 
+__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 (infinite loops which can be modified)
+
+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
+
+                EXPORT  WWDG_IRQHandler                   [WEAK]                                        
+                EXPORT  PVD_IRQHandler                    [WEAK]                      
+                EXPORT  TAMP_STAMP_IRQHandler             [WEAK]         
+                EXPORT  RTC_WKUP_IRQHandler               [WEAK]                     
+                EXPORT  FLASH_IRQHandler                  [WEAK]                                         
+                EXPORT  RCC_IRQHandler                    [WEAK]                                            
+                EXPORT  EXTI0_IRQHandler                  [WEAK]                                            
+                EXPORT  EXTI1_IRQHandler                  [WEAK]                                             
+                EXPORT  EXTI2_IRQHandler                  [WEAK]                                            
+                EXPORT  EXTI3_IRQHandler                  [WEAK]                                           
+                EXPORT  EXTI4_IRQHandler                  [WEAK]                                            
+                EXPORT  DMA1_Stream0_IRQHandler           [WEAK]                                
+                EXPORT  DMA1_Stream1_IRQHandler           [WEAK]                                   
+                EXPORT  DMA1_Stream2_IRQHandler           [WEAK]                                   
+                EXPORT  DMA1_Stream3_IRQHandler           [WEAK]                                   
+                EXPORT  DMA1_Stream4_IRQHandler           [WEAK]                                   
+                EXPORT  DMA1_Stream5_IRQHandler           [WEAK]                                   
+                EXPORT  DMA1_Stream6_IRQHandler           [WEAK]                                   
+                EXPORT  ADC_IRQHandler                    [WEAK]                         
+                EXPORT  CAN1_TX_IRQHandler                [WEAK]                                                
+                EXPORT  CAN1_RX0_IRQHandler               [WEAK]                                               
+                EXPORT  CAN1_RX1_IRQHandler               [WEAK]                                                
+                EXPORT  CAN1_SCE_IRQHandler               [WEAK]                                                
+                EXPORT  EXTI9_5_IRQHandler                [WEAK]                                    
+                EXPORT  TIM1_BRK_TIM9_IRQHandler          [WEAK]                  
+                EXPORT  TIM1_UP_TIM10_IRQHandler          [WEAK]                
+                EXPORT  TIM1_TRG_COM_TIM11_IRQHandler     [WEAK] 
+                EXPORT  TIM1_CC_IRQHandler                [WEAK]                                   
+                EXPORT  TIM2_IRQHandler                   [WEAK]                                            
+                EXPORT  TIM3_IRQHandler                   [WEAK]                                            
+                EXPORT  TIM4_IRQHandler                   [WEAK]                                            
+                EXPORT  I2C1_EV_IRQHandler                [WEAK]                                             
+                EXPORT  I2C1_ER_IRQHandler                [WEAK]                                             
+                EXPORT  I2C2_EV_IRQHandler                [WEAK]                                            
+                EXPORT  I2C2_ER_IRQHandler                [WEAK]                                               
+                EXPORT  SPI1_IRQHandler                   [WEAK]                                           
+                EXPORT  SPI2_IRQHandler                   [WEAK]                                            
+                EXPORT  USART1_IRQHandler                 [WEAK]                                          
+                EXPORT  USART2_IRQHandler                 [WEAK]                                          
+                EXPORT  USART3_IRQHandler                 [WEAK]                                         
+                EXPORT  EXTI15_10_IRQHandler              [WEAK]                                  
+                EXPORT  RTC_Alarm_IRQHandler              [WEAK]                  
+                EXPORT  OTG_FS_WKUP_IRQHandler            [WEAK]                        
+                EXPORT  TIM8_BRK_TIM12_IRQHandler         [WEAK]                 
+                EXPORT  TIM8_UP_TIM13_IRQHandler          [WEAK]                 
+                EXPORT  TIM8_TRG_COM_TIM14_IRQHandler     [WEAK] 
+                EXPORT  TIM8_CC_IRQHandler                [WEAK]                                   
+                EXPORT  DMA1_Stream7_IRQHandler           [WEAK]                                          
+                EXPORT  FSMC_IRQHandler                   [WEAK]                                             
+                EXPORT  SDIO_IRQHandler                   [WEAK]                                             
+                EXPORT  TIM5_IRQHandler                   [WEAK]                                             
+                EXPORT  SPI3_IRQHandler                   [WEAK]                                             
+                EXPORT  UART4_IRQHandler                  [WEAK]                                            
+                EXPORT  UART5_IRQHandler                  [WEAK]                                            
+                EXPORT  TIM6_DAC_IRQHandler               [WEAK]                   
+                EXPORT  TIM7_IRQHandler                   [WEAK]                    
+                EXPORT  DMA2_Stream0_IRQHandler           [WEAK]                                  
+                EXPORT  DMA2_Stream1_IRQHandler           [WEAK]                                   
+                EXPORT  DMA2_Stream2_IRQHandler           [WEAK]                                    
+                EXPORT  DMA2_Stream3_IRQHandler           [WEAK]                                    
+                EXPORT  DMA2_Stream4_IRQHandler           [WEAK]                                 
+                EXPORT  ETH_IRQHandler                    [WEAK]                                         
+                EXPORT  ETH_WKUP_IRQHandler               [WEAK]                     
+                EXPORT  CAN2_TX_IRQHandler                [WEAK]                                               
+                EXPORT  CAN2_RX0_IRQHandler               [WEAK]                                               
+                EXPORT  CAN2_RX1_IRQHandler               [WEAK]                                               
+                EXPORT  CAN2_SCE_IRQHandler               [WEAK]                                               
+                EXPORT  OTG_FS_IRQHandler                 [WEAK]                                       
+                EXPORT  DMA2_Stream5_IRQHandler           [WEAK]                                   
+                EXPORT  DMA2_Stream6_IRQHandler           [WEAK]                                   
+                EXPORT  DMA2_Stream7_IRQHandler           [WEAK]                                   
+                EXPORT  USART6_IRQHandler                 [WEAK]                                           
+                EXPORT  I2C3_EV_IRQHandler                [WEAK]                                              
+                EXPORT  I2C3_ER_IRQHandler                [WEAK]                                              
+                EXPORT  OTG_HS_EP1_OUT_IRQHandler         [WEAK]                      
+                EXPORT  OTG_HS_EP1_IN_IRQHandler          [WEAK]                      
+                EXPORT  OTG_HS_WKUP_IRQHandler            [WEAK]                        
+                EXPORT  OTG_HS_IRQHandler                 [WEAK]                                      
+                EXPORT  DCMI_IRQHandler                   [WEAK]                                             
+                EXPORT  CRYP_IRQHandler                   [WEAK]                                     
+                EXPORT  HASH_RNG_IRQHandler               [WEAK]
+
+WWDG_IRQHandler                                                       
+PVD_IRQHandler                                      
+TAMP_STAMP_IRQHandler                  
+RTC_WKUP_IRQHandler                                
+FLASH_IRQHandler                                                       
+RCC_IRQHandler                                                            
+EXTI0_IRQHandler                                                          
+EXTI1_IRQHandler                                                           
+EXTI2_IRQHandler                                                          
+EXTI3_IRQHandler                                                         
+EXTI4_IRQHandler                                                          
+DMA1_Stream0_IRQHandler                                       
+DMA1_Stream1_IRQHandler                                          
+DMA1_Stream2_IRQHandler                                          
+DMA1_Stream3_IRQHandler                                          
+DMA1_Stream4_IRQHandler                                          
+DMA1_Stream5_IRQHandler                                          
+DMA1_Stream6_IRQHandler                                          
+ADC_IRQHandler                                         
+CAN1_TX_IRQHandler                                                            
+CAN1_RX0_IRQHandler                                                          
+CAN1_RX1_IRQHandler                                                           
+CAN1_SCE_IRQHandler                                                           
+EXTI9_5_IRQHandler                                                
+TIM1_BRK_TIM9_IRQHandler                        
+TIM1_UP_TIM10_IRQHandler                      
+TIM1_TRG_COM_TIM11_IRQHandler  
+TIM1_CC_IRQHandler                                               
+TIM2_IRQHandler                                                           
+TIM3_IRQHandler                                                           
+TIM4_IRQHandler                                                           
+I2C1_EV_IRQHandler                                                         
+I2C1_ER_IRQHandler                                                         
+I2C2_EV_IRQHandler                                                        
+I2C2_ER_IRQHandler                                                           
+SPI1_IRQHandler                                                          
+SPI2_IRQHandler                                                           
+USART1_IRQHandler                                                       
+USART2_IRQHandler                                                       
+USART3_IRQHandler                                                      
+EXTI15_10_IRQHandler                                            
+RTC_Alarm_IRQHandler                            
+OTG_FS_WKUP_IRQHandler                                
+TIM8_BRK_TIM12_IRQHandler                      
+TIM8_UP_TIM13_IRQHandler                       
+TIM8_TRG_COM_TIM14_IRQHandler  
+TIM8_CC_IRQHandler                                               
+DMA1_Stream7_IRQHandler                                                 
+FSMC_IRQHandler                                                            
+SDIO_IRQHandler                                                            
+TIM5_IRQHandler                                                            
+SPI3_IRQHandler                                                            
+UART4_IRQHandler                                                          
+UART5_IRQHandler                                                          
+TIM6_DAC_IRQHandler                            
+TIM7_IRQHandler                              
+DMA2_Stream0_IRQHandler                                         
+DMA2_Stream1_IRQHandler                                          
+DMA2_Stream2_IRQHandler                                           
+DMA2_Stream3_IRQHandler                                           
+DMA2_Stream4_IRQHandler                                        
+ETH_IRQHandler                                                         
+ETH_WKUP_IRQHandler                                
+CAN2_TX_IRQHandler                                                           
+CAN2_RX0_IRQHandler                                                          
+CAN2_RX1_IRQHandler                                                          
+CAN2_SCE_IRQHandler                                                          
+OTG_FS_IRQHandler                                                    
+DMA2_Stream5_IRQHandler                                          
+DMA2_Stream6_IRQHandler                                          
+DMA2_Stream7_IRQHandler                                          
+USART6_IRQHandler                                                        
+I2C3_EV_IRQHandler                                                          
+I2C3_ER_IRQHandler                                                          
+OTG_HS_EP1_OUT_IRQHandler                           
+OTG_HS_EP1_IN_IRQHandler                            
+OTG_HS_WKUP_IRQHandler                                
+OTG_HS_IRQHandler                                                   
+DCMI_IRQHandler                                                            
+CRYP_IRQHandler                                                    
+HASH_RNG_IRQHandler                                               
+
+                B       .
+
+                ENDP
+
+                ALIGN
+
+;*******************************************************************************
+; User Stack and Heap initialization
+;*******************************************************************************
+                 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
+
+                 LDR     R0, =  Heap_Mem
+                 LDR     R1, =(Stack_Mem + Stack_Size)
+                 LDR     R2, = (Heap_Mem +  Heap_Size)
+                 LDR     R3, = Stack_Mem
+                 BX      LR
+
+                 ALIGN
+
+                 ENDIF
+
+                 END
+
+

+ 300 - 0
app/HARDWARE/includes/cJSONbak.h

@@ -0,0 +1,300 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type)   type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 15
+
+#include <stddef.h>
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False  (1 << 0)
+#define cJSON_True   (1 << 1)
+#define cJSON_NULL   (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array  (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw    (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+    struct cJSON *next;
+    struct cJSON *prev;
+    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+    struct cJSON *child;
+
+    /* The type of the item, as above. */
+    int type;
+
+    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
+    char *valuestring;
+    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+    int valueint;
+    /* The item's number, if type==cJSON_Number */
+    double valuedouble;
+
+    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+    char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+      void *(CJSON_CDECL *malloc_fn)(size_t sz);
+      void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check item type and return its value */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/array that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items.
+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detach items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
+ * The input pointer json cannot point to a read-only address area, such as a string constant, 
+ * but should point to a readable and writable address area. */
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
+
+/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
+#define cJSON_SetBoolValue(object, boolValue) ( \
+    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
+    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
+    cJSON_Invalid\
+)
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 77 - 0
app/HARDWARE/includes/delay.h

@@ -0,0 +1,77 @@
+#ifndef __DELAY_H
+#define __DELAY_H
+#include "stm32f2xx.h"
+
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32开发板
+//使用SysTick的普通计数模式对延迟进行管理(适合STM32F10x系列)
+//包括delay_us,delay_ms
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2010/1/1
+//版本:V1.8
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
+//All rights reserved
+//********************************************************************************
+//V1.2修改说明
+//修正了中断中调用出现死循环的错误
+//防止延时不准确,采用do while结构!
+//V1.3修改说明
+//增加了对UCOSII延时的支持.
+//如果使用ucosII,delay_init会自动设置SYSTICK的值,使之与ucos的TICKS_PER_SEC对应.
+//delay_ms和delay_us也进行了针对ucos的改造.
+//delay_us可以在ucos下使用,而且准确度很高,更重要的是没有占用额外的定时器.
+//delay_ms在ucos下,可以当成OSTimeDly来用,在未启动ucos时,它采用delay_us实现,从而准确延时
+//可以用来初始化外设,在启动了ucos之后delay_ms根据延时的长短,选择OSTimeDly实现或者delay_us实现.
+//V1.4修改说明 20110929
+//修改了使用ucos,但是ucos未启动的时候,delay_ms中中断无法响应的bug.
+//V1.5修改说明 20120902
+//在delay_us加入ucos上锁,防止由于ucos打断delay_us的执行,可能导致的延时不准。
+//V1.6修改说明 20150109
+//在delay_ms加入OSLockNesting判断。
+//V1.7修改说明 20150319
+//修改OS支持方式,以支持任意OS(不限于UCOSII和UCOSIII,理论上任意OS都可以支持)
+//添加:delay_osrunning/delay_ostickspersec/delay_osintnesting三个宏定义
+//添加:delay_osschedlock/delay_osschedunlock/delay_ostimedly三个函数
+//V1.8修改说明 20150519
+//修正UCOSIII支持时的2个bug:
+//delay_tickspersec改为:delay_ostickspersec
+//delay_intnesting改为:delay_osintnesting
+////////////////////////////////////////////////////////////////////////////////// 
+	 
+void delay_init(void);
+void delay_ms(u16 nms);
+void delay_us(u32 nus);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 49 - 0
app/HARDWARE/includes/hd_eth.h

@@ -0,0 +1,49 @@
+#ifndef HD_ETH_H
+#define HD_ETH_H
+
+#include "stdint.h"
+
+#define DP83848_PHY_ADDRESS   0x1
+
+#define ETH_INIT_FLAG           0x01 /* Ethernet Init Flag */
+#define ETH_LINK_FLAG           0x10 /* Ethernet Link Flag */
+
+//IP ADDR
+#define IP_ADDR0   192
+#define IP_ADDR1   168
+#define IP_ADDR2   0
+#define IP_ADDR3   48
+
+//MAC ADDR
+#define MAC_ADDR0   2
+#define MAC_ADDR1   8
+#define MAC_ADDR2   4
+#define MAC_ADDR3   2
+#define MAC_ADDR4   0
+#define MAC_ADDR5   0
+
+/*NETMASK*/
+#define NETMASK_ADDR0   255
+#define NETMASK_ADDR1   255
+#define NETMASK_ADDR2   255
+#define NETMASK_ADDR3   0
+
+/*Gateway Address*/
+#define GW_ADDR0   192
+#define GW_ADDR1   168
+#define GW_ADDR2   0
+#define GW_ADDR3   1
+
+
+extern uint8_t eth_recFlag;
+
+void LwIP_Pkt_Handle(void);
+
+void ETH_BSP_Config(void);
+uint8_t hd_ethGetPhyStatus(void);
+void lwIP_Init(void);
+#endif 
+
+
+
+

+ 54 - 0
app/HARDWARE/includes/led.h

@@ -0,0 +1,54 @@
+#ifndef __LED_H
+#define	__LED_H
+#include "stm32f2xx.h"
+//引脚定义
+/*******************************************************/
+
+#define LED_PIN                  GPIO_Pin_6                 
+#define LED_GPIO_PORT            GPIOF                      
+#define LED_GPIO_CLK             RCC_AHB1Periph_GPIOF
+
+#define NET_STATUS_LED_PIN                  GPIO_Pin_8                
+#define NET_STATUS_LED_GPIO_PORT            GPIOF                      
+#define NET_STATUS_LED_GPIO_CLK             RCC_AHB1Periph_GPIOF
+
+#define STATUS_LED_PIN                  GPIO_Pin_7                 
+#define STATUS_LED_GPIO_PORT            GPIOF                      
+#define STATUS_LED_GPIO_CLK             RCC_AHB1Periph_GPIOF
+
+/************************************************************/
+
+
+/** 控制LED灯亮灭的宏,
+	* LED低电平亮,设置ON=0,OFF=1
+	* 若LED高电平亮,把宏设置成ON=1 ,OFF=0 即可
+	*/
+#define ON  1
+#define OFF 0
+
+/* 带参宏,可以像内联函数一样使用 */
+#define LED(a)	if (a)	\
+					GPIO_SetBits(LED_GPIO_PORT,LED_PIN);\
+					else		\
+					GPIO_ResetBits(LED_GPIO_PORT,LED_PIN)
+#define NET_STATUS_LED(a)	if (a)	\
+					GPIO_SetBits(NET_STATUS_LED_GPIO_PORT,NET_STATUS_LED_PIN);\
+					else		\
+					GPIO_ResetBits(NET_STATUS_LED_GPIO_PORT,NET_STATUS_LED_PIN)
+					
+#define STATUS_LED(a)	if (a)	\
+					GPIO_SetBits(STATUS_LED_GPIO_PORT,STATUS_LED_PIN);\
+					else		\
+					GPIO_ResetBits(STATUS_LED_GPIO_PORT,STATUS_LED_PIN)
+
+
+void LED_GPIO_Config(void);
+void NET_STATUS_LED_Config(void);
+void STATUS_LED_Config(void);
+					
+int hd_netledOpen(void);					
+int hd_netledClose(void);					
+void hd_netledSetOpenTime(int tms);
+					
+#endif
+

+ 28 - 0
app/HARDWARE/includes/log.h

@@ -0,0 +1,28 @@
+/*
+ * log.h
+ *
+ *  Created on: Nov 7, 2022
+ *      Author: tangm
+ */
+
+#ifndef INC_LOG_H_
+#define INC_LOG_H_
+
+#include <stdarg.h>
+
+#define LOG_LEN_MAX 256
+
+typedef enum LOG_LEVEL_U
+{
+	LOG_NONE = 0,
+	LOG_INFO,
+	LOG_DEBUG,
+	LOG_WARN,
+	LOG_ERROR,
+	LOG_MAX,
+}logLevel_t;
+
+void LogPrint(logLevel_t logLevel, const char *func, const int line, char * fmt, ...);
+
+#define LOG_PRINT(logLevel, fmt, ...) LogPrint(logLevel, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
+#endif /* INC_LOG_H_ */

+ 74 - 0
app/HARDWARE/includes/malloc.h

@@ -0,0 +1,74 @@
+#ifndef __MALLOC_H
+#define __MALLOC_H
+
+
+
+#include "stm32f2xx.h"
+
+ 
+ 
+#ifndef NULL
+#define NULL 0
+#endif
+
+//定义两个内存池
+#define SRAMIN	 0		//内部内存池
+#define SRAMEX   1		//外部内存池 
+
+#define SRAMBANK 	2	  //定义支持的SRAM块数.	
+
+
+//mem1内存参数设定.mem1完全处于内部SRAM里面.
+#define MEM1_BLOCK_SIZE			32  	  						              //内存块大小为32字节
+#define MEM1_MAX_SIZE			  2*1024  						              //最大管理内存 40K
+#define MEM1_ALLOC_TABLE_SIZE	MEM1_MAX_SIZE/MEM1_BLOCK_SIZE 	//内存表大小
+
+
+//mem2内存参数设定.mem2的内存池处于外部SRAM里面
+#define MEM2_BLOCK_SIZE			32  	  						              //内存块大小为32字节
+#define MEM2_MAX_SIZE			  512 *1024  					              //最大管理内存512K
+#define MEM2_ALLOC_TABLE_SIZE	MEM2_MAX_SIZE/MEM2_BLOCK_SIZE 	//内存表大小 
+		 
+ 
+ 
+//内存管理控制器
+struct _m_mallco_dev
+{
+	void    ( * init ) ( uint8_t );				 //初始化
+	uint8_t ( * perused ) ( uint8_t );		 //内存使用率
+	uint8_t  * membase [ SRAMBANK ];		   //内存池 管理SRAMBANK个区域的内存
+	uint16_t * memmap [ SRAMBANK ]; 		   //内存管理状态表
+	uint8_t    memrdy [ SRAMBANK ]; 			 //内存管理是否就绪
+};
+extern struct _m_mallco_dev mallco_dev;	 //在mallco.c里面定义
+
+
+void mymemset(void *s,uint8_t c,uint32_t count);	    //设置内存
+void mymemcpy(void *des,void *src,uint32_t n);        //复制内存     
+void my_mem_init(uint8_t memx);				                //内存管理初始化函数(外/内部调用)
+uint32_t my_mem_malloc(uint8_t memx,uint32_t size);	  //内存分配(内部调用)
+uint8_t my_mem_free(uint8_t memx,uint32_t offset);		//内存释放(内部调用)
+uint8_t my_mem_perused(uint8_t memx);				          //获得内存使用率(外/内部调用) 
+
+
+//用户调用函数
+void myfree(uint8_t memx,void *ptr);  			           //内存释放(外部调用)
+void *mymalloc(uint8_t memx,uint32_t size);			       //内存分配(外部调用)
+void *myrealloc(uint8_t memx,void *ptr,uint32_t size); //重新分配内存(外部调用)
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 317 - 0
app/HARDWARE/includes/nandflash.h

@@ -0,0 +1,317 @@
+/*
+*********************************************************************************************************
+*
+*	模块名称 : NAND Flash 驱动模块
+*	文件名称 : bsp_nand.h
+*	版    本 : V1.1
+*	说    明 : 头文件
+*
+*	Copyright (C), 2014-2015, 安富莱电子 www.armfly.com
+*
+*********************************************************************************************************
+*/
+
+#ifndef __BSP_NAND_H
+#define __BSP_NAND_H
+#include "stm32f2xx.h"
+typedef struct
+{
+  uint8_t Maker_ID;
+  uint8_t Device_ID;
+  uint8_t Third_ID;
+  uint8_t Fourth_ID;
+}NAND_IDTypeDef;
+
+typedef struct
+{
+  uint16_t Zone;
+  uint16_t Block;
+  uint16_t Page;
+} NAND_ADDRESS_T;
+
+#define NAND_TYPE	S34ML02G100TF
+
+/*
+	定义有效的 NAND ID
+	HY27UF081G2A  	= 0xAD 0xF1 0x80 0x1D
+	K9F1G08U0A		= 0xEC 0xF1 0x80 0x15
+	K9F1G08U0B		= 0xEC 0xF1 0x00 0x95
+
+	H27U4G8F2DTR    = 0xAD DC 90 95
+*/
+
+/* NAND Flash 型号 */
+#define HY27UF081G2A	0xADF1801D
+#define K9F1G08U0A		0xECF18015
+#define K9F1G08U0B		0xECF10095
+#define H27U1G8F2BTR	0xADF1001D		/* STM32-V4 缺省 */
+
+#define H27U4G8F2DTR	0xADDC9095
+#define S34ML02G100TF 0x01DA9095
+
+#define NAND_UNKNOW		0xFFFFFFFF
+
+
+/* Exported constants --------------------------------------------------------*/
+/* NAND Area definition  for STM3210E-EVAL Board RevD */
+#define CMD_AREA                   (uint32_t)(1<<16)  /* A16 = CLE  high */
+#define ADDR_AREA                  (uint32_t)(1<<17)  /* A17 = ALE high */
+#define DATA_AREA                  ((uint32_t)0x00000000)
+
+/* FSMC NAND memory command */
+#define	NAND_CMD_AREA_A            ((uint8_t)0x00)
+#define	NAND_CMD_AREA_B            ((uint8_t)0x01)
+#define NAND_CMD_AREA_C            ((uint8_t)0x50)
+#define NAND_CMD_AREA_TRUE1        ((uint8_t)0x30)
+
+#define NAND_CMD_WRITE0            ((uint8_t)0x80)
+#define NAND_CMD_WRITE_TRUE1       ((uint8_t)0x10)
+
+#define NAND_CMD_ERASE0            ((uint8_t)0x60)
+#define NAND_CMD_ERASE1            ((uint8_t)0xD0)
+
+#define NAND_CMD_READID            ((uint8_t)0x90)
+
+#define NAND_CMD_LOCK_STATUS       ((uint8_t)0x7A)
+#define NAND_CMD_RESET             ((uint8_t)0xFF)
+
+/* NAND memory status */
+#define NAND_BUSY                  ((uint8_t)0x00)
+#define NAND_ERROR                 ((uint8_t)0x01)
+#define NAND_READY                 ((uint8_t)0x40)
+#define NAND_TIMEOUT_ERROR         ((uint8_t)0x80)
+
+
+#if NAND_TYPE==S34ML02G100TF
+	#define NAND_PAGE_SIZE             ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */
+	#define NAND_BLOCK_SIZE            ((uint16_t)0x0040) /* 64 pages per block */
+	#define NAND_ZONE_SIZE             ((uint16_t)0x0400) /* 1024 Block per zone */
+	#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0040) /* last 64 bytes as spare area */
+	#define NAND_MAX_ZONE              ((uint16_t)0x0002) /* 2 zones of 1024 block */
+	#define NAND_ADDR_5					1			/* 0表示只用发送4个字节的地址,1表示5个 */
+	
+		/* 命令代码定义 */
+	#define NAND_CMD_COPYBACK_A			((uint8_t)0x00)		/* PAGE COPY-BACK 命令序列 */
+	#define NAND_CMD_COPYBACK_B			((uint8_t)0x35)
+	#define NAND_CMD_COPYBACK_C			((uint8_t)0x85)
+	#define NAND_CMD_COPYBACK_D			((uint8_t)0x10)
+
+	#define NAND_CMD_STATUS				((uint8_t)0x70)		/* 读NAND Flash的状态字 */
+
+	#define MAX_PHY_BLOCKS_PER_ZONE  1024	/* 每个区最大物理块号 */
+	#define MAX_LOG_BLOCKS_PER_ZONE  1000	/* 每个区最大逻辑块号 */
+
+	#define NAND_BLOCK_COUNT			1024 /* 块个数 */
+	#define NAND_PAGE_TOTAL_SIZE		(NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE)	/* 页面总大小 */
+#elif NAND_TYPE == HY27UF081G2A
+	#define NAND_PAGE_SIZE             ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */
+	#define NAND_BLOCK_SIZE            ((uint16_t)0x0040) /* 64 pages per block */
+	#define NAND_ZONE_SIZE             ((uint16_t)0x0400) /* 1024 Block per zone */
+	#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0040) /* last 64 bytes as spare area */
+	#define NAND_MAX_ZONE              ((uint16_t)0x0001) /* 1 zones of 1024 block */
+	#define NAND_ADDR_5					0			/* 0表示只用发送4个字节的地址,1表示5个 */
+
+	/* 命令代码定义 */
+	#define NAND_CMD_COPYBACK_A			((uint8_t)0x00)		/* PAGE COPY-BACK 命令序列 */
+	#define NAND_CMD_COPYBACK_B			((uint8_t)0x35)
+	#define NAND_CMD_COPYBACK_C			((uint8_t)0x85)
+	#define NAND_CMD_COPYBACK_D			((uint8_t)0x10)
+
+	#define NAND_CMD_STATUS				((uint8_t)0x70)		/* 读NAND Flash的状态字 */
+
+	#define MAX_PHY_BLOCKS_PER_ZONE  1024	/* 每个区最大物理块号 */
+	#define MAX_LOG_BLOCKS_PER_ZONE  1000	/* 每个区最大逻辑块号 */
+
+	#define NAND_BLOCK_COUNT			1024 /* 块个数 */
+	#define NAND_PAGE_TOTAL_SIZE		(NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE)	/* 页面总大小 */
+
+#elif NAND_TYPE == H27U4G8F2DTR
+	#define NAND_PAGE_SIZE             ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */
+	#define NAND_BLOCK_SIZE            ((uint16_t)0x0040) /* 64 pages per block */
+	#define NAND_ZONE_SIZE             ((uint16_t)0x1000) /* 4096 Block per zone */
+	#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0040) /* last 64 bytes as spare area */
+	#define NAND_MAX_ZONE              ((uint16_t)0x0001) /* 1 zones of 4096 block */
+	#define NAND_ADDR_5					1			/* 1表示只发送4个字节的地址,1表示5个 */
+
+	/* 命令代码定义 */
+	#define NAND_CMD_COPYBACK_A			((uint8_t)0x00)		/* PAGE COPY-BACK 命令序列 */
+	#define NAND_CMD_COPYBACK_B			((uint8_t)0x35)
+	#define NAND_CMD_COPYBACK_C			((uint8_t)0x85)
+	#define NAND_CMD_COPYBACK_D			((uint8_t)0x10)
+
+	#define NAND_CMD_STATUS				((uint8_t)0x70)		/* 读NAND Flash的状态字 */
+
+	#define MAX_PHY_BLOCKS_PER_ZONE     4096	/* 每个区最大物理块号 */
+	#define MAX_LOG_BLOCKS_PER_ZONE     4000	/* 每个区最大逻辑块号 */
+
+	#define NAND_BLOCK_COUNT			4096 /* 块个数 */
+	#define NAND_PAGE_TOTAL_SIZE		(NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE)	/* 页面总大小 */
+
+#else
+	#define NAND_PAGE_SIZE             ((uint16_t)0x0200) /* 512 bytes per page w/o Spare Area */
+	#define NAND_BLOCK_SIZE            ((uint16_t)0x0020) /* 32x512 bytes pages per block */
+	#define NAND_ZONE_SIZE             ((uint16_t)0x0400) /* 1024 Block per zone */
+	#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0010) /* last 16 bytes as spare area */
+	#define NAND_MAX_ZONE              ((uint16_t)0x0004) /* 4 zones of 1024 block */
+#endif
+
+#define NAND_BAD_BLOCK_FLAG			0x00	/* 块内第1个page备用区的第1个字节写入非0xFF数据表示坏块 */
+#define NAND_USED_BLOCK_FLAG		0xF0	/* 块内第1个page备用区的第2个字节写入非0xFF数据表示已使用的块 */
+
+#define BI_OFFSET				0		/* 块内第1个page备用区的第1个字节是坏块标志 */
+#define USED_OFFSET				1		/* 块内第1个page备用区的第1个字节是已用标志 */
+#define LBN0_OFFSET				2		/* 块内第1个page备用区的第3个字节表示逻辑块号低8bit */
+#define LBN1_OFFSET				3		/* 块内第1个page备用区的第4个字节表示逻辑块号高8bit */
+#define VALID_SPARE_SIZE		4		/* 实际使用的备用区大小,用于函数内部声明数据缓冲区大小 */
+
+/* FSMC NAND memory address computation */
+#define ADDR_1st_CYCLE(ADDR)       (uint8_t)((ADDR)& 0xFF)               /* 1st addressing cycle */
+#define ADDR_2nd_CYCLE(ADDR)       (uint8_t)(((ADDR)& 0xFF00) >> 8)      /* 2nd addressing cycle */
+#define ADDR_3rd_CYCLE(ADDR)       (uint8_t)(((ADDR)& 0xFF0000) >> 16)   /* 3rd addressing cycle */
+#define ADDR_4th_CYCLE(ADDR)       (uint8_t)(((ADDR)& 0xFF000000) >> 24) /* 4th addressing cycle */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+#define NAND_OK   0
+#define NAND_FAIL 1
+
+#define FREE_BLOCK  (1 << 12 )
+#define BAD_BLOCK   (1 << 13 )
+#define VALID_BLOCK (1 << 14 )
+#define USED_BLOCK  (1 << 15 )
+
+/*
+		LUT[]的格式:
+		uint16_t usGoodBlockFirst;				 // 第1个好块
+		uint16_t usDataBlockCount;	             // 可用于数据存储的块个数, 从第2个好块开始
+		uint16_t usBakBlockStart;				 // 备份块起始块号
+		uint32_t usPhyBlockNo[ulDataBlockCount]; // 物理块号数组。低字节在前,高字节在后。
+*/
+#define DATA_BLOCK_PERCENT		98	/* 数据块占总有效块数的百分比 */
+#define LUT_FIRST_GOOD_BLOCK	0	/* LUT[] 第1个单元用于存储第1个有效块号 */
+#define LUT_DATA_BLOCK_COUNT	1	/* LUT[] 第2个单元用于存储第有效块号个数 */
+#define LUT_BAK_BLOCK_START		2	/* LUT[] 第3个单元用于备份区起始块号 */
+#define LUT_GOOD_BLOCK_START	3	/* LUT[] 第4个单元用于数据区起始块号 */
+
+
+/* Private Structures---------------------------------------------------------*/
+typedef struct __SPARE_AREA {
+	uint16_t LogicalIndex;
+	uint16_t DataStatus;
+	uint16_t BlockStatus;
+} SPARE_AREA;
+
+typedef enum {
+  WRITE_IDLE = 0,
+  POST_WRITE,
+  PRE_WRITE,
+  WRITE_CLEANUP,
+  WRITE_ONGOING
+}WRITE_STATE;
+
+typedef enum {
+  OLD_BLOCK = 0,
+  UNUSED_BLOCK
+}BLOCK_STATE;
+
+/* ONFI 结构 (for H27U4G8F2DTR)  page 26 */
+/* 必须添加__packed关键字表示结构体成员间紧密排列 */
+__packed typedef struct
+{
+	uint8_t Sign[4];		/* = "ONFI" */
+	uint16_t Revision; 		/* Bit1 = 1 表示支持 ONFI Ver 1.0 */
+	uint16_t Features;		/* */
+	uint16_t OptionalCommands;
+	uint8_t Rsv1[22];
+
+	/* Manufacturer information block */
+	uint8_t Manufacturer[12];	/* 制造商 */
+	uint8_t Model[20];	/* 型号 */
+	uint8_t JEDEC_ID;	/* AD */
+	uint16_t DateCode;
+	uint8_t Rsv2[13];
+
+	/* Memory organization block */
+	uint32_t PageDataSize;
+	uint16_t PageSpareSize;
+	uint32_t PartialPageDataSize;
+	uint16_t PartialPageSpareSize;
+	uint32_t BlockSize;
+	uint32_t LogicalUnitSize;
+	uint8_t LogicalUnitNumber;
+	uint8_t AddressCycles;
+	uint8_t CellBits;
+	uint16_t BadBlockMax;
+	uint16_t BlockEndurance;
+	uint8_t ValidBlocksBegin;	/* 最前面保证有效的块个数 */
+	uint16_t BlockEndurance2;	/* Block endurance for guaranteed valid blocks */
+	uint8_t  ProgramsPerPage;	/* Number of programs per page */
+	uint8_t PartialProgram;
+	uint8_t ECCcorrectBits;
+	uint8_t InterleavedAddrBits;	/* 交错的地址位 */
+	uint8_t InterleavedOperaton;
+	uint8_t Rsv3[13];
+
+	/* Electrical parameters block */
+	uint8_t PinCapactance;
+	uint16_t TimingMode;
+	uint16_t ProgramCacheTimingMode;
+	uint16_t PageProgTime;
+	uint16_t BlockEraseTime;
+	uint16_t PageReadTime;
+	uint16_t ChangeColumnSetupTime;
+	uint8_t Rsv4[23];
+
+	/* Vendor block */
+	uint16_t VendorRevision;
+	uint8_t VendorSpecific[88];
+	uint16_t IntegritaCRC;
+}PARAM_PAGE_T;
+
+/* Private macro --------------------------------------------------------------*/
+//#define WEAR_LEVELLING_SUPPORT		磨损平衡支持
+#define WEAR_DEPTH         10			/* 磨损深度 */
+#define PAGE_TO_WRITE      (Transfer_Length/512)
+
+#define BAD_BALOK_TEST_CYCLE	3		/* 判别坏块算法的重复擦写次数  */
+
+/* NAND 块统计 */
+typedef struct
+{
+	uint32_t ChipID;
+	char ChipName[16];
+	uint32_t Bad;
+	uint32_t Free;
+	uint32_t Used;
+}NAND_BLOCK_INFO_T;
+
+/* Private variables ----------------------------------------------------------*/
+/* Private function prototypes ------------------------------------------------*/
+/* exported functions ---------------------------------------------------------*/
+uint8_t NAND_Init(void);
+uint8_t NAND_Write(uint32_t _ulMemAddr, uint32_t *_pWriteBuf, uint16_t _usSize);
+uint8_t NAND_Read(uint32_t _ulMemAddr, uint32_t *_pReadBuf, uint16_t _usSize);
+uint8_t NAND_Format(void);
+void NAND_DispBadBlockInfo(void);
+uint8_t NAND_ScanBlock(uint32_t _ulPageNo);
+uint32_t NAND_FormatCapacity(void);
+uint32_t NAND_ReadID(void);
+
+void NAND_DispPhyPageData(uint32_t _uiPhyPageNo);
+void NAND_DispLogicPageData(uint32_t _uiLogicPageNo);
+
+uint8_t NAND_WriteMultiSectors(uint8_t *_pBuf, uint32_t _SectorNo, uint16_t _SectorSize, uint32_t _SectorCount);
+uint8_t NAND_ReadMultiSectors(uint8_t *_pBuf, uint32_t _SectorNo, uint16_t _SectorSize, uint32_t _SectorCount);
+
+void NAND_ReadONFI(uint8_t *_pBuf);
+void NAND_ReadParamPage(PARAM_PAGE_T *_pData);
+void NAND_DispParamPage(void);
+
+
+void NAND_ScanAllBadBlock(void);
+uint8_t NAND_GetBlockInfo(NAND_BLOCK_INFO_T *_pInfo);
+void NAND_MarkBadBlock(uint32_t _ulBlockNo);
+
+#endif /* __FSMC_NAND_H */
+
+/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/

+ 7 - 0
app/HARDWARE/includes/spi.h

@@ -0,0 +1,7 @@
+#ifndef __SPI_H
+#define __SPI_H
+#include "stm32f2xx_spi.h"
+void spi_config(void);
+uint8_t SPI2_ReadWriteByte(uint8_t txd);
+void SpiNSSEnable( uint8_t status );
+#endif

+ 252 - 0
app/HARDWARE/includes/sram.h

@@ -0,0 +1,252 @@
+#ifndef __SRAM_H
+#define __SRAM_H															    
+
+
+
+#include "stm32f2xx.h"
+#include <stdio.h>
+
+//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=10 
+//对IS61LV25616/IS62WV25616,地址线范围为A0~A17 
+//对IS61LV51216/IS62WV51216,地址线范围为A0~A18
+#define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))		
+
+#define IS62WV51216_SIZE 0x100000  //512*16/2bits = 0x100000  ,1M字节
+
+
+#define FSMC_GPIO_AF             GPIO_AF_FSMC
+
+/*A地址信号线*/    
+#define FSMC_A0_GPIO_PORT        GPIOF
+#define FSMC_A0_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A0_GPIO_PIN         GPIO_Pin_0
+#define FSMC_A0_GPIO_PinSource   GPIO_PinSource0
+
+#define FSMC_A1_GPIO_PORT        GPIOF
+#define FSMC_A1_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A1_GPIO_PIN         GPIO_Pin_1
+#define FSMC_A1_GPIO_PinSource   GPIO_PinSource1
+
+#define FSMC_A2_GPIO_PORT        GPIOF
+#define FSMC_A2_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A2_GPIO_PIN         GPIO_Pin_2
+#define FSMC_A2_GPIO_PinSource   GPIO_PinSource2
+
+#define FSMC_A3_GPIO_PORT        GPIOF
+#define FSMC_A3_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A3_GPIO_PIN         GPIO_Pin_3
+#define FSMC_A3_GPIO_PinSource   GPIO_PinSource3
+
+#define FSMC_A4_GPIO_PORT        GPIOF
+#define FSMC_A4_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A4_GPIO_PIN         GPIO_Pin_4
+#define FSMC_A4_GPIO_PinSource   GPIO_PinSource4
+
+#define FSMC_A5_GPIO_PORT        GPIOF
+#define FSMC_A5_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A5_GPIO_PIN         GPIO_Pin_5
+#define FSMC_A5_GPIO_PinSource   GPIO_PinSource5
+
+#define FSMC_A6_GPIO_PORT        GPIOF
+#define FSMC_A6_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A6_GPIO_PIN         GPIO_Pin_12
+#define FSMC_A6_GPIO_PinSource   GPIO_PinSource12
+
+#define FSMC_A7_GPIO_PORT        GPIOF
+#define FSMC_A7_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A7_GPIO_PIN         GPIO_Pin_13
+#define FSMC_A7_GPIO_PinSource   GPIO_PinSource13
+
+#define FSMC_A8_GPIO_PORT        GPIOF
+#define FSMC_A8_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A8_GPIO_PIN         GPIO_Pin_14
+#define FSMC_A8_GPIO_PinSource   GPIO_PinSource14
+
+#define FSMC_A9_GPIO_PORT        GPIOF
+#define FSMC_A9_GPIO_CLK         RCC_AHB1Periph_GPIOF
+#define FSMC_A9_GPIO_PIN         GPIO_Pin_15
+#define FSMC_A9_GPIO_PinSource   GPIO_PinSource15
+
+#define FSMC_A10_GPIO_PORT        GPIOG
+#define FSMC_A10_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A10_GPIO_PIN         GPIO_Pin_0
+#define FSMC_A10_GPIO_PinSource   GPIO_PinSource0
+
+#define FSMC_A11_GPIO_PORT        GPIOG
+#define FSMC_A11_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A11_GPIO_PIN         GPIO_Pin_1
+#define FSMC_A11_GPIO_PinSource   GPIO_PinSource1
+
+#define FSMC_A12_GPIO_PORT        GPIOG
+#define FSMC_A12_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A12_GPIO_PIN         GPIO_Pin_2
+#define FSMC_A12_GPIO_PinSource   GPIO_PinSource2
+
+#define FSMC_A13_GPIO_PORT        GPIOG
+#define FSMC_A13_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A13_GPIO_PIN         GPIO_Pin_3
+#define FSMC_A13_GPIO_PinSource   GPIO_PinSource3
+
+#define FSMC_A14_GPIO_PORT        GPIOG
+#define FSMC_A14_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A14_GPIO_PIN         GPIO_Pin_4
+#define FSMC_A14_GPIO_PinSource   GPIO_PinSource4
+
+#define FSMC_A15_GPIO_PORT        GPIOG
+#define FSMC_A15_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_A15_GPIO_PIN         GPIO_Pin_5
+#define FSMC_A15_GPIO_PinSource   GPIO_PinSource5
+
+#define FSMC_A16_GPIO_PORT        GPIOD
+#define FSMC_A16_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_A16_GPIO_PIN         GPIO_Pin_11
+#define FSMC_A16_GPIO_PinSource   GPIO_PinSource11
+
+#define FSMC_A17_GPIO_PORT        GPIOD
+#define FSMC_A17_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_A17_GPIO_PIN         GPIO_Pin_12
+#define FSMC_A17_GPIO_PinSource   GPIO_PinSource12
+
+#define FSMC_A18_GPIO_PORT        GPIOD
+#define FSMC_A18_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_A18_GPIO_PIN         GPIO_Pin_13
+#define FSMC_A18_GPIO_PinSource   GPIO_PinSource13
+
+/*D 数据信号线*/
+#define FSMC_D0_GPIO_PORT        GPIOD
+#define FSMC_D0_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D0_GPIO_PIN         GPIO_Pin_14
+#define FSMC_D0_GPIO_PinSource   GPIO_PinSource14
+
+#define FSMC_D1_GPIO_PORT        GPIOD
+#define FSMC_D1_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D1_GPIO_PIN         GPIO_Pin_15
+#define FSMC_D1_GPIO_PinSource   GPIO_PinSource15
+
+#define FSMC_D2_GPIO_PORT        GPIOD
+#define FSMC_D2_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D2_GPIO_PIN         GPIO_Pin_0
+#define FSMC_D2_GPIO_PinSource   GPIO_PinSource0
+
+#define FSMC_D3_GPIO_PORT        GPIOD
+#define FSMC_D3_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D3_GPIO_PIN         GPIO_Pin_1
+#define FSMC_D3_GPIO_PinSource   GPIO_PinSource1
+
+#define FSMC_D4_GPIO_PORT        GPIOE
+#define FSMC_D4_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D4_GPIO_PIN         GPIO_Pin_7
+#define FSMC_D4_GPIO_PinSource   GPIO_PinSource7
+
+#define FSMC_D5_GPIO_PORT        GPIOE
+#define FSMC_D5_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D5_GPIO_PIN         GPIO_Pin_8
+#define FSMC_D5_GPIO_PinSource   GPIO_PinSource8
+
+#define FSMC_D6_GPIO_PORT        GPIOE
+#define FSMC_D6_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D6_GPIO_PIN         GPIO_Pin_9
+#define FSMC_D6_GPIO_PinSource   GPIO_PinSource9
+
+#define FSMC_D7_GPIO_PORT        GPIOE
+#define FSMC_D7_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D7_GPIO_PIN         GPIO_Pin_10
+#define FSMC_D7_GPIO_PinSource   GPIO_PinSource10
+
+#define FSMC_D8_GPIO_PORT        GPIOE
+#define FSMC_D8_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D8_GPIO_PIN         GPIO_Pin_11
+#define FSMC_D8_GPIO_PinSource   GPIO_PinSource11
+
+#define FSMC_D9_GPIO_PORT        GPIOE
+#define FSMC_D9_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D9_GPIO_PIN         GPIO_Pin_12
+#define FSMC_D9_GPIO_PinSource   GPIO_PinSource12
+
+#define FSMC_D10_GPIO_PORT        GPIOE
+#define FSMC_D10_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D10_GPIO_PIN         GPIO_Pin_13
+#define FSMC_D10_GPIO_PinSource   GPIO_PinSource13
+
+#define FSMC_D11_GPIO_PORT        GPIOE
+#define FSMC_D11_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D11_GPIO_PIN         GPIO_Pin_14
+#define FSMC_D11_GPIO_PinSource   GPIO_PinSource14
+
+#define FSMC_D12_GPIO_PORT        GPIOE
+#define FSMC_D12_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_D12_GPIO_PIN         GPIO_Pin_15
+#define FSMC_D12_GPIO_PinSource   GPIO_PinSource15
+
+#define FSMC_D13_GPIO_PORT        GPIOD
+#define FSMC_D13_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D13_GPIO_PIN         GPIO_Pin_8
+#define FSMC_D13_GPIO_PinSource   GPIO_PinSource8
+
+#define FSMC_D14_GPIO_PORT        GPIOD
+#define FSMC_D14_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D14_GPIO_PIN         GPIO_Pin_9
+#define FSMC_D14_GPIO_PinSource   GPIO_PinSource9
+
+#define FSMC_D15_GPIO_PORT        GPIOD
+#define FSMC_D15_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_D15_GPIO_PIN         GPIO_Pin_10
+#define FSMC_D15_GPIO_PinSource   GPIO_PinSource10
+
+/*控制信号线*/  
+/*CS片选*/
+/*NE3 ,对应的基地址0x68000000*/
+#define FSMC_CS_GPIO_PORT        GPIOG
+#define FSMC_CS_GPIO_CLK         RCC_AHB1Periph_GPIOG
+#define FSMC_CS_GPIO_PIN         GPIO_Pin_10
+#define FSMC_CS_GPIO_PinSource   GPIO_PinSource10
+
+/*WE写使能*/
+#define FSMC_WE_GPIO_PORT        GPIOD
+#define FSMC_WE_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_WE_GPIO_PIN         GPIO_Pin_5
+#define FSMC_WE_GPIO_PinSource   GPIO_PinSource5
+
+/*OE读使能*/
+#define FSMC_OE_GPIO_PORT        GPIOD
+#define FSMC_OE_GPIO_CLK         RCC_AHB1Periph_GPIOD
+#define FSMC_OE_GPIO_PIN         GPIO_Pin_4
+#define FSMC_OE_GPIO_PinSource   GPIO_PinSource4
+
+
+/*UB数据掩码*/
+#define FSMC_UDQM_GPIO_PORT        GPIOE
+#define FSMC_UDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_UDQM_GPIO_PIN         GPIO_Pin_1
+#define FSMC_UDQM_GPIO_PinSource   GPIO_PinSource1
+
+/*LB数据掩码*/
+#define FSMC_LDQM_GPIO_PORT        GPIOE
+#define FSMC_LDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define FSMC_LDQM_GPIO_PIN         GPIO_Pin_0
+#define FSMC_LDQM_GPIO_PinSource   GPIO_PinSource0
+
+
+/*信息输出*/
+#define SRAM_DEBUG_ON         1
+
+#define SRAM_INFO(fmt,arg...)           printf("<<-SRAM-INFO->> "fmt"\n",##arg)
+#define SRAM_ERROR(fmt,arg...)          printf("<<-SRAM-ERROR->> "fmt"\n",##arg)
+#define SRAM_DEBUG(fmt,arg...)          do{\
+                                          if(SRAM_DEBUG_ON)\
+                                          printf("<<-SRAM-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
+                                          }while(0)
+
+
+
+
+											  
+void FSMC_SRAM_Init(void);
+void FSMC_SRAM_WriteBuffer(uint8_t* pBuffer,uint32_t WriteAddr,uint32_t NumHalfwordToWrite);
+void FSMC_SRAM_ReadBuffer(uint8_t* pBuffer,uint32_t ReadAddr,uint32_t NumHalfwordToRead);
+
+uint8_t SRAM_Test(void);
+void Disable_LCD_CS(void);//F407板 当不使用屏幕时 失能接LCD_CS的脚 防止影响
+
+#endif
+

+ 95 - 0
app/HARDWARE/includes/usart.h

@@ -0,0 +1,95 @@
+#ifndef __DEBUG_USART_H
+#define	__DEBUG_USART_H
+
+#include "stm32f2xx.h"
+#include <stdio.h>
+
+
+//繫祇貢왯多신땍屢
+/*******************************************************/
+#define DEBUG_USART                             USART6
+#define DEBUG_USART_CLK                         RCC_APB2Periph_USART6
+#define DEBUG_USART_BAUDRATE                    115200  //눔왯꺼景쪽
+
+#define DEBUG_USART_RX_GPIO_PORT                GPIOC
+#define DEBUG_USART_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOC
+#define DEBUG_USART_RX_PIN                      GPIO_Pin_7
+#define DEBUG_USART_RX_AF                       GPIO_AF_USART6
+#define DEBUG_USART_RX_SOURCE                   GPIO_PinSource7
+
+#define DEBUG_USART_TX_GPIO_PORT                GPIOC
+#define DEBUG_USART_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOC
+#define DEBUG_USART_TX_PIN                      GPIO_Pin_6
+#define DEBUG_USART_TX_AF                       GPIO_AF_USART6
+#define DEBUG_USART_TX_SOURCE                   GPIO_PinSource6
+
+#define DEBUG_USART_IRQHandler                  USART6_IRQHandler
+#define DEBUG_USART_IRQ                 				USART6_IRQn
+
+//繫祇貢왯DMA
+#define DEBUG_USART_DR_BASE               (USART6_BASE+0x04)		//DR셍닸포
+#define DEBUG_USART_DMA_CLK               RCC_AHB1Periph_DMA2	
+#define DEBUG_USART_DMA_CHANNEL           DMA_Channel_5
+#define DEBUG_USART_DMA_STREAM            DMA2_Stream1
+
+#define BUFF_SIZE                     5000				//dma왕쇌댕鬼
+
+/************************************************************/
+//232多신땍屢
+#define USART_232                             USART1
+#define USART_232_CLK                         RCC_APB2Periph_USART1
+#define USART_232_BAUDRATE                    115200  //눔왯꺼景쪽
+
+#define USART_232_RX_GPIO_PORT                GPIOA
+#define USART_232_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOA
+#define USART_232_RX_PIN                      GPIO_Pin_10
+#define USART_232_RX_AF                       GPIO_AF_USART1
+#define USART_232_RX_SOURCE                   GPIO_PinSource10
+
+#define USART_232_TX_GPIO_PORT                GPIOA
+#define USART_232_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOA
+#define USART_232_TX_PIN                      GPIO_Pin_9
+#define USART_232_TX_AF                       GPIO_AF_USART1
+#define USART_232_TX_SOURCE                   GPIO_PinSource9
+
+#define USART_232_IRQHandler                  USART1_IRQHandler
+#define USART_232_IRQ                 				USART1_IRQn
+//485多신땍屢
+#define USART_485                             USART3
+#define USART_485_CLK                         RCC_APB1Periph_USART3 
+#define USART_485_BAUDRATE                    9600  //눔왯꺼景쪽
+
+#define USART_485_RX_GPIO_PORT                GPIOC
+#define USART_485_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOC
+#define USART_485_RX_PIN                      GPIO_Pin_11
+#define USART_485_RX_AF                       GPIO_AF_USART3
+#define USART_485_RX_SOURCE                   GPIO_PinSource11
+
+#define USART_485_TX_GPIO_PORT                GPIOC
+#define USART_485_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOC
+#define USART_485_TX_PIN                      GPIO_Pin_10
+#define USART_485_TX_AF                       GPIO_AF_USART3
+#define USART_485_TX_SOURCE                   GPIO_PinSource10
+
+#define USART_485_IRQHandler                  USART3_IRQHandler
+#define USART_485_IRQ                 				USART3_IRQn
+//485왠齡多신
+#define USART_485_DE_GPIO_PORT 								GPIOC
+#define USART_485_DE_GPIO_CLK									RCC_AHB1Periph_GPIOC
+#define USART_485_DE_PIN											GPIO_Pin_12
+
+void Debug_USART_Config(void);
+void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
+void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
+
+void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch);
+void USART_DMA_Config(void);
+void DEBUG_USART_Config(void);
+void USART_232_config(void);
+void Usart_SendHex( USART_TypeDef * pUSARTx, uint8_t *str,uint16_t hexLength);
+void USART_485_config(void);
+
+extern uint8_t UART6_RX_BUF[BUFF_SIZE];
+extern uint8_t UART6_RX_STAT;
+extern uint32_t UART6_RX_NUM;
+#endif /* __USART1_H */

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3156 - 0
app/HARDWARE/sources/cJSONbak.c


+ 268 - 0
app/HARDWARE/sources/delay.c

@@ -0,0 +1,268 @@
+#include "delay.h"
+
+#define 	SYSTEM_SUPPORT_OS 1
+////////////////////////////////////////////////////////////////////////////////// 	 
+//如果需要使用OS,则包括下面的头文件即可.
+#if SYSTEM_SUPPORT_OS
+#include "includes.h"					//ucos 使用	  
+#endif
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32开发板
+//使用SysTick的普通计数模式对延迟进行管理(适合STM32F10x系列)
+//包括delay_us,delay_ms
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2010/1/1
+//版本:V1.8
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
+//All rights reserved
+//********************************************************************************
+//V1.2修改说明
+//修正了中断中调用出现死循环的错误
+//防止延时不准确,采用do while结构!
+//V1.3修改说明
+//增加了对UCOSII延时的支持.
+//如果使用ucosII,delay_init会自动设置SYSTICK的值,使之与ucos的TICKS_PER_SEC对应.
+//delay_ms和delay_us也进行了针对ucos的改造.
+//delay_us可以在ucos下使用,而且准确度很高,更重要的是没有占用额外的定时器.
+//delay_ms在ucos下,可以当成OSTimeDly来用,在未启动ucos时,它采用delay_us实现,从而准确延时
+//可以用来初始化外设,在启动了ucos之后delay_ms根据延时的长短,选择OSTimeDly实现或者delay_us实现.
+//V1.4修改说明 20110929
+//修改了使用ucos,但是ucos未启动的时候,delay_ms中中断无法响应的bug.
+//V1.5修改说明 20120902
+//在delay_us加入ucos上锁,防止由于ucos打断delay_us的执行,可能导致的延时不准。
+//V1.6修改说明 20150109
+//在delay_ms加入OSLockNesting判断。
+//V1.7修改说明 20150319
+//修改OS支持方式,以支持任意OS(不限于UCOSII和UCOSIII,理论上任意OS都可以支持)
+//添加:delay_osrunning/delay_ostickspersec/delay_osintnesting三个宏定义
+//添加:delay_osschedlock/delay_osschedunlock/delay_ostimedly三个函数
+//V1.8修改说明 20150519
+//修正UCOSIII支持时的2个bug:
+//delay_tickspersec改为:delay_ostickspersec
+//delay_intnesting改为:delay_osintnesting
+//////////////////////////////////////////////////////////////////////////////////  
+
+static u8  fac_us=0;							//us延时倍乘数			   
+static u16 fac_ms=0;							//ms延时倍乘数,在ucos下,代表每个节拍的ms数
+
+
+#if SYSTEM_SUPPORT_OS							//如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
+//当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
+//首先是3个宏定义:
+//    delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数
+//delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick
+// delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
+//然后是3个函数:
+//  delay_osschedlock:用于锁定OS任务调度,禁止调度
+//delay_osschedunlock:用于解锁OS任务调度,重新开启调度
+//    delay_ostimedly:用于OS延时,可以引起任务调度.
+
+//本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
+//支持UCOSII
+#ifdef 	OS_CRITICAL_METHOD						//OS_CRITICAL_METHOD定义了,说明要支持UCOSII				
+#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
+#define delay_ostickspersec	OS_TICKS_PER_SEC	//OS时钟节拍,即每秒调度次数
+#define delay_osintnesting 	OSIntNesting		//中断嵌套级别,即中断嵌套次数
+#endif
+
+//支持UCOSIII
+#ifdef 	CPU_CFG_CRITICAL_METHOD					//CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII	
+#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
+#define delay_ostickspersec	OSCfg_TickRate_Hz	//OS时钟节拍,即每秒调度次数
+#define delay_osintnesting 	OSIntNestingCtr		//中断嵌套级别,即中断嵌套次数
+#endif
+
+
+//us级延时时,关闭任务调度(防止打断us级延迟)
+void delay_osschedlock(void)
+{
+#ifdef CPU_CFG_CRITICAL_METHOD   				//使用UCOSIII
+	OS_ERR err; 
+	OSSchedLock(&err);							//UCOSIII的方式,禁止调度,防止打断us延时
+#else											//否则UCOSII
+	OSSchedLock();								//UCOSII的方式,禁止调度,防止打断us延时
+#endif
+}
+
+//us级延时时,恢复任务调度
+void delay_osschedunlock(void)
+{	
+#ifdef CPU_CFG_CRITICAL_METHOD   				//使用UCOSIII
+	OS_ERR err; 
+	OSSchedUnlock(&err);						//UCOSIII的方式,恢复调度
+#else											//否则UCOSII
+	OSSchedUnlock();							//UCOSII的方式,恢复调度
+#endif
+}
+
+//调用OS自带的延时函数延时
+//ticks:延时的节拍数
+void delay_ostimedly(u32 ticks)
+{
+#ifdef CPU_CFG_CRITICAL_METHOD
+	OS_ERR err; 
+	OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);	//UCOSIII延时采用周期模式
+#else
+	OSTimeDly(ticks);							//UCOSII延时
+#endif 
+}
+ 
+//systick中断服务函数,使用ucos时用到
+extern void systick_add(uint32_t tms);
+void SysTick_Handler(void)
+{	
+	if(delay_osrunning==1)						//OS开始跑了,才执行正常的调度处理
+	{
+		OSIntEnter();							//进入中断
+		OSTimeTick();       					//调用ucos的时钟服务程序               
+		OSIntExit();       	 					//触发任务切换软中断
+		systick_add(1000/OS_TICKS_PER_SEC);
+	}
+}
+#endif
+
+			   
+//初始化延迟函数
+//当使用OS的时候,此函数会初始化OS的时钟节拍
+//SYSTICK的时钟固定为HCLK时钟的1/8
+//SYSCLK:系统时钟
+void delay_init()
+{
+#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
+	u32 reload;
+#endif
+	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
+	fac_us=SystemCoreClock/8000000;				//为系统时钟的1/8  
+#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
+	reload=SystemCoreClock/8000000;				//每秒钟的计数次数 单位为K	   
+	reload*=1000000/delay_ostickspersec;		//根据delay_ostickspersec设定溢出时间
+												//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
+	fac_ms=1000/delay_ostickspersec;			//代表OS可以延时的最少单位	   
+
+	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
+	SysTick->LOAD=reload; 						//每1/delay_ostickspersec秒中断一次	
+	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    
+
+#else
+	fac_ms=(u16)fac_us*1000;					//非OS下,代表每个ms需要的systick时钟数   
+#endif
+}								    
+
+#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
+//延时nus
+//nus为要延时的us数.		    								   
+void delay_us(u32 nus)
+{		
+	u32 ticks;
+	u32 told,tnow,tcnt=0;
+	u32 reload=SysTick->LOAD;					//LOAD的值	    	 
+	ticks=nus*fac_us; 							//需要的节拍数	  		 
+	tcnt=0;
+	delay_osschedlock();						//阻止OS调度,防止打断us延时
+	told=SysTick->VAL;        					//刚进入时的计数器值
+	while(1)
+	{
+		tnow=SysTick->VAL;	
+		if(tnow!=told)
+		{	    
+			if(tnow<told)tcnt+=told-tnow;		//这里注意一下SYSTICK是一个递减的计数器就可以了.
+			else tcnt+=reload-tnow+told;	    
+			told=tnow;
+			if(tcnt>=ticks)break;				//时间超过/等于要延迟的时间,则退出.
+		}  
+	};
+	delay_osschedunlock();						//恢复OS调度									    
+}
+//延时nms
+//nms:要延时的ms数
+void delay_ms(u16 nms)
+{	
+	if(delay_osrunning&&delay_osintnesting==0)	//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	    
+	{		 
+		if(nms>=fac_ms)							//延时的时间大于OS的最少时间周期 
+		{ 
+   			delay_ostimedly(nms/fac_ms);		//OS延时
+		}
+		nms%=fac_ms;							//OS已经无法提供这么小的延时了,采用普通方式延时    
+	}
+	delay_us((u32)(nms*1000));					//普通方式延时  
+}
+#else //不用OS时
+//延时nus
+//nus为要延时的us数.		    								   
+void delay_us(u32 nus)
+{		
+	u32 temp;	    	 
+	SysTick->LOAD=nus*fac_us; 					//时间加载	  		 
+	SysTick->VAL=0x00;        					//清空计数器
+	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数	  
+	do
+	{
+		temp=SysTick->CTRL;
+	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
+	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
+	SysTick->VAL =0X00;      					 //清空计数器	 
+}
+//延时nms
+//注意nms的范围
+//SysTick->LOAD为24位寄存器,所以,最大延时为:
+//nms<=0xffffff*8*1000/SYSCLK
+//SYSCLK单位为Hz,nms单位为ms
+//对72M条件下,nms<=1864 
+void delay_ms(u16 nms)
+{	 		  	  
+	u32 temp;		   
+	SysTick->LOAD=(u32)nms*fac_ms;				//时间加载(SysTick->LOAD为24bit)
+	SysTick->VAL =0x00;							//清空计数器
+	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数  
+	do
+	{
+		temp=SysTick->CTRL;
+	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
+	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
+	SysTick->VAL =0X00;       					//清空计数器	  	    
+} 
+#endif 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 361 - 0
app/HARDWARE/sources/hd_eth.c

@@ -0,0 +1,361 @@
+#include "string.h"
+#include "includes.h"
+#include "lwip/netif.h"
+#include "arch/ethernetif.h"
+#include "arch/sys_arch.h"
+#include "lwip/init.h"
+#include "lwip/timers.h"
+#include "lwip/tcpip.h"
+#include "lwip/dhcp.h"
+#include "lwip/inet.h"
+
+struct netif gnetif;
+ETH_InitTypeDef ETH_InitStructure;
+uint32_t  EthStatus = 0;
+
+
+//初始ETH设备端口
+void ETH_GPIO_Config(void)
+{
+  GPIO_InitTypeDef GPIO_InitStructure;
+  
+  /* Enable GPIOs clocks */
+  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE |
+                         RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE);
+
+  /* Enable SYSCFG clock */
+  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);  
+
+  /* MII/RMII Media interface selection --------------------------------------*/
+  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
+	
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; 	
+
+  /* Configure PA1, PA2 and PA7 */
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7;
+  GPIO_Init(GPIOA, &GPIO_InitStructure);
+	GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
+	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
+
+  /* Configure PB5 and PB8 */
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_10;
+  GPIO_Init(GPIOB, &GPIO_InitStructure);
+	GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_ETH);	
+	GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_ETH);	
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH);	
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_ETH);
+
+  /* Configure PC1, PC2, PC3, PC4 and PC5 */
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
+  GPIO_Init(GPIOC, &GPIO_InitStructure);
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
+                                
+  /* Configure PG11, PG14 and PG13 */
+  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
+  GPIO_Init(GPIOG, &GPIO_InitStructure);
+  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
+  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
+}
+
+//硬件复位PHY
+void ETH_PHY_RESET(void)
+{
+	GPIO_InitTypeDef GPIO_InitStructure;
+	
+	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
+	
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;  
+  GPIO_Init(GPIOE, &GPIO_InitStructure);
+	
+	GPIO_SetBits(GPIOE, GPIO_Pin_2);	
+	systick_delayms(10);
+	GPIO_ResetBits(GPIOE, GPIO_Pin_2);	
+	systick_delayms(10);
+	GPIO_SetBits(GPIOE, GPIO_Pin_2);	
+	systick_delayms(10);
+}
+
+
+//配置以太网接收中断
+void ETH_NVIC_Config(void)
+{
+  NVIC_InitTypeDef   NVIC_InitStructure;
+
+  /* Enable the Ethernet global Interrupt */
+  NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);    
+	
+  /* Enable the Ethernet Rx Interrupt */
+  ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
+  ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);	
+  ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);
+}
+
+
+//配置以太网外设
+static void ETH_MACDMA_Config(void)
+{
+  ETH_InitTypeDef ETH_InitStructure;
+
+  /* Enable ETHERNET clock  */
+  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |
+                         RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);                                             
+
+  /* Reset ETHERNET on AHB Bus */
+  ETH_DeInit();
+
+  /* Software reset */
+  ETH_SoftwareReset();
+
+  /* Wait for software reset */
+  while (ETH_GetSoftwareResetStatus() == SET);
+
+  /* ETHERNET Configuration --------------------------------------------------*/
+  /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
+  ETH_StructInit(&ETH_InitStructure);
+
+  /* Fill ETH_InitStructure parametrs */
+  /*------------------------   MAC   -----------------------------------*/
+  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
+  //ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable; 
+  //  ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
+  //  ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;   
+
+  ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
+  ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
+  ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
+  ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
+  ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
+  ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
+  ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
+  ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
+#ifdef CHECKSUM_BY_HARDWARE
+  ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
+#endif
+
+  /*------------------------   DMA   -----------------------------------*/  
+  
+  /* When we use the Checksum offload feature, we need to enable the Store and Forward mode: 
+  the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum, 
+  if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
+  ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable; 
+  ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;         
+  ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;     
+ 
+  ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;       
+  ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;   
+  ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
+  ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;      
+  ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;                
+  ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;          
+  ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
+  ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
+
+  /* Configure Ethernet */
+	if(ETH_Init(&ETH_InitStructure, DP83848_PHY_ADDRESS)) EthStatus = ETH_INIT_FLAG;
+  else                                                  EthStatus = 0;
+}
+
+//获取phy连接状态   1:连接   0:断开
+uint8_t hd_ethGetPhyStatus(void)
+{
+	if(ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR) & 0x00000004) return 1;
+	else                                                               return 0;
+}
+
+void ETH_BSP_Config(void)
+{
+	ETH_GPIO_Config();
+	ETH_PHY_RESET();
+	ETH_MACDMA_Config();
+	if(EthStatus & ETH_INIT_FLAG) ETH_NVIC_Config();	
+	if(hd_ethGetPhyStatus()) EthStatus |= ETH_LINK_FLAG;
+}
+
+
+//以太网中断处理函数
+extern OS_EVENT *ETH_RecvDataSem;
+void ETH_IRQHandler(void)
+{
+  /* Frame received */
+  if (ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) 
+  {
+		OSSemPost(ETH_RecvDataSem);
+  }
+	
+  /* Clear the interrupt flags. */
+  /* Clear the Eth DMA Rx IT pending bits */
+  ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
+  ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
+}
+
+///////////////////////////////////////////////////////PHY///////////////////////////////////////////////////////////////////////////
+void low_level_init(struct netif *netif);
+void hd_ethCheckLinkStatus(uint16_t phyAddr)
+{
+	uint8_t linksta = hd_ethGetPhyStatus();
+	
+	if(EthStatus & ETH_INIT_FLAG)
+	{
+		if(EthStatus & ETH_LINK_FLAG)
+		{
+			if(linksta == 0)
+			{
+				netif_set_link_down(&gnetif);
+				EthStatus &= ~ETH_LINK_FLAG;
+			}
+		}
+		else 
+		{
+			if(linksta != 0)
+			{
+				netif_set_link_up(&gnetif);
+				EthStatus |= ETH_LINK_FLAG;
+			}
+		}
+	}
+	else 
+	{
+		if(linksta != 0)
+		{
+			low_level_init(&gnetif);
+			netif_set_link_up(&gnetif);
+#if LWIP_DHCP == 1
+			dhcp_start(&gnetif);
+#endif 			
+		}
+	}
+}
+
+void eth_link_callback(struct netif *netif)
+{
+	__IO uint32_t timeout = 0;
+	uint32_t tmpreg,RegValue;
+	
+	if(netif_is_link_up(netif))
+	{
+		printf("network is up");
+		
+		if(ETH_InitStructure.ETH_AutoNegotiation != ETH_AutoNegotiation_Disable)
+		{
+			timeout = 0;
+			ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_BCR, PHY_AutoNegotiation);
+			do
+			{
+				timeout ++;
+			}while(!(ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO));
+			
+			RegValue = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_SR);
+			if(RegValue & PHY_DUPLEX_STATUS) ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
+			else                             ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex; 
+			if(RegValue & PHY_SPEED_STATUS)  ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
+			else                             ETH_InitStructure.ETH_Speed = ETH_Speed_100M; 
+			
+			tmpreg = ETH->MACCR;
+			tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Speed | ETH_InitStructure.ETH_Mode);
+			ETH->MACCR = (uint32_t)tmpreg;
+			_eth_delay_(ETH_REG_WRITE_DELAY);
+      tmpreg = ETH->MACCR;
+      ETH->MACCR = tmpreg;
+		}
+		ETH_Start();
+		
+		netif_set_up(&gnetif);
+	}
+	else 
+	{
+		printf("network is down");		
+		ETH_Stop();
+		netif_set_down(&gnetif);
+	}
+}
+
+void ethphycheck_timer(void *arg)
+{
+  LWIP_UNUSED_ARG(arg);
+
+  hd_ethCheckLinkStatus(DP83848_PHY_ADDRESS);
+  sys_timeout(1000, ethphycheck_timer, NULL);
+}
+
+///////////////////////////////////////////////////////LWIP///////////////////////////////////////////////////////////////////////////
+//初始化LWIP协议栈
+void lwIP_Init(void)
+{
+	struct ip_addr ipaddr;
+	struct ip_addr netmask;
+	struct ip_addr gw;
+	
+	tcpip_init(NULL, NULL);
+
+#if LWIP_DHCP == 1
+	ip_addr_set_zero(&ipaddr);
+	ip_addr_set_zero(&netmask);	
+	ip_addr_set_zero(&gw);		
+#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 
+
+	netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);
+	netif_set_default(&gnetif);	
+	
+//	netif_set_up(&gnetif);
+	if(EthStatus == (ETH_LINK_FLAG | ETH_INIT_FLAG))
+	{
+		gnetif.flags |= NETIF_FLAG_LINK_UP; 
+		netif_set_up(&gnetif);
+		ETH_Start();
+		
+#if LWIP_DHCP == 1	
+		dhcp_start(&gnetif);
+		while(ip_addr_cmp(&(gnetif.ip_addr), &ipaddr))
+		{
+			OSTimeDly(10/(1000/OS_TICKS_PER_SEC));
+		}
+		printf("dhcp ip_addr is %s \r\n", inet_ntoa(gnetif.ip_addr));
+#endif 		
+	}
+	else 
+	{
+		netif_set_down(&gnetif);
+		gnetif.flags &= ~NETIF_FLAG_LINK_UP; 
+		ETH_Stop();
+	}
+	
+	netif_set_link_callback(&gnetif, eth_link_callback);
+	sys_timeout(2000, ethphycheck_timer, NULL);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 129 - 0
app/HARDWARE/sources/led.c

@@ -0,0 +1,129 @@
+#include "led.h"
+
+void LED_GPIO_Config(void)
+{		
+		/*定义一个GPIO_InitTypeDef类型的结构体*/
+		GPIO_InitTypeDef GPIO_InitStructure;
+
+		/*开启LED相关的GPIO外设时钟*/
+		RCC_AHB1PeriphClockCmd ( LED_GPIO_CLK, ENABLE); 
+
+		/*选择要控制的GPIO引脚*/															   
+		GPIO_InitStructure.GPIO_Pin = LED_PIN;	
+
+		/*设置引脚模式为输出模式*/
+		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
+    
+    /*设置引脚的输出类型为推挽输出*/
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    
+    /*设置引脚为上拉模式*/
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+
+		/*设置引脚速率为2MHz */   
+		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 
+
+		/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
+		GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);	
+}
+
+void NET_STATUS_LED_Config(void)
+{
+			/*定义一个GPIO_InitTypeDef类型的结构体*/
+		GPIO_InitTypeDef GPIO_InitStructure;
+
+		/*开启NET_STATUS_LED相关的GPIO外设时钟*/
+		RCC_AHB1PeriphClockCmd ( NET_STATUS_LED_GPIO_CLK, ENABLE); 
+
+		/*选择要控制的GPIO引脚*/															   
+		GPIO_InitStructure.GPIO_Pin = NET_STATUS_LED_PIN;	
+
+		/*设置引脚模式为输出模式*/
+		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
+    
+    /*设置引脚的输出类型为推挽输出*/
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    
+    /*设置引脚为上拉模式*/
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+
+		/*设置引脚速率为2MHz */   
+		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 
+
+		/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
+		GPIO_Init(NET_STATUS_LED_GPIO_PORT, &GPIO_InitStructure);	
+}
+
+void STATUS_LED_Config(void)
+{
+				/*定义一个GPIO_InitTypeDef类型的结构体*/
+		GPIO_InitTypeDef GPIO_InitStructure;
+
+		/*开启STATUS_LED相关的GPIO外设时钟*/
+		RCC_AHB1PeriphClockCmd ( STATUS_LED_GPIO_CLK, ENABLE); 
+
+		/*选择要控制的GPIO引脚*/															   
+		GPIO_InitStructure.GPIO_Pin = STATUS_LED_PIN;	
+
+		/*设置引脚模式为输出模式*/
+		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
+    
+    /*设置引脚的输出类型为推挽输出*/
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    
+    /*设置引脚为上拉模式*/
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+
+		/*设置引脚速率为2MHz */   
+		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 
+
+		/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
+		GPIO_Init(STATUS_LED_GPIO_PORT, &GPIO_InitStructure);	
+}
+
+
+
+
+int led_openTime = 500;
+int led_closeTime = 500;
+
+
+int hd_netledOpen(void)
+{
+	NET_STATUS_LED(1);
+	return led_openTime;
+}
+
+int hd_netledClose(void)
+{
+	NET_STATUS_LED(0);
+	return led_closeTime;
+}
+
+void hd_netledSetOpenTime(int tms)
+{
+	if(tms > 1000) tms = 1000;
+	
+	led_openTime = tms;
+	led_closeTime = (1000 - led_openTime);
+}
+
+int hd_netledGetOpenTime(void)
+{
+	return led_openTime;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 61 - 0
app/HARDWARE/sources/log.c

@@ -0,0 +1,61 @@
+/*
+ * log.c
+ *
+ *  Created on: Nov 7, 2022
+ *      Author: tangm
+ */
+#include "log.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include "usart.h"
+///重定向c库函数printf到串口,重定向后可使用printf函数
+int fputc(int ch, FILE *f)
+{
+		/* 发送一个字节数据到串口 */
+		USART_SendData(USART_232, (uint8_t) ch);
+		
+		/* 等待发送完毕 */
+		while (USART_GetFlagStatus(USART_232, USART_FLAG_TXE) == RESET);	
+		return (ch);
+}
+
+///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
+int fgetc(FILE *f)
+{
+		/* 等待串口输入数据 */
+		while (USART_GetFlagStatus(USART_232, USART_FLAG_RXNE) == RESET);
+
+		return (int)USART_ReceiveData(USART_232);
+}
+
+void LogPrint(logLevel_t logLevel, const char *func, const int line, char * fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	char buf[LOG_LEN_MAX];
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	switch (logLevel)
+	{
+#ifdef _LOG_INFO
+		case LOG_INFO:
+			printf("LOG[%-5s][%-20s:%4d] %s\r\n", "INFO", func, line, buf);
+			break;
+#endif
+#ifdef _LOG_DEBUG
+		case LOG_DEBUG:
+			printf("LOG[%-5s][%-20s:%4d] %s\r\n", "DEBUG", func, line, buf);
+			break;
+#endif
+#ifdef _LOG_WARN
+		case LOG_WARN:
+			printf("LOG[%-5s][%-20s:%4d] %s\r\n", "WARN", func, line, buf);
+			break;
+#endif
+		case LOG_ERROR:
+			printf("LOG[%-5s][%-20s:%4d] %s\r\n", "ERROR", func, line, buf);
+			break;
+		default:
+			break;
+	}
+}

+ 226 - 0
app/HARDWARE/sources/malloc.c

@@ -0,0 +1,226 @@
+#include "malloc.h"	    
+
+
+
+//内存池(32字节对齐)
+__align(32) uint8_t mem1base[MEM1_MAX_SIZE];													//内部SRAM内存池
+__align(32) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));					//外部SRAM内存池
+
+
+//内存管理表
+uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE];													//内部SRAM内存池MAP
+uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE)));	//外部SRAM内存池MAP
+
+
+//内存管理参数	   
+const uint32_t memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE};			//内存表大小
+const uint32_t memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE};						      //内存分块大小
+const uint32_t memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE};								          //内存总大小
+
+
+//内存管理控制器
+struct _m_mallco_dev mallco_dev=
+{
+	my_mem_init,				             //内存初始化
+	my_mem_perused,				           //内存使用率
+	mem1base,mem2base,			         //内存池
+	mem1mapbase,mem2mapbase,	       //内存管理状态表
+	0,0,  		 				               //内存管理未就绪
+};
+
+
+
+//复制内存
+//*des:目的地址
+//*src:源地址
+//n:需要复制的内存长度(字节为单位)
+void mymemcpy(void *des,void *src,uint32_t n)  
+{  
+	uint8_t *xdes=des;
+	uint8_t *xsrc=src; 
+	
+	
+	while(n--)*xdes++=*xsrc++;  
+	
+}  
+
+
+//设置内存
+//*s:内存首地址
+//c :要设置的值
+//count:需要设置的内存大小(字节为单位)
+void mymemset(void *s,uint8_t c,uint32_t count)  
+{  
+	uint8_t *xs = s;  
+
+
+	while(count--)*xs++=c;  
+	
+}	   
+
+
+//内存管理初始化  
+//memx:所属内存块
+void my_mem_init(uint8_t memx)  
+{  
+	mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零  
+	mymemset(mallco_dev.membase[memx], 0,memsize[memx]);	//内存池所有数据清零  
+	mallco_dev.memrdy[memx]=1;								//内存管理初始化OK  
+}  
+
+
+//获取内存使用率
+//memx:所属内存块
+//返回值:使用率(0~100)
+uint8_t my_mem_perused(uint8_t memx)  
+{  
+	uint32_t used=0;  
+	uint32_t i;  
+	
+	
+	for(i=0;i<memtblsize[memx];i++)  
+	{  
+			if(mallco_dev.memmap[memx][i])used++; 
+	} 
+	
+	return (used*100)/(memtblsize[memx]);  
+	
+}  
+
+
+//内存分配(内部调用)
+//memx:所属内存块
+//size:要分配的内存大小(字节)
+//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
+uint32_t my_mem_malloc(uint8_t memx,uint32_t size)  
+{  
+	signed long offset=0;  
+	uint32_t nmemb;	//需要的内存块数  
+	uint32_t cmemb=0;//连续空内存块数
+	uint32_t i;  
+	
+	
+	if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先执行初始化 
+	
+	if(size==0)
+		return 0XFFFFFFFF;//不需要分配
+	
+	nmemb=size/memblksize[memx];  	//获取需要分配的连续内存块数
+	
+	if(size%memblksize[memx])nmemb++; 
+	
+	for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整个内存控制区  
+	{     
+		if(!mallco_dev.memmap[memx][offset])cmemb++;//连续空内存块数增加
+		else cmemb=0;								//连续内存块清零
+		
+		if(cmemb==nmemb)							//找到了连续nmemb个空内存块
+		{
+			for(i=0;i<nmemb;i++)  					//标注内存块非空 
+			{  
+					mallco_dev.memmap[memx][offset+i]=nmemb;  
+			}  
+			return (offset*memblksize[memx]);//返回偏移地址  
+		}
+		
+	}  
+	
+	return 0XFFFFFFFF;//未找到符合分配条件的内存块  
+	
+}  
+
+
+//释放内存(内部调用) 
+//memx:所属内存块
+//offset:内存地址偏移
+//返回值:0,释放成功;1,释放失败;  
+uint8_t my_mem_free(uint8_t memx,uint32_t offset)  
+{  
+	int i;  
+	
+	
+	if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化
+	{
+	mallco_dev.init(memx);    
+			return 1;//未初始化  
+	}  
+	
+	if(offset<memsize[memx])//偏移在内存池内. 
+	{  
+			int index=offset/memblksize[memx];			//偏移所在内存块号码  
+			int nmemb=mallco_dev.memmap[memx][index];	//内存块数量
+			for(i=0;i<nmemb;i++)  						//内存块清零
+			{  
+					mallco_dev.memmap[memx][index+i]=0;  
+			}  
+			return 0;  
+	}
+	else 
+		return 2;//偏移超区了.  
+	
+}  
+
+
+//释放内存(外部调用) 
+//memx:所属内存块
+//ptr:内存首地址 
+void myfree(uint8_t memx,void *ptr)  
+{  
+	uint32_t offset;   
+	
+	
+	if(ptr==NULL)return;//地址为0.  
+	offset=(uint32_t)ptr-(uint32_t)mallco_dev.membase[memx];     
+	my_mem_free(memx,offset);	//释放内存     
+	
+}  
+
+
+//分配内存(外部调用)
+//memx:所属内存块
+//size:内存大小(字节)
+//返回值:分配到的内存首地址.
+void *mymalloc(uint8_t memx,uint32_t size)  
+{  
+	uint32_t offset;   
+	
+	
+	offset=my_mem_malloc(memx,size);  	   	 
+	
+	if(offset==0XFFFFFFFF)return NULL;  
+	else return (void*)((uint32_t)mallco_dev.membase[memx]+offset);  
+	
+}  
+
+
+//重新分配内存(外部调用)
+//memx:所属内存块
+//*ptr:旧内存首地址
+//size:要分配的内存大小(字节)
+//返回值:新分配到的内存首地址.
+void *myrealloc(uint8_t memx,void *ptr,uint32_t size)  
+{  
+	uint32_t offset;    
+	
+	
+	offset=my_mem_malloc(memx,size);   	
+	if(offset==0XFFFFFFFF)return NULL;     
+	else  
+	{  									   
+		mymemcpy((void*)((uint32_t)mallco_dev.membase[memx]+offset),ptr,size);	//拷贝旧内存内容到新内存   
+		myfree(memx,ptr);  											  		//释放旧内存
+		return (void*)((uint32_t)mallco_dev.membase[memx]+offset);  				//返回新内存首地址
+	}  
+	
+}
+
+
+
+
+
+
+
+
+
+
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2190 - 0
app/HARDWARE/sources/nandflash.c


+ 69 - 0
app/HARDWARE/sources/spi.c

@@ -0,0 +1,69 @@
+#include "spi.h"
+
+
+void SPI2_GPIO_Config(void)
+{
+    GPIO_InitTypeDef GPIO_InitStructure;
+
+    /* Enable SPI2 and GPIO clock */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
+		
+		 /* Configure SPI2 CS pin */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+    /* Configure SPI2 pins: SCK, MISO and MOSI */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    /* Connect GPIO pins to SPI2 alternate function */
+    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // SCK
+    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); // MISO
+    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // MOSI
+}
+
+void spi_config(void)
+{
+		SPI2_GPIO_Config();
+    SPI_InitTypeDef SPI_InitStructure;
+
+    /* SPI2 configuration */
+    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
+    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
+    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
+    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
+    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
+    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
+    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
+    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
+    SPI_InitStructure.SPI_CRCPolynomial = 7;
+    SPI_Init(SPI2, &SPI_InitStructure);
+
+    /* Enable SPI2 */
+    SPI_Cmd(SPI2, ENABLE);
+}
+/*-------------------------------------------------*/
+/*函数名:SPI收发一个字节                          */
+/*参  数:txd:要发送的数据                        */
+/*返回值:接收到的数据                             */
+/*-------------------------------------------------*/
+uint8_t SPI2_ReadWriteByte(uint8_t txd)
+{
+	while(SPI_GetFlagStatus(SPI2,SPI_FLAG_TXE)!=1);  
+	SPI_SendData(SPI2,txd);                                   
+	while(SPI_GetFlagStatus(SPI2,SPI_FLAG_RXNE)!=1); 
+	return SPI_ReceiveData(SPI2);              
+}
+
+void SpiNSSEnable( uint8_t status )
+{
+    GPIO_WriteBit( GPIOB, GPIO_Pin_12, (BitAction) status );
+}

+ 452 - 0
app/HARDWARE/sources/sram.c

@@ -0,0 +1,452 @@
+/**
+  ******************************************************************************
+  * @file    sram.c
+  * @author  fire
+  * @version V1.0
+  * @date    2015-xx-xx
+  * @brief   sram应用函数接口
+  ******************************************************************************
+  * @attention
+  *
+  * 实验平台:野火  STM32 F407 开发板 
+  * 论坛    :http://www.firebbs.cn
+  * 淘宝    :https://fire-stm32.taobao.com
+  *
+  ******************************************************************************
+  */
+
+
+
+#include "sram.h"	  
+
+
+
+/**
+  * @brief  初始化控制SRAM的IO
+  * @param  无
+  * @retval 无
+  */
+static void SRAM_GPIO_Config(void)
+{
+	GPIO_InitTypeDef  GPIO_InitStructure;
+ 
+  /* 使能SRAM相关的GPIO时钟 */
+
+                         /*地址信号线*/
+  RCC_AHB1PeriphClockCmd(FSMC_A0_GPIO_CLK | FSMC_A1_GPIO_CLK | FSMC_A2_GPIO_CLK | 
+                         FSMC_A3_GPIO_CLK | FSMC_A4_GPIO_CLK | FSMC_A5_GPIO_CLK |
+                         FSMC_A6_GPIO_CLK | FSMC_A7_GPIO_CLK | FSMC_A8_GPIO_CLK |
+                         FSMC_A9_GPIO_CLK | FSMC_A10_GPIO_CLK| FSMC_A11_GPIO_CLK| 
+												 FSMC_A12_GPIO_CLK| FSMC_A13_GPIO_CLK|FSMC_A14_GPIO_CLK|
+												 FSMC_A15_GPIO_CLK|FSMC_A16_GPIO_CLK|FSMC_A17_GPIO_CLK|FSMC_A18_GPIO_CLK|
+                         /*数据信号线*/
+                         FSMC_D0_GPIO_CLK | FSMC_D1_GPIO_CLK | FSMC_D2_GPIO_CLK | 
+                         FSMC_D3_GPIO_CLK | FSMC_D4_GPIO_CLK | FSMC_D5_GPIO_CLK |
+                         FSMC_D6_GPIO_CLK | FSMC_D7_GPIO_CLK | FSMC_D8_GPIO_CLK |
+                         FSMC_D9_GPIO_CLK | FSMC_D10_GPIO_CLK| FSMC_D11_GPIO_CLK|
+                         FSMC_D12_GPIO_CLK| FSMC_D13_GPIO_CLK| FSMC_D14_GPIO_CLK|
+                         FSMC_D15_GPIO_CLK|  
+                         /*控制信号线*/
+                         FSMC_CS_GPIO_CLK  | FSMC_WE_GPIO_CLK | FSMC_OE_GPIO_CLK |
+                         FSMC_UDQM_GPIO_CLK|FSMC_LDQM_GPIO_CLK, ENABLE);
+												 
+
+
+	 /*-- GPIO 配置 -----------------------------------------------------*/
+
+  /* 通用 GPIO 配置 */
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+  
+  /*A地址信号线 针对引脚配置*/
+  GPIO_InitStructure.GPIO_Pin = FSMC_A0_GPIO_PIN; 
+  GPIO_Init(FSMC_A0_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A0_GPIO_PORT,FSMC_A0_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A1_GPIO_PIN; 
+  GPIO_Init(FSMC_A1_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A1_GPIO_PORT,FSMC_A1_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A2_GPIO_PIN; 
+  GPIO_Init(FSMC_A2_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A2_GPIO_PORT,FSMC_A2_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A3_GPIO_PIN; 
+  GPIO_Init(FSMC_A3_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A3_GPIO_PORT,FSMC_A3_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A4_GPIO_PIN; 
+  GPIO_Init(FSMC_A4_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A4_GPIO_PORT,FSMC_A4_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A5_GPIO_PIN; 
+  GPIO_Init(FSMC_A5_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A5_GPIO_PORT,FSMC_A5_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A6_GPIO_PIN; 
+  GPIO_Init(FSMC_A6_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A6_GPIO_PORT,FSMC_A6_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A7_GPIO_PIN; 
+  GPIO_Init(FSMC_A7_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A7_GPIO_PORT,FSMC_A7_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A8_GPIO_PIN; 
+  GPIO_Init(FSMC_A8_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A8_GPIO_PORT,FSMC_A8_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A9_GPIO_PIN; 
+  GPIO_Init(FSMC_A9_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A9_GPIO_PORT,FSMC_A9_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A10_GPIO_PIN; 
+  GPIO_Init(FSMC_A10_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A10_GPIO_PORT,FSMC_A10_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A11_GPIO_PIN; 
+  GPIO_Init(FSMC_A11_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A11_GPIO_PORT,FSMC_A11_GPIO_PinSource,FSMC_GPIO_AF);
+	
+  GPIO_InitStructure.GPIO_Pin = FSMC_A12_GPIO_PIN; 
+  GPIO_Init(FSMC_A12_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A12_GPIO_PORT,FSMC_A12_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A13_GPIO_PIN; 
+  GPIO_Init(FSMC_A13_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A13_GPIO_PORT,FSMC_A13_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A14_GPIO_PIN; 
+  GPIO_Init(FSMC_A14_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A14_GPIO_PORT,FSMC_A14_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A15_GPIO_PIN; 
+  GPIO_Init(FSMC_A15_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A15_GPIO_PORT,FSMC_A15_GPIO_PinSource,FSMC_GPIO_AF);  
+	
+  GPIO_InitStructure.GPIO_Pin = FSMC_A16_GPIO_PIN; 
+  GPIO_Init(FSMC_A16_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A16_GPIO_PORT,FSMC_A16_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A17_GPIO_PIN; 
+  GPIO_Init(FSMC_A17_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A17_GPIO_PORT,FSMC_A17_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_A18_GPIO_PIN; 
+  GPIO_Init(FSMC_A18_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_A18_GPIO_PORT,FSMC_A18_GPIO_PinSource,FSMC_GPIO_AF);
+    
+  /*DQ数据信号线 针对引脚配置*/
+  GPIO_InitStructure.GPIO_Pin = FSMC_D0_GPIO_PIN; 
+  GPIO_Init(FSMC_D0_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D0_GPIO_PORT,FSMC_D0_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D1_GPIO_PIN; 
+  GPIO_Init(FSMC_D1_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D1_GPIO_PORT,FSMC_D1_GPIO_PinSource,FSMC_GPIO_AF);
+    
+  GPIO_InitStructure.GPIO_Pin = FSMC_D2_GPIO_PIN; 
+  GPIO_Init(FSMC_D2_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D2_GPIO_PORT,FSMC_D2_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D3_GPIO_PIN; 
+  GPIO_Init(FSMC_D3_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D3_GPIO_PORT,FSMC_D3_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D4_GPIO_PIN; 
+  GPIO_Init(FSMC_D4_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D4_GPIO_PORT,FSMC_D4_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D5_GPIO_PIN; 
+  GPIO_Init(FSMC_D5_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D5_GPIO_PORT,FSMC_D5_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D6_GPIO_PIN; 
+  GPIO_Init(FSMC_D6_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D6_GPIO_PORT,FSMC_D6_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D7_GPIO_PIN; 
+  GPIO_Init(FSMC_D7_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D7_GPIO_PORT,FSMC_D7_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D8_GPIO_PIN; 
+  GPIO_Init(FSMC_D8_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D8_GPIO_PORT,FSMC_D8_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D9_GPIO_PIN; 
+  GPIO_Init(FSMC_D9_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D9_GPIO_PORT,FSMC_D9_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D10_GPIO_PIN; 
+  GPIO_Init(FSMC_D10_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D10_GPIO_PORT,FSMC_D10_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D11_GPIO_PIN; 
+  GPIO_Init(FSMC_D11_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D11_GPIO_PORT,FSMC_D11_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D12_GPIO_PIN; 
+  GPIO_Init(FSMC_D12_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D12_GPIO_PORT,FSMC_D12_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D13_GPIO_PIN; 
+  GPIO_Init(FSMC_D13_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D13_GPIO_PORT,FSMC_D13_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D14_GPIO_PIN; 
+  GPIO_Init(FSMC_D14_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D14_GPIO_PORT,FSMC_D14_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_D15_GPIO_PIN; 
+  GPIO_Init(FSMC_D15_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_D15_GPIO_PORT,FSMC_D15_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  /*控制信号线*/
+  GPIO_InitStructure.GPIO_Pin = FSMC_CS_GPIO_PIN; 
+  GPIO_Init(FSMC_CS_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_CS_GPIO_PORT,FSMC_CS_GPIO_PinSource,FSMC_GPIO_AF);
+    
+  GPIO_InitStructure.GPIO_Pin = FSMC_WE_GPIO_PIN; 
+  GPIO_Init(FSMC_WE_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_WE_GPIO_PORT,FSMC_WE_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_OE_GPIO_PIN; 
+  GPIO_Init(FSMC_OE_GPIO_PORT, &GPIO_InitStructure);   
+  GPIO_PinAFConfig(FSMC_OE_GPIO_PORT,FSMC_OE_GPIO_PinSource,FSMC_GPIO_AF);  
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_UDQM_GPIO_PIN; 
+  GPIO_Init(FSMC_UDQM_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_UDQM_GPIO_PORT,FSMC_UDQM_GPIO_PinSource,FSMC_GPIO_AF);
+  
+  GPIO_InitStructure.GPIO_Pin = FSMC_LDQM_GPIO_PIN; 
+  GPIO_Init(FSMC_LDQM_GPIO_PORT, &GPIO_InitStructure);
+  GPIO_PinAFConfig(FSMC_LDQM_GPIO_PORT,FSMC_LDQM_GPIO_PinSource,FSMC_GPIO_AF); 
+}				  			
+
+
+/**
+  * @brief  初始化FSMC外设
+  * @param  None. 
+  * @retval None.
+  */
+void FSMC_SRAM_Init(void)
+{	
+	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
+	FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;
+
+	/*初始化SRAM相关的GPIO*/
+	SRAM_GPIO_Config();
+		
+	/*使能FSMC外设时钟*/
+	RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);
+
+	//地址建立时间(ADDSET)为1个HCLK,1/120M = 8.33ns
+	readWriteTiming.FSMC_AddressSetupTime = 0x00;	
+
+	//地址保持时间(ADDHLD)模式A未用到
+	readWriteTiming.FSMC_AddressHoldTime = 0x00;	 
+
+	//数据保持时间(DATAST)+ 1个HCLK = 2/120M=16.6ns
+	readWriteTiming.FSMC_DataSetupTime = 0x02;		  
+	
+	//设置总线转换周期,仅用于复用模式的NOR操作
+	readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
+	
+	//设置时钟分频,仅用于同步类型的存储器
+	//readWriteTiming.FSMC_CLKDivision = 0x16;	
+	readWriteTiming.FSMC_CLKDivision = 0xf;	
+
+	//数据保持时间,仅用于同步型的NOR
+	//readWriteTiming.FSMC_DataLatency = 0x17;		
+	readWriteTiming.FSMC_DataLatency = 0xf;
+	
+	//选择匹配SRAM的模式
+	readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;	 
+    
+
+	// 选择FSMC映射的存储区域: Bank1 sram3
+	FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
+	
+	//设置地址总线与数据总线是否复用,仅用于NOR
+	FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; 
+	
+	//设置要控制的存储器类型:SRAM类型
+	FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;   
+	
+	//存储器数据宽度:16位
+	FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; 
+	
+	//设置是否使用突发访问模式,仅用于同步类型的存储器
+	FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;
+	
+	//设置是否使能等待信号,仅用于同步类型的存储器
+	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
+	
+	//设置等待信号的有效极性,仅用于同步类型的存储器
+	FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
+	
+	//设置是否支持把非对齐的突发操作,仅用于同步类型的存储器
+	FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; 
+	
+	//设置等待信号插入的时间,仅用于同步类型的存储器
+	FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
+	
+	//存储器写使能 
+	FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
+	
+	//不使用等待信号
+	FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;  		
+	
+	// 不使用扩展模式,读写使用相同的时序
+	FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; 
+	
+	//突发写操作
+	FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;  
+	
+	//读写时序配置
+	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
+	
+	//读写同样时序,使用扩展模式时这个配置才有效
+	FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; 
+	
+
+	FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置
+
+	FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);  // 使能BANK										  
+											
+}
+	  		
+
+
+
+/**
+  * @brief  以“字”为单位向sdram写入数据 
+  * @param  pBuffer: 指向数据的指针 
+  * @param  uwWriteAddress: 要写入的SRAM内部地址
+  * @param  uwBufferSize: 要写入数据大小
+  * @retval None.
+  */
+void SRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize)
+{
+  __IO uint32_t write_pointer = (uint32_t)uwWriteAddress;
+ 
+
+  /* 循环写入数据 */
+  for (; uwBufferSize != 0; uwBufferSize--) 
+  {
+    /* 发送数据到SRAM */
+    *(uint32_t *) (Bank1_SRAM3_ADDR + write_pointer) = *pBuffer++;
+
+    /* 地址自增*/
+    write_pointer += 4;
+  }
+    
+}
+
+/**
+  * @brief  从SRAM中读取数据 
+  * @param  pBuffer: 指向存储数据的buffer
+  * @param  ReadAddress: 要读取数据的地十
+  * @param  uwBufferSize: 要读取的数据大小
+  * @retval None.
+  */
+void SRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize)
+{
+  __IO uint32_t write_pointer = (uint32_t)uwReadAddress;
+  
+  
+  /*读取数据 */
+  for(; uwBufferSize != 0x00; uwBufferSize--)
+  {
+   *pBuffer++ = *(__IO uint32_t *)(Bank1_SRAM3_ADDR + write_pointer );
+    
+   /* 地址自增*/
+    write_pointer += 4;
+  } 
+}
+
+
+/**
+  * @brief  测试SRAM是否正常 
+  * @param  None
+  * @retval 正常返回1,异常返回0
+  */
+uint8_t SRAM_Test(void)
+{
+  /*写入数据计数器*/
+  uint32_t counter=0;
+  
+  /* 8位的数据 */
+  uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0;  
+  
+  /* 16位的数据 */
+  uint16_t uhWritedata_16b = 0, uhReaddata_16b = 0; 
+  
+  SRAM_INFO("正在检测SRAM,以8位、16位的方式读写sram...");
+
+
+  /*按8位格式读写数据,并校验*/
+  
+  /* 把SRAM数据全部重置为0 ,IS62WV51216_SIZE是以8位为单位的 */
+  for (counter = 0x00; counter < IS62WV51216_SIZE; counter++)
+  {
+    *(__IO uint8_t*) (Bank1_SRAM3_ADDR + counter) = (uint8_t)0x0;
+  }
+  
+  /* 向整个SRAM写入数据  8位 */
+  for (counter = 0; counter < IS62WV51216_SIZE; counter++)
+  {
+    *(__IO uint8_t*) (Bank1_SRAM3_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter);
+  }
+  
+  /* 读取 SRAM 数据并检测*/
+  for(counter = 0; counter<IS62WV51216_SIZE;counter++ )
+  {
+    ubReaddata_8b = *(__IO uint8_t*)(Bank1_SRAM3_ADDR + counter);  //从该地址读出数据
+    
+    if(ubReaddata_8b != (uint8_t)(ubWritedata_8b + counter))      //检测数据,若不相等,跳出函数,返回检测失败结果。
+    {
+      SRAM_ERROR("8位数据读写错误!");
+      return 0;
+    }
+  }
+
+  
+  /*按16位格式读写数据,并检测*/
+  
+  /* 把SRAM数据全部重置为0 */
+  for (counter = 0x00; counter < IS62WV51216_SIZE/2; counter++)
+  {
+    *(__IO uint16_t*) (Bank1_SRAM3_ADDR + 2*counter) = (uint16_t)0x00;
+  }
+  
+  /* 向整个SRAM写入数据  16位 */
+  for (counter = 0; counter < IS62WV51216_SIZE/2; counter++)
+  {
+    *(__IO uint16_t*) (Bank1_SRAM3_ADDR + 2*counter) = (uint16_t)(uhWritedata_16b + counter);
+  }
+  
+    /* 读取 SRAM 数据并检测*/
+  for(counter = 0; counter<IS62WV51216_SIZE/2;counter++ )
+  {
+    uhReaddata_16b = *(__IO uint16_t*)(Bank1_SRAM3_ADDR + 2*counter);  //从该地址读出数据
+    
+    if(uhReaddata_16b != (uint16_t)(uhWritedata_16b + counter))      //检测数据,若不相等,跳出函数,返回检测失败结果。
+    {
+      SRAM_ERROR("16位数据读写错误!");
+
+      return 0;
+    }
+  }
+  
+  SRAM_INFO("SRAM读写测试正常!"); 
+  /*检测正常,return 1 */
+  return 1;
+
+}
+
+
+
+
+

+ 453 - 0
app/HARDWARE/sources/usart.c

@@ -0,0 +1,453 @@
+#include "usart.h"
+
+uint8_t UART6_RX_BUF[BUFF_SIZE];
+uint8_t UART6_RX_STAT=0;
+uint32_t UART6_RX_NUM = 0;	
+
+
+ /**
+  * @brief  DEBUG_USART GPIO 配置,工作模式配置。115200 8-N-1 ,中断接收模式
+  * @param  无
+  * @retval 无
+  */
+void DEBUG_USART_Config(void)
+{
+  USART_InitTypeDef USART_InitStruct;
+  GPIO_InitTypeDef GPIO_InitStruct;
+
+  // Enable USART6 clock
+  RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
+
+  // Enable GPIOC clock
+  RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK, ENABLE);
+
+  // Configure USART6 pins
+  GPIO_InitStruct.GPIO_Pin = DEBUG_USART_RX_PIN | DEBUG_USART_TX_PIN;  // USART6_TX (PC6) and USART6_RX (PC7)
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStruct);
+
+  // Connect USART6 pins to AF8
+  GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT, DEBUG_USART_RX_SOURCE, DEBUG_USART_RX_AF);
+  GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT, DEBUG_USART_TX_SOURCE, DEBUG_USART_TX_AF);
+
+  // Configure USART6
+  USART_InitStruct.USART_BaudRate = DEBUG_USART_BAUDRATE;
+  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
+  USART_InitStruct.USART_StopBits = USART_StopBits_1;
+  USART_InitStruct.USART_Parity = USART_Parity_No;
+  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  USART_Init(DEBUG_USART, &USART_InitStruct);
+	
+
+	NVIC_InitTypeDef NVIC_InitStructure;
+	NVIC_InitStructure.NVIC_IRQChannel 					 = DEBUG_USART_IRQ;      //IRQ通道
+	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;          		 //主优先级
+	NVIC_InitStructure.NVIC_IRQChannelSubPriority		 = 1;                //从优先级
+	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;           //使能通道
+	NVIC_Init(&NVIC_InitStructure);
+	
+  // Enable USART6
+	USART_ITConfig(DEBUG_USART, USART_IT_IDLE, ENABLE); //开启空闲中断
+	DMA_Cmd(DEBUG_USART_DMA_STREAM, ENABLE);						//使能DMA接收
+  USART_Cmd(DEBUG_USART, ENABLE);
+	USART_ClearFlag(DEBUG_USART, USART_FLAG_TC);
+	
+
+}
+
+void DEBUG_USART_IRQHandler(void)
+{
+	uint16_t clear;
+	if(USART_GetITStatus(DEBUG_USART,USART_IT_IDLE)!=RESET)
+	{
+		//清除空闲中断
+		clear=USART6->SR;
+		clear=USART6->DR;
+		//关闭DMA
+		DMA_Cmd(DEBUG_USART_DMA_STREAM,DISABLE);
+		UART6_RX_NUM=BUFF_SIZE-DMA_GetCurrDataCounter(DEBUG_USART_DMA_STREAM);
+		//清除DMA中断
+		DMA_ClearFlag(DEBUG_USART_DMA_STREAM,DMA_IT_TCIF1);
+		DMA_Cmd(DEBUG_USART_DMA_STREAM, ENABLE);
+		//接收状态置位
+		UART6_RX_STAT=1;
+		
+	}
+}
+
+/**
+  * @brief  USART1 TX DMA 配置,内存到外设(USART1->DR)
+  * @param  无
+  * @retval 无
+  */
+
+void USART_DMA_Config(void)
+{
+	// 使能串口和DMA时钟
+  RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
+  RCC_AHB1PeriphClockCmd(DEBUG_USART_DMA_CLK, ENABLE);
+	
+  DMA_InitTypeDef DMA_InitStructure;
+  
+  DMA_InitStructure.DMA_Channel = DEBUG_USART_DMA_CHANNEL;  
+  /*设置DMA源:串口数据寄存器地址*/
+  DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_USART_DR_BASE;	 
+  /*内存地址(要传输的变量的指针)*/
+  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)UART6_RX_BUF;
+  /*方向:从外设到内存*/		
+  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;	
+  /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/	
+  DMA_InitStructure.DMA_BufferSize = BUFF_SIZE;
+  /*外设地址不增*/	    
+  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
+  /*内存地址自增*/
+  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;	
+  /*外设数据单位*/	
+  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+  /*内存数据单位 8bit*/
+  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;	
+  /*DMA模式:不断循环*/
+  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	 
+  /*优先级:中*/	
+  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;      
+  /*禁用FIFO*/
+  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        
+  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;    
+  /*存储器突发传输 16个节拍*/
+  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;    
+  /*外设突发传输 1个节拍*/
+  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    
+  /*配置DMA2的数据流*/		   
+  DMA_Init(DEBUG_USART_DMA_STREAM, &DMA_InitStructure);
+	USART_DMACmd(DEBUG_USART,USART_DMAReq_Rx,ENABLE);
+	DMA_ITConfig(DEBUG_USART_DMA_STREAM,DMA_IT_TC,ENABLE);
+	NVIC_InitTypeDef NVIC_InitStructure;
+	NVIC_InitStructure.NVIC_IRQChannel                   = DMA2_Stream5_IRQn ;//串口1发送中断通道
+	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;                 //抢占优先级
+	NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 2;		          //子优先级
+	NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;			  //IRQ通道使能
+	NVIC_Init(&NVIC_InitStructure);
+	
+}
+
+void DMA2_Stream5_IRQHandler() {
+    if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)) 
+		{
+        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
+    }
+}
+
+/*
+	485串口de控制端口
+*/
+void USART_485_DE_init()
+{
+	GPIO_InitTypeDef GPIO_InitStruct;
+	RCC_AHB1PeriphClockCmd(USART_485_DE_GPIO_CLK, ENABLE);
+	GPIO_InitStruct.GPIO_Pin = USART_485_DE_PIN; 
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(USART_485_DE_GPIO_PORT, &GPIO_InitStruct);
+
+}
+void USART_485_DE_TX()
+{
+	GPIO_WriteBit(USART_485_DE_GPIO_PORT,USART_485_DE_PIN,1);
+}
+void USART_485_DE_RX()
+{
+	GPIO_WriteBit(USART_485_DE_GPIO_PORT,USART_485_DE_PIN,0);
+}
+void USART_485_Send(uint8_t *message,uint16_t size)
+{
+	uint16_t i=0;
+	USART_485_DE_TX();
+	for(i=0;i<size;i++)
+	{
+		USART_SendData(USART_232,*(message+i));
+		while (USART_GetFlagStatus(USART_232, USART_FLAG_TC) == RESET);
+	}
+	USART_485_DE_RX();
+}
+//void _485_Config(void)
+//{
+//	GPIO_InitTypeDef GPIO_InitStructure;
+//	USART_InitTypeDef USART_InitStructure;
+
+//	/* config USART clock */
+//	RCC_AHB1PeriphClockCmd(_485_USART_RX_GPIO_CLK|_485_USART_TX_GPIO_CLK|_485_RE_GPIO_CLK, ENABLE);
+//	RCC_APB1PeriphClockCmd(_485_USART_CLK, ENABLE); 
+
+//	
+//	  /* Connect PXx to USARTx_Tx*/
+//  GPIO_PinAFConfig(_485_USART_RX_GPIO_PORT,_485_USART_RX_SOURCE, _485_USART_RX_AF);
+
+//  /* Connect PXx to USARTx_Rx*/
+//  GPIO_PinAFConfig(_485_USART_TX_GPIO_PORT,_485_USART_TX_SOURCE,_485_USART_TX_AF);
+
+//	
+//	/* USART GPIO config */
+//   /* Configure USART Tx as alternate function push-pull */
+//  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+//  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+
+//  GPIO_InitStructure.GPIO_Pin = _485_USART_TX_PIN  ;
+//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+//  GPIO_Init(_485_USART_TX_GPIO_PORT, &GPIO_InitStructure);
+
+//  /* Configure USART Rx as alternate function  */
+//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
+//	GPIO_InitStructure.GPIO_Pin = _485_USART_RX_PIN;
+//  GPIO_Init(_485_USART_RX_GPIO_PORT, &GPIO_InitStructure);
+
+//  
+//  /* 485收发控制管脚 */
+//  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+//  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+//  GPIO_InitStructure.GPIO_Pin = _485_RE_PIN  ;
+//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+//  GPIO_Init(_485_RE_GPIO_PORT, &GPIO_InitStructure);
+//	  
+//	/* USART mode config */
+//	USART_InitStructure.USART_BaudRate = _485_USART_BAUDRATE;
+//	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
+//	USART_InitStructure.USART_StopBits = USART_StopBits_1;
+//	USART_InitStructure.USART_Parity = USART_Parity_No ;
+//	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+//	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+
+//	USART_Init(_485_USART, &USART_InitStructure); 
+//  USART_Cmd(_485_USART, ENABLE);
+//	
+//	NVIC_Configuration();
+//	/* 使能串口接收中断 */
+//	USART_ITConfig(_485_USART, USART_IT_RXNE, ENABLE);
+//	
+//	GPIO_ResetBits(_485_RE_GPIO_PORT,_485_RE_PIN); //默认进入接收模式
+//}
+
+/*
+	485串口在未配置情况下,初始化的参数
+*/
+void USART_485_config()
+{
+
+	USART_485_DE_init();
+	USART_InitTypeDef USART_InitStruct;
+  GPIO_InitTypeDef GPIO_InitStruct;
+
+	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
+	
+	GPIO_PinAFConfig(USART_485_RX_GPIO_PORT, USART_485_RX_SOURCE, USART_485_RX_AF);
+  GPIO_PinAFConfig(USART_485_TX_GPIO_PORT, USART_485_TX_SOURCE, USART_485_TX_AF);
+	
+  GPIO_InitStruct.GPIO_Pin = USART_485_TX_PIN ;
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(GPIOC, &GPIO_InitStruct);
+	
+  GPIO_InitStruct.GPIO_Pin = USART_485_RX_PIN;
+	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+	GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+	
+  USART_InitStruct.USART_BaudRate = USART_485_BAUDRATE;
+  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
+  USART_InitStruct.USART_StopBits = USART_StopBits_1;
+  USART_InitStruct.USART_Parity = USART_Parity_No;
+  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  USART_Init(USART_485, &USART_InitStruct);
+
+  USART_Cmd(USART_485, ENABLE);
+	
+	USART_ClearFlag(USART_485, USART_FLAG_TC);
+	USART_ITConfig(USART_485,USART_IT_RXNE,ENABLE);
+	USART_ITConfig(USART_485,USART_IT_IDLE,ENABLE);
+	
+	NVIC_InitTypeDef NVIC_InitStruct;
+	NVIC_InitStruct.NVIC_IRQChannel = USART_485_IRQ;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+	NVIC_Init(&NVIC_InitStruct);
+}
+/*
+ *  函数名:void Config_485_Port(uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity, uint8_t flowcontrol)
+ *  输入参数:baudrate,databits,stopbits,parity,flowcontol 串口的配置参数
+ *  输出参数:无
+ *  返回值:无
+ *  函数作用:根据输入参数进行配置485串口参数
+ */
+
+void Config_485_Port(uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity, uint8_t flowcontrol)
+{
+	uint8_t wordLength;
+	if(parity!=0)
+	{
+		wordLength=databits+1;
+  }else wordLength=databits;
+	USART_InitTypeDef USART_InitStruct;
+  GPIO_InitTypeDef GPIO_InitStruct;
+
+  RCC_AHB1PeriphClockCmd(USART_485_CLK, ENABLE);
+
+  RCC_APB2PeriphClockCmd(USART_485_RX_GPIO_CLK, ENABLE);
+
+  GPIO_InitStruct.GPIO_Pin = USART_485_RX_PIN | USART_485_TX_PIN; 
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+  GPIO_PinAFConfig(USART_485_RX_GPIO_PORT, USART_485_RX_SOURCE, USART_485_RX_AF);
+  GPIO_PinAFConfig(USART_485_TX_GPIO_PORT, USART_485_TX_SOURCE, USART_485_TX_AF);
+
+  USART_InitStruct.USART_BaudRate = baudrate;
+  USART_InitStruct.USART_WordLength = (wordLength== 9) ? USART_WordLength_9b : USART_WordLength_8b;
+  USART_InitStruct.USART_StopBits = USART_StopBits_1;
+  USART_InitStruct.USART_Parity = USART_Parity_No;
+	USART_InitStruct.USART_Parity =(parity == 1) ? (USART_Parity_Odd) : (parity == 2 ? USART_Parity_Even : USART_Parity_No);
+	
+  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  USART_Init(USART_485, &USART_InitStruct);
+
+  USART_Cmd(USART_485, ENABLE);
+	USART_ClearFlag(USART1, USART_FLAG_TC);
+	USART_ITConfig(USART_485,USART_IT_RXNE,ENABLE);
+	USART_ITConfig(USART_485,USART_IT_IDLE,ENABLE);
+	
+	 // 配置485接收中断优先级
+	NVIC_InitTypeDef NVIC_InitStruct;
+	NVIC_InitStruct.NVIC_IRQChannel = USART_485_IRQ;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+	NVIC_Init(&NVIC_InitStruct);
+	
+}
+/*
+	232串口配置
+*/
+
+void USART_232_config()
+{
+	USART_InitTypeDef USART_InitStruct;
+  GPIO_InitTypeDef GPIO_InitStruct;
+	
+  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+	
+	GPIO_PinAFConfig(USART_232_RX_GPIO_PORT, USART_232_RX_SOURCE, USART_232_RX_AF);
+  GPIO_PinAFConfig(USART_232_TX_GPIO_PORT, USART_232_TX_SOURCE, USART_232_TX_AF);
+	
+	
+  GPIO_InitStruct.GPIO_Pin = USART_232_RX_PIN | USART_232_TX_PIN; 
+  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
+  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(GPIOA, &GPIO_InitStruct);
+	
+
+
+
+  USART_InitStruct.USART_BaudRate = USART_232_BAUDRATE;
+  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
+  USART_InitStruct.USART_StopBits = USART_StopBits_1;
+  USART_InitStruct.USART_Parity = USART_Parity_No;
+  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  USART_Init(USART_232, &USART_InitStruct);
+	
+  USART_Cmd(USART_232, ENABLE);
+	
+	USART_ClearFlag(USART1, USART_FLAG_TC);
+	
+	USART_ITConfig(USART_232,USART_IT_RXNE,ENABLE);
+	USART_ITConfig(USART_232,USART_IT_IDLE,ENABLE);
+	
+ // 配置USART1接收中断优先级
+	NVIC_InitTypeDef NVIC_InitStruct;
+	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+	NVIC_Init(&NVIC_InitStruct);
+	
+	
+}
+
+/*****************  发送一个字符 **********************/
+void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
+{
+	/* 发送一个字节数据到USART */
+	USART_SendData(pUSARTx,ch);
+		
+	/* 等待发送数据寄存器为空 */
+	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
+}
+
+
+/*****************  发送字符串 **********************/
+void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
+{
+	unsigned int k=0;
+  do 
+  {
+      Usart_SendByte( pUSARTx, *(str + k) );
+      k++;
+  } while(*(str + k)!='\0');
+  
+  /* 等待发送完成 */
+  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
+  {}
+}
+/*****************  输出Hex字符串可能包含0x00**********************/
+void Usart_SendHex( USART_TypeDef * pUSARTx, uint8_t *str,uint16_t hexLength)
+{
+	unsigned int k=0;
+	do 
+  {
+      Usart_SendByte( pUSARTx, *(str + k) );
+      k++;
+  } while(k==hexLength);
+  
+  /* 等待发送完成 */
+  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
+  {}
+}
+/*****************  发送一个16位数 **********************/
+void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
+{
+	uint8_t temp_h, temp_l;
+	
+	/* 取出高八位 */
+	temp_h = (ch&0XFF00)>>8;
+	/* 取出低八位 */
+	temp_l = ch&0XFF;
+	
+	/* 发送高八位 */
+	USART_SendData(pUSARTx,temp_h);	
+	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
+	
+	/* 发送低八位 */
+	USART_SendData(pUSARTx,temp_l);	
+	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
+}
+
+
+/*********************************************END OF FILE**********************/

+ 170 - 0
app/Libraries/inc/misc.h

@@ -0,0 +1,170 @@
+/**
+  ******************************************************************************
+  * @file    misc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the miscellaneous
+  *          firmware library functions (add-on to CMSIS functions).
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MISC_H
+#define __MISC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup MISC
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  NVIC Init Structure definition  
+  */
+
+typedef struct
+{
+  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
+                                                   This parameter can be an enumerator of @ref IRQn_Type 
+                                                   enumeration (For the complete STM32 Devices IRQ Channels
+                                                   list, please refer to stm32f2xx.h file) */
+
+  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
+                                                   specified in NVIC_IRQChannel. This parameter can be a value
+                                                   between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
+                                                   A lower priority value indicates a higher priority */
+
+  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
+                                                   in NVIC_IRQChannel. This parameter can be a value
+                                                   between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
+                                                   A lower priority value indicates a higher priority */
+
+  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
+                                                   will be enabled or disabled. 
+                                                   This parameter can be set either to ENABLE or DISABLE */   
+} NVIC_InitTypeDef;
+ 
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup MISC_Exported_Constants
+  * @{
+  */
+
+/** @defgroup MISC_Vector_Table_Base 
+  * @{
+  */
+
+#define NVIC_VectTab_RAM             ((uint32_t)0x20000000)
+#define NVIC_VectTab_FLASH           ((uint32_t)0x08000000)
+#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \
+                                  ((VECTTAB) == NVIC_VectTab_FLASH))
+/**
+  * @}
+  */
+
+/** @defgroup MISC_System_Low_Power 
+  * @{
+  */
+
+#define NVIC_LP_SEVONPEND            ((uint8_t)0x10)
+#define NVIC_LP_SLEEPDEEP            ((uint8_t)0x04)
+#define NVIC_LP_SLEEPONEXIT          ((uint8_t)0x02)
+#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \
+                        ((LP) == NVIC_LP_SLEEPDEEP) || \
+                        ((LP) == NVIC_LP_SLEEPONEXIT))
+/**
+  * @}
+  */
+
+/** @defgroup MISC_Preemption_Priority_Group 
+  * @{
+  */
+
+#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
+                                                            4 bits for subpriority */
+#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
+                                                            3 bits for subpriority */
+#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
+                                                            2 bits for subpriority */
+#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
+                                                            1 bits for subpriority */
+#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
+                                                            0 bits for subpriority */
+
+#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
+                                       ((GROUP) == NVIC_PriorityGroup_1) || \
+                                       ((GROUP) == NVIC_PriorityGroup_2) || \
+                                       ((GROUP) == NVIC_PriorityGroup_3) || \
+                                       ((GROUP) == NVIC_PriorityGroup_4))
+
+#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY)  ((PRIORITY) < 0x10)
+
+#define IS_NVIC_SUB_PRIORITY(PRIORITY)  ((PRIORITY) < 0x10)
+
+#define IS_NVIC_OFFSET(OFFSET)  ((OFFSET) < 0x000FFFFF)
+
+/**
+  * @}
+  */
+
+/** @defgroup MISC_SysTick_clock_source 
+  * @{
+  */
+
+#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
+#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
+#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
+                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
+void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
+void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
+void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
+void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MISC_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1884 - 0
app/Libraries/inc/stm32f2x7_eth.h


+ 98 - 0
app/Libraries/inc/stm32f2x7_eth_conf.h

@@ -0,0 +1,98 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2x7_eth_conf.h
+  * @author  MCD Application Team
+  * @version V1.1.0
+  * @date    07-October-2011
+  * @brief   Configuration file for the STM32F2x7 Ethernet driver.  
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2x7_ETH_CONF_H
+#define __STM32F2x7_ETH_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* Uncomment the line below when using time stamping and/or IPv4 checksum offload */
+//#define USE_ENHANCED_DMA_DESCRIPTORS
+
+/* Uncomment the line below if you want to use user defined Delay function
+   (for precise timing), otherwise default _eth_delay_ function defined within
+   the Ethernet driver is used (less precise timing) */
+//#define USE_Delay
+
+#ifdef USE_Delay
+  #include "main.h"                /* Header file where the Delay function prototype is exported */  
+  #define _eth_delay_    Delay     /* User can provide more timing precise _eth_delay_ function */
+#else
+
+#define PHY_RESET_DELAY    ((uint32_t)0x000FFFFF)
+/* PHY Configuration delay */ 
+#define PHY_CONFIG_DELAY   ((uint32_t)0x00FFFFFF)
+/* Delay when writing to Ethernet registers*/
+#define ETH_REG_WRITE_DELAY ((uint32_t)0x0000FFFF)
+void ETH_Delay(__IO uint32_t nCount);
+  #define _eth_delay_    ETH_Delay /* Default _eth_delay_ function with less precise timing */
+#endif
+
+
+/* Uncomment the line below to allow custom configuration of the Ethernet driver buffers */    
+//#define CUSTOM_DRIVER_BUFFERS_CONFIG   
+
+#ifdef  CUSTOM_DRIVER_BUFFERS_CONFIG
+/* Redefinition of the Ethernet driver buffers size and count */   
+ #define ETH_RX_BUF_SIZE    ETH_MAX_PACKET_SIZE /* buffer size for receive */
+ #define ETH_TX_BUF_SIZE    ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+ #define ETH_RXBUFNB        20                  /* 20 Rx buffers of size ETH_RX_BUF_SIZE */
+ #define ETH_TXBUFNB        5                   /* 5  Tx buffers of size ETH_TX_BUF_SIZE */
+#endif
+
+
+/* PHY configuration section **************************************************/
+/* PHY Reset delay */ 
+#define PHY_RESET_DELAY    ((uint32_t)0x000FFFFF) 
+/* PHY Configuration delay */ 
+#define PHY_CONFIG_DELAY   ((uint32_t)0x00FFFFFF)
+
+/* The PHY status register value change from a PHY to another, so the user have 
+   to update this value depending on the used external PHY */
+#define PHY_SR    ((uint16_t)16) /* Value for DP83848 PHY */
+
+/* The Speed and Duplex mask values change from a PHY to another, so the user
+   have to update this value depending on the used external PHY */
+#define PHY_SPEED_STATUS            ((uint16_t)0x0002) /* Value for DP83848 PHY */
+#define PHY_DUPLEX_STATUS           ((uint16_t)0x0004) /* Value for DP83848 PHY */
+
+   
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */  
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2x7_ETH_CONF_H */
+
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
+

+ 641 - 0
app/Libraries/inc/stm32f2xx_adc.h

@@ -0,0 +1,641 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_adc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the ADC firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_ADC_H
+#define __STM32F2xx_ADC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup ADC
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief   ADC Init structure definition  
+  */ 
+typedef struct
+{
+  uint32_t ADC_Resolution;                /*!< Configures the ADC resolution dual mode. 
+                                               This parameter can be a value of @ref ADC_resolution */                                   
+  FunctionalState ADC_ScanConvMode;       /*!< Specifies whether the conversion 
+                                               is performed in Scan (multichannels) 
+                                               or Single (one channel) mode.
+                                               This parameter can be set to ENABLE or DISABLE */ 
+  FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion 
+                                               is performed in Continuous or Single mode.
+                                               This parameter can be set to ENABLE or DISABLE. */
+  uint32_t ADC_ExternalTrigConvEdge;      /*!< Select the external trigger edge and
+                                               enable the trigger of a regular group. 
+                                               This parameter can be a value of 
+                                               @ref ADC_external_trigger_edge_for_regular_channels_conversion */
+  uint32_t ADC_ExternalTrigConv;          /*!< Select the external event used to trigger 
+                                               the start of conversion of a regular group.
+                                               This parameter can be a value of 
+                                               @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */
+  uint32_t ADC_DataAlign;                 /*!< Specifies whether the ADC data  alignment
+                                               is left or right. This parameter can be 
+                                               a value of @ref ADC_data_align */
+  uint8_t  ADC_NbrOfConversion;           /*!< Specifies the number of ADC conversions
+                                               that will be done using the sequencer for
+                                               regular channel group.
+                                               This parameter must range from 1 to 16. */
+}ADC_InitTypeDef;
+  
+/** 
+  * @brief   ADC Common Init structure definition  
+  */ 
+typedef struct 
+{
+  uint32_t ADC_Mode;                      /*!< Configures the ADC to operate in 
+                                               independent or multi mode. 
+                                               This parameter can be a value of @ref ADC_Common_mode */                                              
+  uint32_t ADC_Prescaler;                 /*!< Select the frequency of the clock 
+                                               to the ADC. The clock is common for all the ADCs.
+                                               This parameter can be a value of @ref ADC_Prescaler */
+  uint32_t ADC_DMAAccessMode;             /*!< Configures the Direct memory access 
+                                              mode for multi ADC mode.
+                                               This parameter can be a value of 
+                                               @ref ADC_Direct_memory_access_mode_for_multi_mode */
+  uint32_t ADC_TwoSamplingDelay;          /*!< Configures the Delay between 2 sampling phases.
+                                               This parameter can be a value of 
+                                               @ref ADC_delay_between_2_sampling_phases */
+  
+}ADC_CommonInitTypeDef;
+
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Constants
+  * @{
+  */ 
+#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \
+                                   ((PERIPH) == ADC2) || \
+                                   ((PERIPH) == ADC3))  
+
+/** @defgroup ADC_Common_mode 
+  * @{
+  */ 
+#define ADC_Mode_Independent                       ((uint32_t)0x00000000)       
+#define ADC_DualMode_RegSimult_InjecSimult         ((uint32_t)0x00000001)
+#define ADC_DualMode_RegSimult_AlterTrig           ((uint32_t)0x00000002)
+#define ADC_DualMode_InjecSimult                   ((uint32_t)0x00000005)
+#define ADC_DualMode_RegSimult                     ((uint32_t)0x00000006)
+#define ADC_DualMode_Interl                        ((uint32_t)0x00000007)
+#define ADC_DualMode_AlterTrig                     ((uint32_t)0x00000009)
+#define ADC_TripleMode_RegSimult_InjecSimult       ((uint32_t)0x00000011)
+#define ADC_TripleMode_RegSimult_AlterTrig         ((uint32_t)0x00000012)
+#define ADC_TripleMode_InjecSimult                 ((uint32_t)0x00000015)
+#define ADC_TripleMode_RegSimult                   ((uint32_t)0x00000016)
+#define ADC_TripleMode_Interl                      ((uint32_t)0x00000017)
+#define ADC_TripleMode_AlterTrig                   ((uint32_t)0x00000019)
+#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \
+                           ((MODE) == ADC_DualMode_RegSimult_InjecSimult) || \
+                           ((MODE) == ADC_DualMode_RegSimult_AlterTrig) || \
+                           ((MODE) == ADC_DualMode_InjecSimult) || \
+                           ((MODE) == ADC_DualMode_RegSimult) || \
+                           ((MODE) == ADC_DualMode_Interl) || \
+                           ((MODE) == ADC_DualMode_AlterTrig) || \
+                           ((MODE) == ADC_TripleMode_RegSimult_InjecSimult) || \
+                           ((MODE) == ADC_TripleMode_RegSimult_AlterTrig) || \
+                           ((MODE) == ADC_TripleMode_InjecSimult) || \
+                           ((MODE) == ADC_TripleMode_RegSimult) || \
+                           ((MODE) == ADC_TripleMode_Interl) || \
+                           ((MODE) == ADC_TripleMode_AlterTrig))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_Prescaler 
+  * @{
+  */ 
+#define ADC_Prescaler_Div2                         ((uint32_t)0x00000000)
+#define ADC_Prescaler_Div4                         ((uint32_t)0x00010000)
+#define ADC_Prescaler_Div6                         ((uint32_t)0x00020000)
+#define ADC_Prescaler_Div8                         ((uint32_t)0x00030000)
+#define IS_ADC_PRESCALER(PRESCALER) (((PRESCALER) == ADC_Prescaler_Div2) || \
+                                     ((PRESCALER) == ADC_Prescaler_Div4) || \
+                                     ((PRESCALER) == ADC_Prescaler_Div6) || \
+                                     ((PRESCALER) == ADC_Prescaler_Div8))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_Direct_memory_access_mode_for_multi_mode 
+  * @{
+  */ 
+#define ADC_DMAAccessMode_Disabled      ((uint32_t)0x00000000)     /* DMA mode disabled */
+#define ADC_DMAAccessMode_1             ((uint32_t)0x00004000)     /* DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)*/
+#define ADC_DMAAccessMode_2             ((uint32_t)0x00008000)     /* DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)*/
+#define ADC_DMAAccessMode_3             ((uint32_t)0x0000C000)     /* DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2) */
+#define IS_ADC_DMA_ACCESS_MODE(MODE) (((MODE) == ADC_DMAAccessMode_Disabled) || \
+                                      ((MODE) == ADC_DMAAccessMode_1) || \
+                                      ((MODE) == ADC_DMAAccessMode_2) || \
+                                      ((MODE) == ADC_DMAAccessMode_3))
+                                     
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_delay_between_2_sampling_phases 
+  * @{
+  */ 
+#define ADC_TwoSamplingDelay_5Cycles               ((uint32_t)0x00000000)
+#define ADC_TwoSamplingDelay_6Cycles               ((uint32_t)0x00000100)
+#define ADC_TwoSamplingDelay_7Cycles               ((uint32_t)0x00000200)
+#define ADC_TwoSamplingDelay_8Cycles               ((uint32_t)0x00000300)
+#define ADC_TwoSamplingDelay_9Cycles               ((uint32_t)0x00000400)
+#define ADC_TwoSamplingDelay_10Cycles              ((uint32_t)0x00000500)
+#define ADC_TwoSamplingDelay_11Cycles              ((uint32_t)0x00000600)
+#define ADC_TwoSamplingDelay_12Cycles              ((uint32_t)0x00000700)
+#define ADC_TwoSamplingDelay_13Cycles              ((uint32_t)0x00000800)
+#define ADC_TwoSamplingDelay_14Cycles              ((uint32_t)0x00000900)
+#define ADC_TwoSamplingDelay_15Cycles              ((uint32_t)0x00000A00)
+#define ADC_TwoSamplingDelay_16Cycles              ((uint32_t)0x00000B00)
+#define ADC_TwoSamplingDelay_17Cycles              ((uint32_t)0x00000C00)
+#define ADC_TwoSamplingDelay_18Cycles              ((uint32_t)0x00000D00)
+#define ADC_TwoSamplingDelay_19Cycles              ((uint32_t)0x00000E00)
+#define ADC_TwoSamplingDelay_20Cycles              ((uint32_t)0x00000F00)
+#define IS_ADC_SAMPLING_DELAY(DELAY) (((DELAY) == ADC_TwoSamplingDelay_5Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_6Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_7Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_8Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_9Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_10Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_11Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_12Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_13Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_14Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_15Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_16Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_17Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_18Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_19Cycles) || \
+                                      ((DELAY) == ADC_TwoSamplingDelay_20Cycles))
+                                     
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_resolution 
+  * @{
+  */ 
+#define ADC_Resolution_12b                         ((uint32_t)0x00000000)
+#define ADC_Resolution_10b                         ((uint32_t)0x01000000)
+#define ADC_Resolution_8b                          ((uint32_t)0x02000000)
+#define ADC_Resolution_6b                          ((uint32_t)0x03000000)
+#define IS_ADC_RESOLUTION(RESOLUTION) (((RESOLUTION) == ADC_Resolution_12b) || \
+                                       ((RESOLUTION) == ADC_Resolution_10b) || \
+                                       ((RESOLUTION) == ADC_Resolution_8b) || \
+                                       ((RESOLUTION) == ADC_Resolution_6b))
+                                      
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_external_trigger_edge_for_regular_channels_conversion 
+  * @{
+  */ 
+#define ADC_ExternalTrigConvEdge_None          ((uint32_t)0x00000000)
+#define ADC_ExternalTrigConvEdge_Rising        ((uint32_t)0x10000000)
+#define ADC_ExternalTrigConvEdge_Falling       ((uint32_t)0x20000000)
+#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000)
+#define IS_ADC_EXT_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigConvEdge_None) || \
+                             ((EDGE) == ADC_ExternalTrigConvEdge_Rising) || \
+                             ((EDGE) == ADC_ExternalTrigConvEdge_Falling) || \
+                             ((EDGE) == ADC_ExternalTrigConvEdge_RisingFalling))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion 
+  * @{
+  */ 
+#define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000)
+#define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x01000000)
+#define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x02000000)
+#define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x03000000)
+#define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x04000000)
+#define ADC_ExternalTrigConv_T2_CC4                ((uint32_t)0x05000000)
+#define ADC_ExternalTrigConv_T2_TRGO               ((uint32_t)0x06000000)
+#define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x07000000)
+#define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x08000000)
+#define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x09000000)
+#define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x0A000000)
+#define ADC_ExternalTrigConv_T5_CC2                ((uint32_t)0x0B000000)
+#define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x0C000000)
+#define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x0D000000)
+#define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x0E000000)
+#define ADC_ExternalTrigConv_Ext_IT11              ((uint32_t)0x0F000000)
+#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_ExternalTrigConv_T1_CC1) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T1_CC2) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T1_CC3) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T2_CC2) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T2_CC3) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T2_CC4) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T2_TRGO) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T3_CC1) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T3_TRGO) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T4_CC4) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T5_CC1) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T5_CC2) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T5_CC3) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T8_CC1) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_T8_TRGO) || \
+                                  ((REGTRIG) == ADC_ExternalTrigConv_Ext_IT11))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_data_align 
+  * @{
+  */ 
+#define ADC_DataAlign_Right                        ((uint32_t)0x00000000)
+#define ADC_DataAlign_Left                         ((uint32_t)0x00000800)
+#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DataAlign_Right) || \
+                                  ((ALIGN) == ADC_DataAlign_Left))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_channels 
+  * @{
+  */ 
+#define ADC_Channel_0                               ((uint8_t)0x00)
+#define ADC_Channel_1                               ((uint8_t)0x01)
+#define ADC_Channel_2                               ((uint8_t)0x02)
+#define ADC_Channel_3                               ((uint8_t)0x03)
+#define ADC_Channel_4                               ((uint8_t)0x04)
+#define ADC_Channel_5                               ((uint8_t)0x05)
+#define ADC_Channel_6                               ((uint8_t)0x06)
+#define ADC_Channel_7                               ((uint8_t)0x07)
+#define ADC_Channel_8                               ((uint8_t)0x08)
+#define ADC_Channel_9                               ((uint8_t)0x09)
+#define ADC_Channel_10                              ((uint8_t)0x0A)
+#define ADC_Channel_11                              ((uint8_t)0x0B)
+#define ADC_Channel_12                              ((uint8_t)0x0C)
+#define ADC_Channel_13                              ((uint8_t)0x0D)
+#define ADC_Channel_14                              ((uint8_t)0x0E)
+#define ADC_Channel_15                              ((uint8_t)0x0F)
+#define ADC_Channel_16                              ((uint8_t)0x10)
+#define ADC_Channel_17                              ((uint8_t)0x11)
+#define ADC_Channel_18                              ((uint8_t)0x12)
+
+#define ADC_Channel_TempSensor                      ((uint8_t)ADC_Channel_16)
+#define ADC_Channel_Vrefint                         ((uint8_t)ADC_Channel_17)
+#define ADC_Channel_Vbat                            ((uint8_t)ADC_Channel_18)
+
+#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || \
+                                 ((CHANNEL) == ADC_Channel_1) || \
+                                 ((CHANNEL) == ADC_Channel_2) || \
+                                 ((CHANNEL) == ADC_Channel_3) || \
+                                 ((CHANNEL) == ADC_Channel_4) || \
+                                 ((CHANNEL) == ADC_Channel_5) || \
+                                 ((CHANNEL) == ADC_Channel_6) || \
+                                 ((CHANNEL) == ADC_Channel_7) || \
+                                 ((CHANNEL) == ADC_Channel_8) || \
+                                 ((CHANNEL) == ADC_Channel_9) || \
+                                 ((CHANNEL) == ADC_Channel_10) || \
+                                 ((CHANNEL) == ADC_Channel_11) || \
+                                 ((CHANNEL) == ADC_Channel_12) || \
+                                 ((CHANNEL) == ADC_Channel_13) || \
+                                 ((CHANNEL) == ADC_Channel_14) || \
+                                 ((CHANNEL) == ADC_Channel_15) || \
+                                 ((CHANNEL) == ADC_Channel_16) || \
+                                 ((CHANNEL) == ADC_Channel_17) || \
+                                 ((CHANNEL) == ADC_Channel_18))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_sampling_times 
+  * @{
+  */ 
+#define ADC_SampleTime_3Cycles                    ((uint8_t)0x00)
+#define ADC_SampleTime_15Cycles                   ((uint8_t)0x01)
+#define ADC_SampleTime_28Cycles                   ((uint8_t)0x02)
+#define ADC_SampleTime_56Cycles                   ((uint8_t)0x03)
+#define ADC_SampleTime_84Cycles                   ((uint8_t)0x04)
+#define ADC_SampleTime_112Cycles                  ((uint8_t)0x05)
+#define ADC_SampleTime_144Cycles                  ((uint8_t)0x06)
+#define ADC_SampleTime_480Cycles                  ((uint8_t)0x07)
+#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_3Cycles) || \
+                                  ((TIME) == ADC_SampleTime_15Cycles) || \
+                                  ((TIME) == ADC_SampleTime_28Cycles) || \
+                                  ((TIME) == ADC_SampleTime_56Cycles) || \
+                                  ((TIME) == ADC_SampleTime_84Cycles) || \
+                                  ((TIME) == ADC_SampleTime_112Cycles) || \
+                                  ((TIME) == ADC_SampleTime_144Cycles) || \
+                                  ((TIME) == ADC_SampleTime_480Cycles))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_external_trigger_edge_for_injected_channels_conversion 
+  * @{
+  */ 
+#define ADC_ExternalTrigInjecConvEdge_None          ((uint32_t)0x00000000)
+#define ADC_ExternalTrigInjecConvEdge_Rising        ((uint32_t)0x00100000)
+#define ADC_ExternalTrigInjecConvEdge_Falling       ((uint32_t)0x00200000)
+#define ADC_ExternalTrigInjecConvEdge_RisingFalling ((uint32_t)0x00300000)
+#define IS_ADC_EXT_INJEC_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigInjecConvEdge_None) || \
+                                          ((EDGE) == ADC_ExternalTrigInjecConvEdge_Rising) || \
+                                          ((EDGE) == ADC_ExternalTrigInjecConvEdge_Falling) || \
+                                          ((EDGE) == ADC_ExternalTrigInjecConvEdge_RisingFalling))
+                                            
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_extrenal_trigger_sources_for_injected_channels_conversion 
+  * @{
+  */ 
+#define ADC_ExternalTrigInjecConv_T1_CC4            ((uint32_t)0x00000000)
+#define ADC_ExternalTrigInjecConv_T1_TRGO           ((uint32_t)0x00010000)
+#define ADC_ExternalTrigInjecConv_T2_CC1            ((uint32_t)0x00020000)
+#define ADC_ExternalTrigInjecConv_T2_TRGO           ((uint32_t)0x00030000)
+#define ADC_ExternalTrigInjecConv_T3_CC2            ((uint32_t)0x00040000)
+#define ADC_ExternalTrigInjecConv_T3_CC4            ((uint32_t)0x00050000)
+#define ADC_ExternalTrigInjecConv_T4_CC1            ((uint32_t)0x00060000)
+#define ADC_ExternalTrigInjecConv_T4_CC2            ((uint32_t)0x00070000)
+#define ADC_ExternalTrigInjecConv_T4_CC3            ((uint32_t)0x00080000)
+#define ADC_ExternalTrigInjecConv_T4_TRGO           ((uint32_t)0x00090000)
+#define ADC_ExternalTrigInjecConv_T5_CC4            ((uint32_t)0x000A0000)
+#define ADC_ExternalTrigInjecConv_T5_TRGO           ((uint32_t)0x000B0000)
+#define ADC_ExternalTrigInjecConv_T8_CC2            ((uint32_t)0x000C0000)
+#define ADC_ExternalTrigInjecConv_T8_CC3            ((uint32_t)0x000D0000)
+#define ADC_ExternalTrigInjecConv_T8_CC4            ((uint32_t)0x000E0000)
+#define ADC_ExternalTrigInjecConv_Ext_IT15          ((uint32_t)0x000F0000)
+#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_ExternalTrigInjecConv_T1_CC4) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T1_TRGO) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_CC1) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_TRGO) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC2) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC4) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC1) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC2) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC3) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_TRGO) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_CC4) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_TRGO) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC2) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC3) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC4) || \
+                                        ((INJTRIG) == ADC_ExternalTrigInjecConv_Ext_IT15))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_injected_channel_selection 
+  * @{
+  */ 
+#define ADC_InjectedChannel_1                       ((uint8_t)0x14)
+#define ADC_InjectedChannel_2                       ((uint8_t)0x18)
+#define ADC_InjectedChannel_3                       ((uint8_t)0x1C)
+#define ADC_InjectedChannel_4                       ((uint8_t)0x20)
+#define IS_ADC_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) == ADC_InjectedChannel_1) || \
+                                          ((CHANNEL) == ADC_InjectedChannel_2) || \
+                                          ((CHANNEL) == ADC_InjectedChannel_3) || \
+                                          ((CHANNEL) == ADC_InjectedChannel_4))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_analog_watchdog_selection 
+  * @{
+  */ 
+#define ADC_AnalogWatchdog_SingleRegEnable         ((uint32_t)0x00800200)
+#define ADC_AnalogWatchdog_SingleInjecEnable       ((uint32_t)0x00400200)
+#define ADC_AnalogWatchdog_SingleRegOrInjecEnable  ((uint32_t)0x00C00200)
+#define ADC_AnalogWatchdog_AllRegEnable            ((uint32_t)0x00800000)
+#define ADC_AnalogWatchdog_AllInjecEnable          ((uint32_t)0x00400000)
+#define ADC_AnalogWatchdog_AllRegAllInjecEnable    ((uint32_t)0x00C00000)
+#define ADC_AnalogWatchdog_None                    ((uint32_t)0x00000000)
+#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_AnalogWatchdog_SingleRegEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_SingleInjecEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_SingleRegOrInjecEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_AllRegEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_AllInjecEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_AllRegAllInjecEnable) || \
+                                          ((WATCHDOG) == ADC_AnalogWatchdog_None))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_interrupts_definition 
+  * @{
+  */ 
+#define ADC_IT_EOC                                 ((uint16_t)0x0205)  
+#define ADC_IT_AWD                                 ((uint16_t)0x0106)  
+#define ADC_IT_JEOC                                ((uint16_t)0x0407)  
+#define ADC_IT_OVR                                 ((uint16_t)0x201A)  
+#define IS_ADC_IT(IT) (((IT) == ADC_IT_EOC) || ((IT) == ADC_IT_AWD) || \
+                       ((IT) == ADC_IT_JEOC)|| ((IT) == ADC_IT_OVR)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_flags_definition 
+  * @{
+  */ 
+#define ADC_FLAG_AWD                               ((uint8_t)0x01)
+#define ADC_FLAG_EOC                               ((uint8_t)0x02)
+#define ADC_FLAG_JEOC                              ((uint8_t)0x04)
+#define ADC_FLAG_JSTRT                             ((uint8_t)0x08)
+#define ADC_FLAG_STRT                              ((uint8_t)0x10)
+#define ADC_FLAG_OVR                               ((uint8_t)0x20)   
+  
+#define IS_ADC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint8_t)0xC0) == 0x00) && ((FLAG) != 0x00))   
+#define IS_ADC_GET_FLAG(FLAG) (((FLAG) == ADC_FLAG_AWD) || \
+                               ((FLAG) == ADC_FLAG_EOC) || \
+                               ((FLAG) == ADC_FLAG_JEOC) || \
+                               ((FLAG)== ADC_FLAG_JSTRT) || \
+                               ((FLAG) == ADC_FLAG_STRT) || \
+                               ((FLAG)== ADC_FLAG_OVR))     
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_thresholds 
+  * @{
+  */ 
+#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFF)
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_injected_offset 
+  * @{
+  */ 
+#define IS_ADC_OFFSET(OFFSET) ((OFFSET) <= 0xFFF)
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_injected_length 
+  * @{
+  */ 
+#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_injected_rank 
+  * @{
+  */ 
+#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_regular_length 
+  * @{
+  */ 
+#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_regular_rank 
+  * @{
+  */ 
+#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup ADC_regular_discontinuous_mode_number 
+  * @{
+  */ 
+#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8))
+/**
+  * @}
+  */ 
+
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+/*  Function used to set the ADC configuration to the default reset state *****/  
+void ADC_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
+void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
+void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
+void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
+void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+
+/* Analog Watchdog configuration functions ************************************/
+void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
+void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold);
+void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
+
+/* Temperature Sensor, Vrefint and VBAT management functions ******************/
+void ADC_TempSensorVrefintCmd(FunctionalState NewState);
+void ADC_VBATCmd(FunctionalState NewState);
+
+/* Regular Channels Configuration functions ***********************************/
+void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
+void ADC_SoftwareStartConv(ADC_TypeDef* ADCx);
+FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
+void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
+void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
+uint32_t ADC_GetMultiModeConversionValue(void);
+
+/* Regular Channels DMA Configuration functions *******************************/
+void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState);
+
+/* Injected channels Configuration functions **********************************/
+void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
+void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
+void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
+void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
+void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge);
+void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx);
+FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
+void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
+
+/* Interrupts and flags management functions **********************************/
+void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
+FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
+void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
+ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
+void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_ADC_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 636 - 0
app/Libraries/inc/stm32f2xx_can.h

@@ -0,0 +1,636 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_can.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the CAN firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_CAN_H
+#define __STM32F2xx_CAN_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup CAN
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || \
+                                   ((PERIPH) == CAN2))
+
+/** 
+  * @brief  CAN init structure definition
+  */
+typedef struct
+{
+  uint16_t CAN_Prescaler;   /*!< Specifies the length of a time quantum. 
+                                 It ranges from 1 to 1024. */
+  
+  uint8_t CAN_Mode;         /*!< Specifies the CAN operating mode.
+                                 This parameter can be a value of @ref CAN_operating_mode */
+
+  uint8_t CAN_SJW;          /*!< Specifies the maximum number of time quanta 
+                                 the CAN hardware is allowed to lengthen or 
+                                 shorten a bit to perform resynchronization.
+                                 This parameter can be a value of @ref CAN_synchronisation_jump_width */
+
+  uint8_t CAN_BS1;          /*!< Specifies the number of time quanta in Bit 
+                                 Segment 1. This parameter can be a value of 
+                                 @ref CAN_time_quantum_in_bit_segment_1 */
+
+  uint8_t CAN_BS2;          /*!< Specifies the number of time quanta in Bit Segment 2.
+                                 This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */
+  
+  FunctionalState CAN_TTCM; /*!< Enable or disable the time triggered communication mode.
+                                This parameter can be set either to ENABLE or DISABLE. */
+  
+  FunctionalState CAN_ABOM;  /*!< Enable or disable the automatic bus-off management.
+                                  This parameter can be set either to ENABLE or DISABLE. */
+
+  FunctionalState CAN_AWUM;  /*!< Enable or disable the automatic wake-up mode. 
+                                  This parameter can be set either to ENABLE or DISABLE. */
+
+  FunctionalState CAN_NART;  /*!< Enable or disable the non-automatic retransmission mode.
+                                  This parameter can be set either to ENABLE or DISABLE. */
+
+  FunctionalState CAN_RFLM;  /*!< Enable or disable the Receive FIFO Locked mode.
+                                  This parameter can be set either to ENABLE or DISABLE. */
+
+  FunctionalState CAN_TXFP;  /*!< Enable or disable the transmit FIFO priority.
+                                  This parameter can be set either to ENABLE or DISABLE. */
+} CAN_InitTypeDef;
+
+/** 
+  * @brief  CAN filter init structure definition
+  */
+typedef struct
+{
+  uint16_t CAN_FilterIdHigh;         /*!< Specifies the filter identification number (MSBs for a 32-bit
+                                              configuration, first one for a 16-bit configuration).
+                                              This parameter can be a value between 0x0000 and 0xFFFF */
+
+  uint16_t CAN_FilterIdLow;          /*!< Specifies the filter identification number (LSBs for a 32-bit
+                                              configuration, second one for a 16-bit configuration).
+                                              This parameter can be a value between 0x0000 and 0xFFFF */
+
+  uint16_t CAN_FilterMaskIdHigh;     /*!< Specifies the filter mask number or identification number,
+                                              according to the mode (MSBs for a 32-bit configuration,
+                                              first one for a 16-bit configuration).
+                                              This parameter can be a value between 0x0000 and 0xFFFF */
+
+  uint16_t CAN_FilterMaskIdLow;      /*!< Specifies the filter mask number or identification number,
+                                              according to the mode (LSBs for a 32-bit configuration,
+                                              second one for a 16-bit configuration).
+                                              This parameter can be a value between 0x0000 and 0xFFFF */
+
+  uint16_t CAN_FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter.
+                                              This parameter can be a value of @ref CAN_filter_FIFO */
+  
+  uint8_t CAN_FilterNumber;          /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */
+
+  uint8_t CAN_FilterMode;            /*!< Specifies the filter mode to be initialized.
+                                              This parameter can be a value of @ref CAN_filter_mode */
+
+  uint8_t CAN_FilterScale;           /*!< Specifies the filter scale.
+                                              This parameter can be a value of @ref CAN_filter_scale */
+
+  FunctionalState CAN_FilterActivation; /*!< Enable or disable the filter.
+                                              This parameter can be set either to ENABLE or DISABLE. */
+} CAN_FilterInitTypeDef;
+
+/** 
+  * @brief  CAN Tx message structure definition  
+  */
+typedef struct
+{
+  uint32_t StdId;  /*!< Specifies the standard identifier.
+                        This parameter can be a value between 0 to 0x7FF. */
+
+  uint32_t ExtId;  /*!< Specifies the extended identifier.
+                        This parameter can be a value between 0 to 0x1FFFFFFF. */
+
+  uint8_t IDE;     /*!< Specifies the type of identifier for the message that 
+                        will be transmitted. This parameter can be a value 
+                        of @ref CAN_identifier_type */
+
+  uint8_t RTR;     /*!< Specifies the type of frame for the message that will 
+                        be transmitted. This parameter can be a value of 
+                        @ref CAN_remote_transmission_request */
+
+  uint8_t DLC;     /*!< Specifies the length of the frame that will be 
+                        transmitted. This parameter can be a value between 
+                        0 to 8 */
+
+  uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 
+                        to 0xFF. */
+} CanTxMsg;
+
+/** 
+  * @brief  CAN Rx message structure definition  
+  */
+typedef struct
+{
+  uint32_t StdId;  /*!< Specifies the standard identifier.
+                        This parameter can be a value between 0 to 0x7FF. */
+
+  uint32_t ExtId;  /*!< Specifies the extended identifier.
+                        This parameter can be a value between 0 to 0x1FFFFFFF. */
+
+  uint8_t IDE;     /*!< Specifies the type of identifier for the message that 
+                        will be received. This parameter can be a value of 
+                        @ref CAN_identifier_type */
+
+  uint8_t RTR;     /*!< Specifies the type of frame for the received message.
+                        This parameter can be a value of 
+                        @ref CAN_remote_transmission_request */
+
+  uint8_t DLC;     /*!< Specifies the length of the frame that will be received.
+                        This parameter can be a value between 0 to 8 */
+
+  uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to 
+                        0xFF. */
+
+  uint8_t FMI;     /*!< Specifies the index of the filter the message stored in 
+                        the mailbox passes through. This parameter can be a 
+                        value between 0 to 0xFF */
+} CanRxMsg;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup CAN_Exported_Constants
+  * @{
+  */
+
+/** @defgroup CAN_InitStatus 
+  * @{
+  */
+
+#define CAN_InitStatus_Failed              ((uint8_t)0x00) /*!< CAN initialization failed */
+#define CAN_InitStatus_Success             ((uint8_t)0x01) /*!< CAN initialization OK */
+
+
+/* Legacy defines */
+#define CANINITFAILED    CAN_InitStatus_Failed
+#define CANINITOK        CAN_InitStatus_Success
+/**
+  * @}
+  */
+
+/** @defgroup CAN_operating_mode 
+  * @{
+  */
+
+#define CAN_Mode_Normal             ((uint8_t)0x00)  /*!< normal mode */
+#define CAN_Mode_LoopBack           ((uint8_t)0x01)  /*!< loopback mode */
+#define CAN_Mode_Silent             ((uint8_t)0x02)  /*!< silent mode */
+#define CAN_Mode_Silent_LoopBack    ((uint8_t)0x03)  /*!< loopback combined with silent mode */
+
+#define IS_CAN_MODE(MODE) (((MODE) == CAN_Mode_Normal) || \
+                           ((MODE) == CAN_Mode_LoopBack)|| \
+                           ((MODE) == CAN_Mode_Silent) || \
+                           ((MODE) == CAN_Mode_Silent_LoopBack))
+/**
+  * @}
+  */
+
+
+ /**
+  * @defgroup CAN_operating_mode 
+  * @{
+  */  
+#define CAN_OperatingMode_Initialization  ((uint8_t)0x00) /*!< Initialization mode */
+#define CAN_OperatingMode_Normal          ((uint8_t)0x01) /*!< Normal mode */
+#define CAN_OperatingMode_Sleep           ((uint8_t)0x02) /*!< sleep mode */
+
+
+#define IS_CAN_OPERATING_MODE(MODE) (((MODE) == CAN_OperatingMode_Initialization) ||\
+                                    ((MODE) == CAN_OperatingMode_Normal)|| \
+																		((MODE) == CAN_OperatingMode_Sleep))
+/**
+  * @}
+  */
+  
+/**
+  * @defgroup CAN_operating_mode_status
+  * @{
+  */  
+
+#define CAN_ModeStatus_Failed    ((uint8_t)0x00)                /*!< CAN entering the specific mode failed */
+#define CAN_ModeStatus_Success   ((uint8_t)!CAN_ModeStatus_Failed)   /*!< CAN entering the specific mode Succeed */
+/**
+  * @}
+  */
+
+/** @defgroup CAN_synchronisation_jump_width 
+  * @{
+  */
+#define CAN_SJW_1tq                 ((uint8_t)0x00)  /*!< 1 time quantum */
+#define CAN_SJW_2tq                 ((uint8_t)0x01)  /*!< 2 time quantum */
+#define CAN_SJW_3tq                 ((uint8_t)0x02)  /*!< 3 time quantum */
+#define CAN_SJW_4tq                 ((uint8_t)0x03)  /*!< 4 time quantum */
+
+#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1tq) || ((SJW) == CAN_SJW_2tq)|| \
+                         ((SJW) == CAN_SJW_3tq) || ((SJW) == CAN_SJW_4tq))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_time_quantum_in_bit_segment_1 
+  * @{
+  */
+#define CAN_BS1_1tq                 ((uint8_t)0x00)  /*!< 1 time quantum */
+#define CAN_BS1_2tq                 ((uint8_t)0x01)  /*!< 2 time quantum */
+#define CAN_BS1_3tq                 ((uint8_t)0x02)  /*!< 3 time quantum */
+#define CAN_BS1_4tq                 ((uint8_t)0x03)  /*!< 4 time quantum */
+#define CAN_BS1_5tq                 ((uint8_t)0x04)  /*!< 5 time quantum */
+#define CAN_BS1_6tq                 ((uint8_t)0x05)  /*!< 6 time quantum */
+#define CAN_BS1_7tq                 ((uint8_t)0x06)  /*!< 7 time quantum */
+#define CAN_BS1_8tq                 ((uint8_t)0x07)  /*!< 8 time quantum */
+#define CAN_BS1_9tq                 ((uint8_t)0x08)  /*!< 9 time quantum */
+#define CAN_BS1_10tq                ((uint8_t)0x09)  /*!< 10 time quantum */
+#define CAN_BS1_11tq                ((uint8_t)0x0A)  /*!< 11 time quantum */
+#define CAN_BS1_12tq                ((uint8_t)0x0B)  /*!< 12 time quantum */
+#define CAN_BS1_13tq                ((uint8_t)0x0C)  /*!< 13 time quantum */
+#define CAN_BS1_14tq                ((uint8_t)0x0D)  /*!< 14 time quantum */
+#define CAN_BS1_15tq                ((uint8_t)0x0E)  /*!< 15 time quantum */
+#define CAN_BS1_16tq                ((uint8_t)0x0F)  /*!< 16 time quantum */
+
+#define IS_CAN_BS1(BS1) ((BS1) <= CAN_BS1_16tq)
+/**
+  * @}
+  */
+
+/** @defgroup CAN_time_quantum_in_bit_segment_2 
+  * @{
+  */
+#define CAN_BS2_1tq                 ((uint8_t)0x00)  /*!< 1 time quantum */
+#define CAN_BS2_2tq                 ((uint8_t)0x01)  /*!< 2 time quantum */
+#define CAN_BS2_3tq                 ((uint8_t)0x02)  /*!< 3 time quantum */
+#define CAN_BS2_4tq                 ((uint8_t)0x03)  /*!< 4 time quantum */
+#define CAN_BS2_5tq                 ((uint8_t)0x04)  /*!< 5 time quantum */
+#define CAN_BS2_6tq                 ((uint8_t)0x05)  /*!< 6 time quantum */
+#define CAN_BS2_7tq                 ((uint8_t)0x06)  /*!< 7 time quantum */
+#define CAN_BS2_8tq                 ((uint8_t)0x07)  /*!< 8 time quantum */
+
+#define IS_CAN_BS2(BS2) ((BS2) <= CAN_BS2_8tq)
+/**
+  * @}
+  */
+
+/** @defgroup CAN_clock_prescaler 
+  * @{
+  */
+#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1) && ((PRESCALER) <= 1024))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_filter_number 
+  * @{
+  */
+#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 27)
+/**
+  * @}
+  */
+
+/** @defgroup CAN_filter_mode 
+  * @{
+  */
+#define CAN_FilterMode_IdMask       ((uint8_t)0x00)  /*!< identifier/mask mode */
+#define CAN_FilterMode_IdList       ((uint8_t)0x01)  /*!< identifier list mode */
+
+#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FilterMode_IdMask) || \
+                                  ((MODE) == CAN_FilterMode_IdList))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_filter_scale 
+  * @{
+  */
+#define CAN_FilterScale_16bit       ((uint8_t)0x00) /*!< Two 16-bit filters */
+#define CAN_FilterScale_32bit       ((uint8_t)0x01) /*!< One 32-bit filter */
+
+#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FilterScale_16bit) || \
+                                    ((SCALE) == CAN_FilterScale_32bit))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_filter_FIFO
+  * @{
+  */
+#define CAN_Filter_FIFO0             ((uint8_t)0x00)  /*!< Filter FIFO 0 assignment for filter x */
+#define CAN_Filter_FIFO1             ((uint8_t)0x01)  /*!< Filter FIFO 1 assignment for filter x */
+#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FilterFIFO0) || \
+                                  ((FIFO) == CAN_FilterFIFO1))
+
+/* Legacy defines */
+#define CAN_FilterFIFO0  CAN_Filter_FIFO0
+#define CAN_FilterFIFO1  CAN_Filter_FIFO1
+/**
+  * @}
+  */
+
+/** @defgroup CAN_Start_bank_filter_for_slave_CAN 
+  * @{
+  */
+#define IS_CAN_BANKNUMBER(BANKNUMBER) (((BANKNUMBER) >= 1) && ((BANKNUMBER) <= 27))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_Tx 
+  * @{
+  */
+#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02))
+#define IS_CAN_STDID(STDID)   ((STDID) <= ((uint32_t)0x7FF))
+#define IS_CAN_EXTID(EXTID)   ((EXTID) <= ((uint32_t)0x1FFFFFFF))
+#define IS_CAN_DLC(DLC)       ((DLC) <= ((uint8_t)0x08))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_identifier_type 
+  * @{
+  */
+#define CAN_Id_Standard             ((uint32_t)0x00000000)  /*!< Standard Id */
+#define CAN_Id_Extended             ((uint32_t)0x00000004)  /*!< Extended Id */
+#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_Id_Standard) || \
+                               ((IDTYPE) == CAN_Id_Extended))
+
+/* Legacy defines */
+#define CAN_ID_STD      CAN_Id_Standard           
+#define CAN_ID_EXT      CAN_Id_Extended
+/**
+  * @}
+  */
+
+/** @defgroup CAN_remote_transmission_request 
+  * @{
+  */
+#define CAN_RTR_Data                ((uint32_t)0x00000000)  /*!< Data frame */
+#define CAN_RTR_Remote              ((uint32_t)0x00000002)  /*!< Remote frame */
+#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_Data) || ((RTR) == CAN_RTR_Remote))
+
+/* Legacy defines */
+#define CAN_RTR_DATA     CAN_RTR_Data         
+#define CAN_RTR_REMOTE   CAN_RTR_Remote
+/**
+  * @}
+  */
+
+/** @defgroup CAN_transmit_constants 
+  * @{
+  */
+#define CAN_TxStatus_Failed         ((uint8_t)0x00)/*!< CAN transmission failed */
+#define CAN_TxStatus_Ok             ((uint8_t)0x01) /*!< CAN transmission succeeded */
+#define CAN_TxStatus_Pending        ((uint8_t)0x02) /*!< CAN transmission pending */
+#define CAN_TxStatus_NoMailBox      ((uint8_t)0x04) /*!< CAN cell did not provide 
+                                                         an empty mailbox */
+/* Legacy defines */	
+#define CANTXFAILED                  CAN_TxStatus_Failed
+#define CANTXOK                      CAN_TxStatus_Ok
+#define CANTXPENDING                 CAN_TxStatus_Pending
+#define CAN_NO_MB                    CAN_TxStatus_NoMailBox
+/**
+  * @}
+  */
+
+/** @defgroup CAN_receive_FIFO_number_constants 
+  * @{
+  */
+#define CAN_FIFO0                 ((uint8_t)0x00) /*!< CAN FIFO 0 used to receive */
+#define CAN_FIFO1                 ((uint8_t)0x01) /*!< CAN FIFO 1 used to receive */
+
+#define IS_CAN_FIFO(FIFO) (((FIFO) == CAN_FIFO0) || ((FIFO) == CAN_FIFO1))
+/**
+  * @}
+  */
+
+/** @defgroup CAN_sleep_constants 
+  * @{
+  */
+#define CAN_Sleep_Failed     ((uint8_t)0x00) /*!< CAN did not enter the sleep mode */
+#define CAN_Sleep_Ok         ((uint8_t)0x01) /*!< CAN entered the sleep mode */
+
+/* Legacy defines */	
+#define CANSLEEPFAILED   CAN_Sleep_Failed
+#define CANSLEEPOK       CAN_Sleep_Ok
+/**
+  * @}
+  */
+
+/** @defgroup CAN_wake_up_constants 
+  * @{
+  */
+#define CAN_WakeUp_Failed        ((uint8_t)0x00) /*!< CAN did not leave the sleep mode */
+#define CAN_WakeUp_Ok            ((uint8_t)0x01) /*!< CAN leaved the sleep mode */
+
+/* Legacy defines */
+#define CANWAKEUPFAILED   CAN_WakeUp_Failed        
+#define CANWAKEUPOK       CAN_WakeUp_Ok        
+/**
+  * @}
+  */
+
+/**
+  * @defgroup CAN_Error_Code_constants
+  * @{
+  */                                                         
+#define CAN_ErrorCode_NoErr           ((uint8_t)0x00) /*!< No Error */ 
+#define	CAN_ErrorCode_StuffErr        ((uint8_t)0x10) /*!< Stuff Error */ 
+#define	CAN_ErrorCode_FormErr         ((uint8_t)0x20) /*!< Form Error */ 
+#define	CAN_ErrorCode_ACKErr          ((uint8_t)0x30) /*!< Acknowledgment Error */ 
+#define	CAN_ErrorCode_BitRecessiveErr ((uint8_t)0x40) /*!< Bit Recessive Error */ 
+#define	CAN_ErrorCode_BitDominantErr  ((uint8_t)0x50) /*!< Bit Dominant Error */ 
+#define	CAN_ErrorCode_CRCErr          ((uint8_t)0x60) /*!< CRC Error  */ 
+#define	CAN_ErrorCode_SoftwareSetErr  ((uint8_t)0x70) /*!< Software Set Error */ 
+/**
+  * @}
+  */
+
+/** @defgroup CAN_flags 
+  * @{
+  */
+/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagStatus()
+   and CAN_ClearFlag() functions. */
+/* If the flag is 0x1XXXXXXX, it means that it can only be used with 
+   CAN_GetFlagStatus() function.  */
+
+/* Transmit Flags */
+#define CAN_FLAG_RQCP0             ((uint32_t)0x38000001) /*!< Request MailBox0 Flag */
+#define CAN_FLAG_RQCP1             ((uint32_t)0x38000100) /*!< Request MailBox1 Flag */
+#define CAN_FLAG_RQCP2             ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */
+
+/* Receive Flags */
+#define CAN_FLAG_FMP0              ((uint32_t)0x12000003) /*!< FIFO 0 Message Pending Flag */
+#define CAN_FLAG_FF0               ((uint32_t)0x32000008) /*!< FIFO 0 Full Flag            */
+#define CAN_FLAG_FOV0              ((uint32_t)0x32000010) /*!< FIFO 0 Overrun Flag         */
+#define CAN_FLAG_FMP1              ((uint32_t)0x14000003) /*!< FIFO 1 Message Pending Flag */
+#define CAN_FLAG_FF1               ((uint32_t)0x34000008) /*!< FIFO 1 Full Flag            */
+#define CAN_FLAG_FOV1              ((uint32_t)0x34000010) /*!< FIFO 1 Overrun Flag         */
+
+/* Operating Mode Flags */
+#define CAN_FLAG_WKU               ((uint32_t)0x31000008) /*!< Wake up Flag */
+#define CAN_FLAG_SLAK              ((uint32_t)0x31000012) /*!< Sleep acknowledge Flag */
+/* @note When SLAK interrupt is disabled (SLKIE=0), no polling on SLAKI is possible. 
+         In this case the SLAK bit can be polled.*/
+
+/* Error Flags */
+#define CAN_FLAG_EWG               ((uint32_t)0x10F00001) /*!< Error Warning Flag   */
+#define CAN_FLAG_EPV               ((uint32_t)0x10F00002) /*!< Error Passive Flag   */
+#define CAN_FLAG_BOF               ((uint32_t)0x10F00004) /*!< Bus-Off Flag         */
+#define CAN_FLAG_LEC               ((uint32_t)0x30F00070) /*!< Last error code Flag */
+
+#define IS_CAN_GET_FLAG(FLAG) (((FLAG) == CAN_FLAG_LEC)  || ((FLAG) == CAN_FLAG_BOF)   || \
+                               ((FLAG) == CAN_FLAG_EPV)  || ((FLAG) == CAN_FLAG_EWG)   || \
+                               ((FLAG) == CAN_FLAG_WKU)  || ((FLAG) == CAN_FLAG_FOV0)  || \
+                               ((FLAG) == CAN_FLAG_FF0)  || ((FLAG) == CAN_FLAG_FMP0)  || \
+                               ((FLAG) == CAN_FLAG_FOV1) || ((FLAG) == CAN_FLAG_FF1)   || \
+                               ((FLAG) == CAN_FLAG_FMP1) || ((FLAG) == CAN_FLAG_RQCP2) || \
+                               ((FLAG) == CAN_FLAG_RQCP1)|| ((FLAG) == CAN_FLAG_RQCP0) || \
+                               ((FLAG) == CAN_FLAG_SLAK ))
+
+#define IS_CAN_CLEAR_FLAG(FLAG)(((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_RQCP2) || \
+                                ((FLAG) == CAN_FLAG_RQCP1)  || ((FLAG) == CAN_FLAG_RQCP0) || \
+                                ((FLAG) == CAN_FLAG_FF0)  || ((FLAG) == CAN_FLAG_FOV0) ||\
+                                ((FLAG) == CAN_FLAG_FF1) || ((FLAG) == CAN_FLAG_FOV1) || \
+                                ((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_SLAK))
+/**
+  * @}
+  */
+
+  
+/** @defgroup CAN_interrupts 
+  * @{
+  */ 
+#define CAN_IT_TME                  ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/
+
+/* Receive Interrupts */
+#define CAN_IT_FMP0                 ((uint32_t)0x00000002) /*!< FIFO 0 message pending Interrupt*/
+#define CAN_IT_FF0                  ((uint32_t)0x00000004) /*!< FIFO 0 full Interrupt*/
+#define CAN_IT_FOV0                 ((uint32_t)0x00000008) /*!< FIFO 0 overrun Interrupt*/
+#define CAN_IT_FMP1                 ((uint32_t)0x00000010) /*!< FIFO 1 message pending Interrupt*/
+#define CAN_IT_FF1                  ((uint32_t)0x00000020) /*!< FIFO 1 full Interrupt*/
+#define CAN_IT_FOV1                 ((uint32_t)0x00000040) /*!< FIFO 1 overrun Interrupt*/
+
+/* Operating Mode Interrupts */
+#define CAN_IT_WKU                  ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/
+#define CAN_IT_SLK                  ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt*/
+
+/* Error Interrupts */
+#define CAN_IT_EWG                  ((uint32_t)0x00000100) /*!< Error warning Interrupt*/
+#define CAN_IT_EPV                  ((uint32_t)0x00000200) /*!< Error passive Interrupt*/
+#define CAN_IT_BOF                  ((uint32_t)0x00000400) /*!< Bus-off Interrupt*/
+#define CAN_IT_LEC                  ((uint32_t)0x00000800) /*!< Last error code Interrupt*/
+#define CAN_IT_ERR                  ((uint32_t)0x00008000) /*!< Error Interrupt*/
+
+/* Flags named as Interrupts : kept only for FW compatibility */
+#define CAN_IT_RQCP0   CAN_IT_TME
+#define CAN_IT_RQCP1   CAN_IT_TME
+#define CAN_IT_RQCP2   CAN_IT_TME
+
+
+#define IS_CAN_IT(IT)        (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FMP0)  ||\
+                             ((IT) == CAN_IT_FF0)  || ((IT) == CAN_IT_FOV0)  ||\
+                             ((IT) == CAN_IT_FMP1) || ((IT) == CAN_IT_FF1)   ||\
+                             ((IT) == CAN_IT_FOV1) || ((IT) == CAN_IT_EWG)   ||\
+                             ((IT) == CAN_IT_EPV)  || ((IT) == CAN_IT_BOF)   ||\
+                             ((IT) == CAN_IT_LEC)  || ((IT) == CAN_IT_ERR)   ||\
+                             ((IT) == CAN_IT_WKU)  || ((IT) == CAN_IT_SLK))
+
+#define IS_CAN_CLEAR_IT(IT) (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FF0)    ||\
+                             ((IT) == CAN_IT_FOV0)|| ((IT) == CAN_IT_FF1)    ||\
+                             ((IT) == CAN_IT_FOV1)|| ((IT) == CAN_IT_EWG)    ||\
+                             ((IT) == CAN_IT_EPV) || ((IT) == CAN_IT_BOF)    ||\
+                             ((IT) == CAN_IT_LEC) || ((IT) == CAN_IT_ERR)    ||\
+                             ((IT) == CAN_IT_WKU) || ((IT) == CAN_IT_SLK))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+/*  Function used to set the CAN configuration to the default reset state *****/ 
+void CAN_DeInit(CAN_TypeDef* CANx);
+
+/* Initialization and Configuration functions *********************************/ 
+uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);
+void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);
+void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct);
+void CAN_SlaveStartBank(uint8_t CAN_BankNumber); 
+void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState);
+void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState);
+
+/* CAN Frames Transmission functions ******************************************/
+uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
+uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox);
+void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox);
+
+/* CAN Frames Reception functions *********************************************/
+void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);
+void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber);
+uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber);
+
+/* Operation modes functions **************************************************/
+uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode);
+uint8_t CAN_Sleep(CAN_TypeDef* CANx);
+uint8_t CAN_WakeUp(CAN_TypeDef* CANx);
+
+/* CAN Bus Error management functions *****************************************/
+uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx);
+uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx);
+uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx);
+
+/* Interrupts and flags management functions **********************************/
+void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState);
+FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG);
+void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG);
+ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT);
+void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_CAN_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 75 - 0
app/Libraries/inc/stm32f2xx_crc.h

@@ -0,0 +1,75 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_crc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the CRC firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_CRC_H
+#define __STM32F2xx_CRC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup CRC
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup CRC_Exported_Constants
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+void CRC_ResetDR(void);
+uint32_t CRC_CalcCRC(uint32_t Data);
+uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength);
+uint32_t CRC_GetCRC(void);
+void CRC_SetIDRegister(uint8_t IDValue);
+uint8_t CRC_GetIDRegister(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_CRC_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 336 - 0
app/Libraries/inc/stm32f2xx_cryp.h

@@ -0,0 +1,336 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_cryp.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the Cryptographic
+  *          processor(CRYP) firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_CRYP_H
+#define __STM32F2xx_CRYP_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup CRYP
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief   CRYP Init structure definition  
+  */ 
+typedef struct
+{
+  uint16_t CRYP_AlgoDir;   /*!< Encrypt or Decrypt. This parameter can be a 
+                                value of @ref CRYP_Algorithm_Direction */
+  uint16_t CRYP_AlgoMode;  /*!< TDES-ECB, TDES-CBC, DES-ECB, DES-CBC, AES-ECB, 
+                                AES-CBC, AES-CTR, AES-Key. This parameter can be
+                                a value of @ref CRYP_Algorithm_Mode */
+  uint16_t CRYP_DataType;  /*!< 32-bit data, 16-bit data, bit data or bit-string.
+                                This parameter can be a value of @ref CRYP_Data_Type */ 
+  uint16_t CRYP_KeySize;   /*!< Used only in AES mode only : 128, 192 or 256 bit 
+                                key length. This parameter can be a value of 
+                                @ref CRYP_Key_Size_for_AES_only */
+}CRYP_InitTypeDef;
+
+/** 
+  * @brief   CRYP Key(s) structure definition  
+  */ 
+typedef struct
+{
+  uint32_t CRYP_Key0Left;  /*!< Key 0 Left  */
+  uint32_t CRYP_Key0Right; /*!< Key 0 Right */
+  uint32_t CRYP_Key1Left;  /*!< Key 1 left  */
+  uint32_t CRYP_Key1Right; /*!< Key 1 Right */
+  uint32_t CRYP_Key2Left;  /*!< Key 2 left  */
+  uint32_t CRYP_Key2Right; /*!< Key 2 Right */
+  uint32_t CRYP_Key3Left;  /*!< Key 3 left  */
+  uint32_t CRYP_Key3Right; /*!< Key 3 Right */
+}CRYP_KeyInitTypeDef;
+/** 
+  * @brief   CRYP Initialization Vectors (IV) structure definition  
+  */ 
+typedef struct
+{
+  uint32_t CRYP_IV0Left;  /*!< Init Vector 0 Left  */
+  uint32_t CRYP_IV0Right; /*!< Init Vector 0 Right */
+  uint32_t CRYP_IV1Left;  /*!< Init Vector 1 left  */
+  uint32_t CRYP_IV1Right; /*!< Init Vector 1 Right */
+}CRYP_IVInitTypeDef;
+
+/** 
+  * @brief  CRYP context swapping structure definition  
+  */ 
+typedef struct
+{
+  /*!< Configuration */
+  uint32_t CR_bits9to2;
+  /*!< KEY */
+  uint32_t CRYP_IV0LR;
+  uint32_t CRYP_IV0RR;
+  uint32_t CRYP_IV1LR;
+  uint32_t CRYP_IV1RR;
+  /*!< IV */
+  uint32_t CRYP_K0LR;
+  uint32_t CRYP_K0RR;
+  uint32_t CRYP_K1LR;
+  uint32_t CRYP_K1RR;
+  uint32_t CRYP_K2LR;
+  uint32_t CRYP_K2RR;
+  uint32_t CRYP_K3LR;
+  uint32_t CRYP_K3RR;
+}CRYP_Context;
+
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup CRYP_Exported_Constants
+  * @{
+  */
+
+/** @defgroup CRYP_Algorithm_Direction 
+  * @{
+  */
+#define CRYP_AlgoDir_Encrypt      ((uint16_t)0x0000)
+#define CRYP_AlgoDir_Decrypt      ((uint16_t)0x0004)
+#define IS_CRYP_ALGODIR(ALGODIR) (((ALGODIR) == CRYP_AlgoDir_Encrypt) || \
+                                  ((ALGODIR) == CRYP_AlgoDir_Decrypt))
+
+/**
+  * @}
+  */ 
+ 
+/** @defgroup CRYP_Algorithm_Mode 
+  * @{
+  */
+
+/*!< TDES Modes */
+#define CRYP_AlgoMode_TDES_ECB    ((uint16_t)0x0000)
+#define CRYP_AlgoMode_TDES_CBC    ((uint16_t)0x0008)
+
+/*!< DES Modes */
+#define CRYP_AlgoMode_DES_ECB     ((uint16_t)0x0010)
+#define CRYP_AlgoMode_DES_CBC     ((uint16_t)0x0018)
+
+/*!< AES Modes */
+#define CRYP_AlgoMode_AES_ECB     ((uint16_t)0x0020)
+#define CRYP_AlgoMode_AES_CBC     ((uint16_t)0x0028)
+#define CRYP_AlgoMode_AES_CTR     ((uint16_t)0x0030)
+#define CRYP_AlgoMode_AES_Key     ((uint16_t)0x0038)
+
+#define IS_CRYP_ALGOMODE(ALGOMODE) (((ALGOMODE) == CRYP_AlgoMode_TDES_ECB) || \
+                                   ((ALGOMODE) == CRYP_AlgoMode_TDES_CBC)|| \
+                                   ((ALGOMODE) == CRYP_AlgoMode_DES_ECB)|| \
+                                   ((ALGOMODE) == CRYP_AlgoMode_DES_CBC) || \
+                                   ((ALGOMODE) == CRYP_AlgoMode_AES_ECB) || \
+                                   ((ALGOMODE) == CRYP_AlgoMode_AES_CBC) || \
+                                   ((ALGOMODE) == CRYP_AlgoMode_AES_CTR) || \
+                                   ((ALGOMODE) == CRYP_AlgoMode_AES_Key))
+/**
+  * @}
+  */ 
+ 
+/** @defgroup CRYP_Data_Type 
+  * @{
+  */
+#define CRYP_DataType_32b         ((uint16_t)0x0000)
+#define CRYP_DataType_16b         ((uint16_t)0x0040)
+#define CRYP_DataType_8b          ((uint16_t)0x0080)
+#define CRYP_DataType_1b          ((uint16_t)0x00C0)
+#define IS_CRYP_DATATYPE(DATATYPE) (((DATATYPE) == CRYP_DataType_32b) || \
+                                    ((DATATYPE) == CRYP_DataType_16b)|| \
+                                    ((DATATYPE) == CRYP_DataType_8b)|| \
+                                    ((DATATYPE) == CRYP_DataType_1b))  
+/**
+  * @}
+  */
+                                     
+/** @defgroup CRYP_Key_Size_for_AES_only 
+  * @{
+  */
+#define CRYP_KeySize_128b         ((uint16_t)0x0000)
+#define CRYP_KeySize_192b         ((uint16_t)0x0100)
+#define CRYP_KeySize_256b         ((uint16_t)0x0200)
+#define IS_CRYP_KEYSIZE(KEYSIZE) (((KEYSIZE) == CRYP_KeySize_128b)|| \
+                                  ((KEYSIZE) == CRYP_KeySize_192b)|| \
+                                  ((KEYSIZE) == CRYP_KeySize_256b))
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_flags_definition 
+  * @{
+  */
+#define CRYP_FLAG_BUSY            ((uint8_t)0x10)  /*!< The CRYP core is currently 
+                                                        processing a block of data 
+                                                        or a key preparation (for 
+                                                        AES decryption). */
+#define CRYP_FLAG_IFEM            ((uint8_t)0x01)  /*!< Input Fifo Empty */
+#define CRYP_FLAG_IFNF            ((uint8_t)0x02)  /*!< Input Fifo is Not Full */
+#define CRYP_FLAG_INRIS           ((uint8_t)0x22)  /*!< Raw interrupt pending */
+#define CRYP_FLAG_OFNE            ((uint8_t)0x04)  /*!< Input Fifo service raw 
+                                                        interrupt status */
+#define CRYP_FLAG_OFFU            ((uint8_t)0x08)  /*!< Output Fifo is Full */
+#define CRYP_FLAG_OUTRIS          ((uint8_t)0x21)  /*!< Output Fifo service raw 
+                                                        interrupt status */
+
+#define IS_CRYP_GET_FLAG(FLAG) (((FLAG) == CRYP_FLAG_IFEM)  || \
+                                ((FLAG) == CRYP_FLAG_IFNF)  || \
+                                ((FLAG) == CRYP_FLAG_OFNE)  || \
+                                ((FLAG) == CRYP_FLAG_OFFU)  || \
+                                ((FLAG) == CRYP_FLAG_BUSY)  || \
+                                ((FLAG) == CRYP_FLAG_OUTRIS)|| \
+                                ((FLAG) == CRYP_FLAG_INRIS))
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_interrupts_definition 
+  * @{
+  */
+#define CRYP_IT_INI               ((uint8_t)0x01) /*!< IN Fifo Interrupt */
+#define CRYP_IT_OUTI              ((uint8_t)0x02) /*!< OUT Fifo Interrupt */
+#define IS_CRYP_CONFIG_IT(IT) ((((IT) & (uint8_t)0xFC) == 0x00) && ((IT) != 0x00))
+#define IS_CRYP_GET_IT(IT) (((IT) == CRYP_IT_INI) || ((IT) == CRYP_IT_OUTI))
+
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_Encryption_Decryption_modes_definition 
+  * @{
+  */
+#define MODE_ENCRYPT             ((uint8_t)0x01)
+#define MODE_DECRYPT             ((uint8_t)0x00)
+
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_DMA_transfer_requests 
+  * @{
+  */
+#define CRYP_DMAReq_DataIN             ((uint8_t)0x01)
+#define CRYP_DMAReq_DataOUT            ((uint8_t)0x02)
+#define IS_CRYP_DMAREQ(DMAREQ) ((((DMAREQ) & (uint8_t)0xFC) == 0x00) && ((DMAREQ) != 0x00))
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/*  Function used to set the CRYP configuration to the default reset state ****/
+void CRYP_DeInit(void);
+
+/* CRYP Initialization and Configuration functions ****************************/
+void CRYP_Init(CRYP_InitTypeDef* CRYP_InitStruct);
+void CRYP_StructInit(CRYP_InitTypeDef* CRYP_InitStruct);
+void CRYP_KeyInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct);
+void CRYP_KeyStructInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct);
+void CRYP_IVInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct);
+void CRYP_IVStructInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct);
+void CRYP_Cmd(FunctionalState NewState);
+
+/* CRYP Data processing functions *********************************************/
+void CRYP_DataIn(uint32_t Data);
+uint32_t CRYP_DataOut(void);
+void CRYP_FIFOFlush(void);
+
+/* CRYP Context swapping functions ********************************************/
+ErrorStatus CRYP_SaveContext(CRYP_Context* CRYP_ContextSave,
+                             CRYP_KeyInitTypeDef* CRYP_KeyInitStruct);
+void CRYP_RestoreContext(CRYP_Context* CRYP_ContextRestore);
+
+/* CRYP's DMA interface function **********************************************/
+void CRYP_DMACmd(uint8_t CRYP_DMAReq, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void CRYP_ITConfig(uint8_t CRYP_IT, FunctionalState NewState);
+ITStatus CRYP_GetITStatus(uint8_t CRYP_IT);
+FlagStatus CRYP_GetFlagStatus(uint8_t CRYP_FLAG);
+
+/* High Level AES functions **************************************************/
+ErrorStatus CRYP_AES_ECB(uint8_t Mode,
+                         uint8_t *Key, uint16_t Keysize,
+                         uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output);
+
+ErrorStatus CRYP_AES_CBC(uint8_t Mode,
+                         uint8_t InitVectors[16],
+                         uint8_t *Key, uint16_t Keysize,
+                         uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output);
+
+ErrorStatus CRYP_AES_CTR(uint8_t Mode,
+                         uint8_t InitVectors[16],
+                         uint8_t *Key, uint16_t Keysize,
+                         uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output);
+
+/* High Level TDES functions **************************************************/
+ErrorStatus CRYP_TDES_ECB(uint8_t Mode,
+                           uint8_t Key[24], 
+                           uint8_t *Input, uint32_t Ilength,
+                           uint8_t *Output);
+
+ErrorStatus CRYP_TDES_CBC(uint8_t Mode,
+                          uint8_t Key[24],
+                          uint8_t InitVectors[8],
+                          uint8_t *Input, uint32_t Ilength,
+                          uint8_t *Output);
+
+/* High Level DES functions **************************************************/
+ErrorStatus CRYP_DES_ECB(uint8_t Mode,
+                         uint8_t Key[8],
+                         uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output);
+
+ErrorStatus CRYP_DES_CBC(uint8_t Mode,
+                         uint8_t Key[8],
+                         uint8_t InitVectors[8],
+                         uint8_t *Input,uint32_t Ilength,
+                         uint8_t *Output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_CRYP_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+

+ 296 - 0
app/Libraries/inc/stm32f2xx_dac.h

@@ -0,0 +1,296 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dac.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the DAC firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_DAC_H
+#define __STM32F2xx_DAC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup DAC
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  DAC Init structure definition
+  */
+
+typedef struct
+{
+  uint32_t DAC_Trigger;                      /*!< Specifies the external trigger for the selected DAC channel.
+                                                  This parameter can be a value of @ref DAC_trigger_selection */
+
+  uint32_t DAC_WaveGeneration;               /*!< Specifies whether DAC channel noise waves or triangle waves
+                                                  are generated, or whether no wave is generated.
+                                                  This parameter can be a value of @ref DAC_wave_generation */
+
+  uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or
+                                                  the maximum amplitude triangle generation for the DAC channel. 
+                                                  This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
+
+  uint32_t DAC_OutputBuffer;                 /*!< Specifies whether the DAC channel output buffer is enabled or disabled.
+                                                  This parameter can be a value of @ref DAC_output_buffer */
+}DAC_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup DAC_Exported_Constants
+  * @{
+  */
+
+/** @defgroup DAC_trigger_selection 
+  * @{
+  */
+
+#define DAC_Trigger_None                   ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register 
+                                                                       has been loaded, and not by external trigger */
+#define DAC_Trigger_T2_TRGO                ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T4_TRGO                ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T5_TRGO                ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T6_TRGO                ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T7_TRGO                ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T8_TRGO                ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel */                                                                       
+
+#define DAC_Trigger_Ext_IT9                ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_Software               ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel */
+
+#define IS_DAC_TRIGGER(TRIGGER) (((TRIGGER) == DAC_Trigger_None) || \
+                                 ((TRIGGER) == DAC_Trigger_T6_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T8_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T7_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T5_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T2_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T4_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_Ext_IT9) || \
+                                 ((TRIGGER) == DAC_Trigger_Software))
+
+/**
+  * @}
+  */
+
+/** @defgroup DAC_wave_generation 
+  * @{
+  */
+
+#define DAC_WaveGeneration_None            ((uint32_t)0x00000000)
+#define DAC_WaveGeneration_Noise           ((uint32_t)0x00000040)
+#define DAC_WaveGeneration_Triangle        ((uint32_t)0x00000080)
+#define IS_DAC_GENERATE_WAVE(WAVE) (((WAVE) == DAC_WaveGeneration_None) || \
+                                    ((WAVE) == DAC_WaveGeneration_Noise) || \
+                                    ((WAVE) == DAC_WaveGeneration_Triangle))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_lfsrunmask_triangleamplitude
+  * @{
+  */
+
+#define DAC_LFSRUnmask_Bit0                ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation */
+#define DAC_LFSRUnmask_Bits1_0             ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits2_0             ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits3_0             ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits4_0             ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits5_0             ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits6_0             ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits7_0             ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits8_0             ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits9_0             ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits10_0            ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits11_0            ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation */
+#define DAC_TriangleAmplitude_1            ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */
+#define DAC_TriangleAmplitude_3            ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */
+#define DAC_TriangleAmplitude_7            ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */
+#define DAC_TriangleAmplitude_15           ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */
+#define DAC_TriangleAmplitude_31           ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */
+#define DAC_TriangleAmplitude_63           ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */
+#define DAC_TriangleAmplitude_127          ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */
+#define DAC_TriangleAmplitude_255          ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */
+#define DAC_TriangleAmplitude_511          ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */
+#define DAC_TriangleAmplitude_1023         ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */
+#define DAC_TriangleAmplitude_2047         ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */
+#define DAC_TriangleAmplitude_4095         ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */
+
+#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) (((VALUE) == DAC_LFSRUnmask_Bit0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits1_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits2_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits3_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits4_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits5_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits6_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits7_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits8_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits9_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits10_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits11_0) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_1) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_3) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_7) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_15) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_31) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_63) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_127) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_255) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_511) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_1023) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_2047) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_4095))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_output_buffer 
+  * @{
+  */
+
+#define DAC_OutputBuffer_Enable            ((uint32_t)0x00000000)
+#define DAC_OutputBuffer_Disable           ((uint32_t)0x00000002)
+#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_OutputBuffer_Enable) || \
+                                           ((STATE) == DAC_OutputBuffer_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Channel_selection 
+  * @{
+  */
+
+#define DAC_Channel_1                      ((uint32_t)0x00000000)
+#define DAC_Channel_2                      ((uint32_t)0x00000010)
+#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_Channel_1) || \
+                                 ((CHANNEL) == DAC_Channel_2))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_data_alignement 
+  * @{
+  */
+
+#define DAC_Align_12b_R                    ((uint32_t)0x00000000)
+#define DAC_Align_12b_L                    ((uint32_t)0x00000004)
+#define DAC_Align_8b_R                     ((uint32_t)0x00000008)
+#define IS_DAC_ALIGN(ALIGN) (((ALIGN) == DAC_Align_12b_R) || \
+                             ((ALIGN) == DAC_Align_12b_L) || \
+                             ((ALIGN) == DAC_Align_8b_R))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_wave_generation 
+  * @{
+  */
+
+#define DAC_Wave_Noise                     ((uint32_t)0x00000040)
+#define DAC_Wave_Triangle                  ((uint32_t)0x00000080)
+#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_Wave_Noise) || \
+                           ((WAVE) == DAC_Wave_Triangle))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_data 
+  * @{
+  */
+
+#define IS_DAC_DATA(DATA) ((DATA) <= 0xFFF0) 
+/**
+  * @}
+  */
+  
+/** @defgroup DAC_interrupts_definition 
+  * @{
+  */   
+#define DAC_IT_DMAUDR                      ((uint32_t)0x00002000)  
+#define IS_DAC_IT(IT) (((IT) == DAC_IT_DMAUDR)) 
+
+/**
+  * @}
+  */ 
+
+/** @defgroup DAC_flags_definition 
+  * @{
+  */ 
+  
+#define DAC_FLAG_DMAUDR                    ((uint32_t)0x00002000)  
+#define IS_DAC_FLAG(FLAG) (((FLAG) == DAC_FLAG_DMAUDR))  
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+/*  Function used to set the DAC configuration to the default reset state *****/  
+void DAC_DeInit(void);
+
+/*  DAC channels configuration: trigger, output buffer, data format functions */
+void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);
+void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct);
+void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);
+void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState);
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState);
+void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState);
+void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data);
+void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data);
+void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1);
+uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel);
+
+/* DMA management functions ***************************************************/
+void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState);
+FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG);
+void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG);
+ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT);
+void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_DAC_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 101 - 0
app/Libraries/inc/stm32f2xx_dbgmcu.h

@@ -0,0 +1,101 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dbgmcu.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the DBGMCU firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_DBGMCU_H
+#define __STM32F2xx_DBGMCU_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup DBGMCU
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup DBGMCU_Exported_Constants
+  * @{
+  */ 
+#define DBGMCU_SLEEP                 ((uint32_t)0x00000001)
+#define DBGMCU_STOP                  ((uint32_t)0x00000002)
+#define DBGMCU_STANDBY               ((uint32_t)0x00000004)
+#define IS_DBGMCU_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFFF8) == 0x00) && ((PERIPH) != 0x00))
+
+#define DBGMCU_TIM2_STOP             ((uint32_t)0x00000001)
+#define DBGMCU_TIM3_STOP             ((uint32_t)0x00000002)
+#define DBGMCU_TIM4_STOP             ((uint32_t)0x00000004)
+#define DBGMCU_TIM5_STOP             ((uint32_t)0x00000008)
+#define DBGMCU_TIM6_STOP             ((uint32_t)0x00000010)
+#define DBGMCU_TIM7_STOP             ((uint32_t)0x00000020)
+#define DBGMCU_TIM12_STOP            ((uint32_t)0x00000040)
+#define DBGMCU_TIM13_STOP            ((uint32_t)0x00000080)
+#define DBGMCU_TIM14_STOP            ((uint32_t)0x00000100)
+#define DBGMCU_RTC_STOP              ((uint32_t)0x00000400)
+#define DBGMCU_WWDG_STOP             ((uint32_t)0x00000800)
+#define DBGMCU_IWDG_STOP             ((uint32_t)0x00001000)
+#define DBGMCU_I2C1_SMBUS_TIMEOUT    ((uint32_t)0x00200000)
+#define DBGMCU_I2C2_SMBUS_TIMEOUT    ((uint32_t)0x00400000)
+#define DBGMCU_I2C3_SMBUS_TIMEOUT    ((uint32_t)0x00800000)
+#define DBGMCU_CAN1_STOP             ((uint32_t)0x02000000)
+#define DBGMCU_CAN2_STOP             ((uint32_t)0x04000000)
+#define IS_DBGMCU_APB1PERIPH(PERIPH) ((((PERIPH) & 0xF91FE200) == 0x00) && ((PERIPH) != 0x00))
+
+#define DBGMCU_TIM1_STOP             ((uint32_t)0x00000001)
+#define DBGMCU_TIM8_STOP             ((uint32_t)0x00000002)
+#define DBGMCU_TIM9_STOP             ((uint32_t)0x00010000)
+#define DBGMCU_TIM10_STOP            ((uint32_t)0x00020000)
+#define DBGMCU_TIM11_STOP            ((uint32_t)0x00040000)
+#define IS_DBGMCU_APB2PERIPH(PERIPH) ((((PERIPH) & 0xFFF8FFFC) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+uint32_t DBGMCU_GetREVID(void);
+uint32_t DBGMCU_GetDEVID(void);
+void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState);
+void DBGMCU_APB1PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState);
+void DBGMCU_APB2PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_DBGMCU_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 304 - 0
app/Libraries/inc/stm32f2xx_dcmi.h

@@ -0,0 +1,304 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dcmi.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the DCMI firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_DCMI_H
+#define __STM32F2xx_DCMI_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup DCMI
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/** 
+  * @brief   DCMI Init structure definition  
+  */ 
+typedef struct
+{
+  uint16_t DCMI_CaptureMode;      /*!< Specifies the Capture Mode: Continuous or Snapshot.
+                                       This parameter can be a value of @ref DCMI_Capture_Mode */
+
+  uint16_t DCMI_SynchroMode;      /*!< Specifies the Synchronization Mode: Hardware or Embedded.
+                                       This parameter can be a value of @ref DCMI_Synchronization_Mode */
+
+  uint16_t DCMI_PCKPolarity;      /*!< Specifies the Pixel clock polarity: Falling or Rising.
+                                       This parameter can be a value of @ref DCMI_PIXCK_Polarity */
+
+  uint16_t DCMI_VSPolarity;       /*!< Specifies the Vertical synchronization polarity: High or Low.
+                                       This parameter can be a value of @ref DCMI_VSYNC_Polarity */
+
+  uint16_t DCMI_HSPolarity;       /*!< Specifies the Horizontal synchronization polarity: High or Low.
+                                       This parameter can be a value of @ref DCMI_HSYNC_Polarity */
+
+  uint16_t DCMI_CaptureRate;      /*!< Specifies the frequency of frame capture: All, 1/2 or 1/4.
+                                       This parameter can be a value of @ref DCMI_Capture_Rate */
+
+  uint16_t DCMI_ExtendedDataMode; /*!< Specifies the data width: 8-bit, 10-bit, 12-bit or 14-bit.
+                                       This parameter can be a value of @ref DCMI_Extended_Data_Mode */
+} DCMI_InitTypeDef;
+
+/** 
+  * @brief   DCMI CROP Init structure definition  
+  */ 
+typedef struct
+{
+  uint16_t DCMI_VerticalStartLine;      /*!< Specifies the Vertical start line count from which the image capture
+                                             will start. This parameter can be a value between 0x00 and 0x1FFF */
+
+  uint16_t DCMI_HorizontalOffsetCount;  /*!< Specifies the number of pixel clocks to count before starting a capture.
+                                             This parameter can be a value between 0x00 and 0x3FFF */
+
+  uint16_t DCMI_VerticalLineCount;      /*!< Specifies the number of lines to be captured from the starting point.
+                                             This parameter can be a value between 0x00 and 0x3FFF */
+
+  uint16_t DCMI_CaptureCount;           /*!< Specifies the number of pixel clocks to be captured from the starting
+                                             point on the same line.
+                                             This parameter can be a value between 0x00 and 0x3FFF */
+} DCMI_CROPInitTypeDef;
+
+/** 
+  * @brief   DCMI Embedded Synchronisation CODE Init structure definition  
+  */ 
+typedef struct
+{
+  uint8_t DCMI_FrameStartCode; /*!< Specifies the code of the frame start delimiter. */
+  uint8_t DCMI_LineStartCode;  /*!< Specifies the code of the line start delimiter. */
+  uint8_t DCMI_LineEndCode;    /*!< Specifies the code of the line end delimiter. */
+  uint8_t DCMI_FrameEndCode;   /*!< Specifies the code of the frame end delimiter. */
+} DCMI_CodesInitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup DCMI_Exported_Constants
+  * @{
+  */
+
+/** @defgroup DCMI_Capture_Mode 
+  * @{
+  */ 
+#define DCMI_CaptureMode_Continuous    ((uint16_t)0x0000) /*!< The received data are transferred continuously 
+                                                               into the destination memory through the DMA */
+#define DCMI_CaptureMode_SnapShot      ((uint16_t)0x0002) /*!< Once activated, the interface waits for the start of 
+                                                               frame and then transfers a single frame through the DMA */
+#define IS_DCMI_CAPTURE_MODE(MODE)(((MODE) == DCMI_CaptureMode_Continuous) || \
+                                   ((MODE) == DCMI_CaptureMode_SnapShot))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_Synchronization_Mode
+  * @{
+  */ 
+#define DCMI_SynchroMode_Hardware    ((uint16_t)0x0000) /*!< Hardware synchronization data capture (frame/line start/stop)
+                                                             is synchronized with the HSYNC/VSYNC signals */
+#define DCMI_SynchroMode_Embedded    ((uint16_t)0x0010) /*!< Embedded synchronization data capture is synchronized with 
+                                                             synchronization codes embedded in the data flow */
+#define IS_DCMI_SYNCHRO(MODE)(((MODE) == DCMI_SynchroMode_Hardware) || \
+                              ((MODE) == DCMI_SynchroMode_Embedded))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_PIXCK_Polarity 
+  * @{
+  */ 
+#define DCMI_PCKPolarity_Falling    ((uint16_t)0x0000) /*!< Pixel clock active on Falling edge */
+#define DCMI_PCKPolarity_Rising     ((uint16_t)0x0020) /*!< Pixel clock active on Rising edge */
+#define IS_DCMI_PCKPOLARITY(POLARITY)(((POLARITY) == DCMI_PCKPolarity_Falling) || \
+                                      ((POLARITY) == DCMI_PCKPolarity_Rising))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_VSYNC_Polarity 
+  * @{
+  */ 
+#define DCMI_VSPolarity_Low     ((uint16_t)0x0000) /*!< Vertical synchronization active Low */
+#define DCMI_VSPolarity_High    ((uint16_t)0x0080) /*!< Vertical synchronization active High */
+#define IS_DCMI_VSPOLARITY(POLARITY)(((POLARITY) == DCMI_VSPolarity_Low) || \
+                                     ((POLARITY) == DCMI_VSPolarity_High))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_HSYNC_Polarity 
+  * @{
+  */ 
+#define DCMI_HSPolarity_Low     ((uint16_t)0x0000) /*!< Horizontal synchronization active Low */
+#define DCMI_HSPolarity_High    ((uint16_t)0x0040) /*!< Horizontal synchronization active High */
+#define IS_DCMI_HSPOLARITY(POLARITY)(((POLARITY) == DCMI_HSPolarity_Low) || \
+                                     ((POLARITY) == DCMI_HSPolarity_High))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_Capture_Rate 
+  * @{
+  */ 
+#define DCMI_CaptureRate_All_Frame     ((uint16_t)0x0000) /*!< All frames are captured */
+#define DCMI_CaptureRate_1of2_Frame    ((uint16_t)0x0100) /*!< Every alternate frame captured */
+#define DCMI_CaptureRate_1of4_Frame    ((uint16_t)0x0200) /*!< One frame in 4 frames captured */
+#define IS_DCMI_CAPTURE_RATE(RATE) (((RATE) == DCMI_CaptureRate_All_Frame) || \
+                                    ((RATE) == DCMI_CaptureRate_1of2_Frame) ||\
+                                    ((RATE) == DCMI_CaptureRate_1of4_Frame))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_Extended_Data_Mode 
+  * @{
+  */ 
+#define DCMI_ExtendedDataMode_8b     ((uint16_t)0x0000) /*!< Interface captures 8-bit data on every pixel clock */
+#define DCMI_ExtendedDataMode_10b    ((uint16_t)0x0400) /*!< Interface captures 10-bit data on every pixel clock */
+#define DCMI_ExtendedDataMode_12b    ((uint16_t)0x0800) /*!< Interface captures 12-bit data on every pixel clock */
+#define DCMI_ExtendedDataMode_14b    ((uint16_t)0x0C00) /*!< Interface captures 14-bit data on every pixel clock */
+#define IS_DCMI_EXTENDED_DATA(DATA)(((DATA) == DCMI_ExtendedDataMode_8b) || \
+                                    ((DATA) == DCMI_ExtendedDataMode_10b) ||\
+                                    ((DATA) == DCMI_ExtendedDataMode_12b) ||\
+                                    ((DATA) == DCMI_ExtendedDataMode_14b))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_interrupt_sources 
+  * @{
+  */ 
+#define DCMI_IT_FRAME    ((uint16_t)0x0001)
+#define DCMI_IT_OVF      ((uint16_t)0x0002)
+#define DCMI_IT_ERR      ((uint16_t)0x0004)
+#define DCMI_IT_VSYNC    ((uint16_t)0x0008)
+#define DCMI_IT_LINE     ((uint16_t)0x0010)
+#define IS_DCMI_CONFIG_IT(IT) ((((IT) & (uint16_t)0xFFE0) == 0x0000) && ((IT) != 0x0000))
+#define IS_DCMI_GET_IT(IT) (((IT) == DCMI_IT_FRAME) || \
+                            ((IT) == DCMI_IT_OVF) || \
+                            ((IT) == DCMI_IT_ERR) || \
+                            ((IT) == DCMI_IT_VSYNC) || \
+                            ((IT) == DCMI_IT_LINE))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DCMI_Flags 
+  * @{
+  */ 
+/** 
+  * @brief   DCMI SR register  
+  */ 
+#define DCMI_FLAG_HSYNC     ((uint16_t)0x2001)
+#define DCMI_FLAG_VSYNC     ((uint16_t)0x2002)
+#define DCMI_FLAG_FNE       ((uint16_t)0x2004)
+/** 
+  * @brief   DCMI RISR register  
+  */ 
+#define DCMI_FLAG_FRAMERI    ((uint16_t)0x0001)
+#define DCMI_FLAG_OVFRI      ((uint16_t)0x0002)
+#define DCMI_FLAG_ERRRI      ((uint16_t)0x0004)
+#define DCMI_FLAG_VSYNCRI    ((uint16_t)0x0008)
+#define DCMI_FLAG_LINERI     ((uint16_t)0x0010)
+/** 
+  * @brief   DCMI MISR register  
+  */ 
+#define DCMI_FLAG_FRAMEMI    ((uint16_t)0x1001)
+#define DCMI_FLAG_OVFMI      ((uint16_t)0x1002)
+#define DCMI_FLAG_ERRMI      ((uint16_t)0x1004)
+#define DCMI_FLAG_VSYNCMI    ((uint16_t)0x1008)
+#define DCMI_FLAG_LINEMI     ((uint16_t)0x1010)
+#define IS_DCMI_GET_FLAG(FLAG) (((FLAG) == DCMI_FLAG_HSYNC) || \
+                                ((FLAG) == DCMI_FLAG_VSYNC) || \
+                                ((FLAG) == DCMI_FLAG_FNE) || \
+                                ((FLAG) == DCMI_FLAG_FRAMERI) || \
+                                ((FLAG) == DCMI_FLAG_OVFRI) || \
+                                ((FLAG) == DCMI_FLAG_ERRRI) || \
+                                ((FLAG) == DCMI_FLAG_VSYNCRI) || \
+                                ((FLAG) == DCMI_FLAG_LINERI) || \
+                                ((FLAG) == DCMI_FLAG_FRAMEMI) || \
+                                ((FLAG) == DCMI_FLAG_OVFMI) || \
+                                ((FLAG) == DCMI_FLAG_ERRMI) || \
+                                ((FLAG) == DCMI_FLAG_VSYNCMI) || \
+                                ((FLAG) == DCMI_FLAG_LINEMI))
+                                
+#define IS_DCMI_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFFE0) == 0x0000) && ((FLAG) != 0x0000))
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the DCMI configuration to the default reset state ****/ 
+void DCMI_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void DCMI_Init(DCMI_InitTypeDef* DCMI_InitStruct);
+void DCMI_StructInit(DCMI_InitTypeDef* DCMI_InitStruct);
+void DCMI_CROPConfig(DCMI_CROPInitTypeDef* DCMI_CROPInitStruct);
+void DCMI_CROPCmd(FunctionalState NewState);
+void DCMI_SetEmbeddedSynchroCodes(DCMI_CodesInitTypeDef* DCMI_CodesInitStruct);
+void DCMI_JPEGCmd(FunctionalState NewState);
+
+/* Image capture functions ****************************************************/
+void DCMI_Cmd(FunctionalState NewState);
+void DCMI_CaptureCmd(FunctionalState NewState);
+uint32_t DCMI_ReadData(void);
+
+/* Interrupts and flags management functions **********************************/
+void DCMI_ITConfig(uint16_t DCMI_IT, FunctionalState NewState);
+FlagStatus DCMI_GetFlagStatus(uint16_t DCMI_FLAG);
+void DCMI_ClearFlag(uint16_t DCMI_FLAG);
+ITStatus DCMI_GetITStatus(uint16_t DCMI_IT);
+void DCMI_ClearITPendingBit(uint16_t DCMI_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_DCMI_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 601 - 0
app/Libraries/inc/stm32f2xx_dma.h

@@ -0,0 +1,601 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dma.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the DMA firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_DMA_H
+#define __STM32F2xx_DMA_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup DMA
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  DMA Init structure definition
+  */
+
+typedef struct
+{
+  uint32_t DMA_Channel;            /*!< Specifies the channel used for the specified stream. 
+                                        This parameter can be a value of @ref DMA_channel */
+ 
+  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Streamx. */
+
+  uint32_t DMA_Memory0BaseAddr;    /*!< Specifies the memory 0 base address for DMAy Streamx. 
+                                        This memory is the default memory used when double buffer mode is
+                                        not enabled. */
+
+  uint32_t DMA_DIR;                /*!< Specifies if the data will be transferred from memory to peripheral, 
+                                        from memory to memory or from peripheral to memory.
+                                        This parameter can be a value of @ref DMA_data_transfer_direction */
+
+  uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Stream. 
+                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize
+                                        or DMA_MemoryDataSize members depending in the transfer direction. */
+
+  uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register should be incremented or not.
+                                        This parameter can be a value of @ref DMA_peripheral_incremented_mode */
+
+  uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register should be incremented or not.
+                                        This parameter can be a value of @ref DMA_memory_incremented_mode */
+
+  uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.
+                                        This parameter can be a value of @ref DMA_peripheral_data_size */
+
+  uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.
+                                        This parameter can be a value of @ref DMA_memory_data_size */
+
+  uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Streamx.
+                                        This parameter can be a value of @ref DMA_circular_normal_mode
+                                        @note The circular buffer mode cannot be used if the memory-to-memory
+                                              data transfer is configured on the selected Stream */
+
+  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Streamx.
+                                        This parameter can be a value of @ref DMA_priority_level */
+
+  uint32_t DMA_FIFOMode;          /*!< Specifies if the FIFO mode or Direct mode will be used for the specified Stream.
+                                        This parameter can be a value of @ref DMA_fifo_direct_mode
+                                        @note The Direct mode (FIFO mode disabled) cannot be used if the 
+                                               memory-to-memory data transfer is configured on the selected Stream */
+
+  uint32_t DMA_FIFOThreshold;      /*!< Specifies the FIFO threshold level.
+                                        This parameter can be a value of @ref DMA_fifo_threshold_level */
+
+  uint32_t DMA_MemoryBurst;        /*!< Specifies the Burst transfer configuration for the memory transfers. 
+                                        It specifies the amount of data to be transferred in a single non interruptable 
+                                        transaction. This parameter can be a value of @ref DMA_memory_burst 
+                                        @note The burst mode is possible only if the address Increment mode is enabled. */
+
+  uint32_t DMA_PeripheralBurst;    /*!< Specifies the Burst transfer configuration for the peripheral transfers. 
+                                        It specifies the amount of data to be transferred in a single non interruptable 
+                                        transaction. This parameter can be a value of @ref DMA_peripheral_burst
+                                        @note The burst mode is possible only if the address Increment mode is enabled. */  
+}DMA_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup DMA_Exported_Constants
+  * @{
+  */
+
+#define IS_DMA_ALL_PERIPH(PERIPH) (((PERIPH) == DMA1_Stream0) || \
+                                   ((PERIPH) == DMA1_Stream1) || \
+                                   ((PERIPH) == DMA1_Stream2) || \
+                                   ((PERIPH) == DMA1_Stream3) || \
+                                   ((PERIPH) == DMA1_Stream4) || \
+                                   ((PERIPH) == DMA1_Stream5) || \
+                                   ((PERIPH) == DMA1_Stream6) || \
+                                   ((PERIPH) == DMA1_Stream7) || \
+                                   ((PERIPH) == DMA2_Stream0) || \
+                                   ((PERIPH) == DMA2_Stream1) || \
+                                   ((PERIPH) == DMA2_Stream2) || \
+                                   ((PERIPH) == DMA2_Stream3) || \
+                                   ((PERIPH) == DMA2_Stream4) || \
+                                   ((PERIPH) == DMA2_Stream5) || \
+                                   ((PERIPH) == DMA2_Stream6) || \
+                                   ((PERIPH) == DMA2_Stream7))
+
+#define IS_DMA_ALL_CONTROLLER(CONTROLLER) (((CONTROLLER) == DMA1) || \
+                                           ((CONTROLLER) == DMA2))
+
+/** @defgroup DMA_channel 
+  * @{
+  */ 
+#define DMA_Channel_0                     ((uint32_t)0x00000000)
+#define DMA_Channel_1                     ((uint32_t)0x02000000)
+#define DMA_Channel_2                     ((uint32_t)0x04000000)
+#define DMA_Channel_3                     ((uint32_t)0x06000000)
+#define DMA_Channel_4                     ((uint32_t)0x08000000)
+#define DMA_Channel_5                     ((uint32_t)0x0A000000)
+#define DMA_Channel_6                     ((uint32_t)0x0C000000)
+#define DMA_Channel_7                     ((uint32_t)0x0E000000)
+
+#define IS_DMA_CHANNEL(CHANNEL) (((CHANNEL) == DMA_Channel_0) || \
+                                 ((CHANNEL) == DMA_Channel_1) || \
+                                 ((CHANNEL) == DMA_Channel_2) || \
+                                 ((CHANNEL) == DMA_Channel_3) || \
+                                 ((CHANNEL) == DMA_Channel_4) || \
+                                 ((CHANNEL) == DMA_Channel_5) || \
+                                 ((CHANNEL) == DMA_Channel_6) || \
+                                 ((CHANNEL) == DMA_Channel_7))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_data_transfer_direction 
+  * @{
+  */ 
+#define DMA_DIR_PeripheralToMemory        ((uint32_t)0x00000000)
+#define DMA_DIR_MemoryToPeripheral        ((uint32_t)0x00000040) 
+#define DMA_DIR_MemoryToMemory            ((uint32_t)0x00000080)
+
+#define IS_DMA_DIRECTION(DIRECTION) (((DIRECTION) == DMA_DIR_PeripheralToMemory ) || \
+                                     ((DIRECTION) == DMA_DIR_MemoryToPeripheral)  || \
+                                     ((DIRECTION) == DMA_DIR_MemoryToMemory)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_data_buffer_size 
+  * @{
+  */ 
+#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_peripheral_incremented_mode 
+  * @{
+  */ 
+#define DMA_PeripheralInc_Enable          ((uint32_t)0x00000200)
+#define DMA_PeripheralInc_Disable         ((uint32_t)0x00000000)
+
+#define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PeripheralInc_Enable) || \
+                                            ((STATE) == DMA_PeripheralInc_Disable))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_memory_incremented_mode 
+  * @{
+  */ 
+#define DMA_MemoryInc_Enable              ((uint32_t)0x00000400)
+#define DMA_MemoryInc_Disable             ((uint32_t)0x00000000)
+
+#define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MemoryInc_Enable) || \
+                                        ((STATE) == DMA_MemoryInc_Disable))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_peripheral_data_size 
+  * @{
+  */ 
+#define DMA_PeripheralDataSize_Byte       ((uint32_t)0x00000000) 
+#define DMA_PeripheralDataSize_HalfWord   ((uint32_t)0x00000800) 
+#define DMA_PeripheralDataSize_Word       ((uint32_t)0x00001000)
+
+#define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PeripheralDataSize_Byte)  || \
+                                           ((SIZE) == DMA_PeripheralDataSize_HalfWord) || \
+                                           ((SIZE) == DMA_PeripheralDataSize_Word))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_memory_data_size 
+  * @{
+  */ 
+#define DMA_MemoryDataSize_Byte           ((uint32_t)0x00000000) 
+#define DMA_MemoryDataSize_HalfWord       ((uint32_t)0x00002000) 
+#define DMA_MemoryDataSize_Word           ((uint32_t)0x00004000)
+
+#define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MemoryDataSize_Byte)  || \
+                                       ((SIZE) == DMA_MemoryDataSize_HalfWord) || \
+                                       ((SIZE) == DMA_MemoryDataSize_Word ))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_circular_normal_mode 
+  * @{
+  */ 
+#define DMA_Mode_Normal                   ((uint32_t)0x00000000) 
+#define DMA_Mode_Circular                 ((uint32_t)0x00000100)
+
+#define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Normal ) || \
+                           ((MODE) == DMA_Mode_Circular)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_priority_level 
+  * @{
+  */ 
+#define DMA_Priority_Low                  ((uint32_t)0x00000000)
+#define DMA_Priority_Medium               ((uint32_t)0x00010000) 
+#define DMA_Priority_High                 ((uint32_t)0x00020000)
+#define DMA_Priority_VeryHigh             ((uint32_t)0x00030000)
+
+#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_Priority_Low )   || \
+                                   ((PRIORITY) == DMA_Priority_Medium) || \
+                                   ((PRIORITY) == DMA_Priority_High)   || \
+                                   ((PRIORITY) == DMA_Priority_VeryHigh)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_fifo_direct_mode 
+  * @{
+  */ 
+#define DMA_FIFOMode_Disable              ((uint32_t)0x00000000) 
+#define DMA_FIFOMode_Enable               ((uint32_t)0x00000004)
+
+#define IS_DMA_FIFO_MODE_STATE(STATE) (((STATE) == DMA_FIFOMode_Disable ) || \
+                                       ((STATE) == DMA_FIFOMode_Enable)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_fifo_threshold_level 
+  * @{
+  */ 
+#define DMA_FIFOThreshold_1QuarterFull    ((uint32_t)0x00000000)
+#define DMA_FIFOThreshold_HalfFull        ((uint32_t)0x00000001) 
+#define DMA_FIFOThreshold_3QuartersFull   ((uint32_t)0x00000002)
+#define DMA_FIFOThreshold_Full            ((uint32_t)0x00000003)
+
+#define IS_DMA_FIFO_THRESHOLD(THRESHOLD) (((THRESHOLD) == DMA_FIFOThreshold_1QuarterFull ) || \
+                                          ((THRESHOLD) == DMA_FIFOThreshold_HalfFull)      || \
+                                          ((THRESHOLD) == DMA_FIFOThreshold_3QuartersFull) || \
+                                          ((THRESHOLD) == DMA_FIFOThreshold_Full)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_memory_burst 
+  * @{
+  */ 
+#define DMA_MemoryBurst_Single            ((uint32_t)0x00000000)
+#define DMA_MemoryBurst_INC4              ((uint32_t)0x00800000)  
+#define DMA_MemoryBurst_INC8              ((uint32_t)0x01000000)
+#define DMA_MemoryBurst_INC16             ((uint32_t)0x01800000)
+
+#define IS_DMA_MEMORY_BURST(BURST) (((BURST) == DMA_MemoryBurst_Single) || \
+                                    ((BURST) == DMA_MemoryBurst_INC4)  || \
+                                    ((BURST) == DMA_MemoryBurst_INC8)  || \
+                                    ((BURST) == DMA_MemoryBurst_INC16))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_peripheral_burst 
+  * @{
+  */ 
+#define DMA_PeripheralBurst_Single        ((uint32_t)0x00000000)
+#define DMA_PeripheralBurst_INC4          ((uint32_t)0x00200000)  
+#define DMA_PeripheralBurst_INC8          ((uint32_t)0x00400000)
+#define DMA_PeripheralBurst_INC16         ((uint32_t)0x00600000)
+
+#define IS_DMA_PERIPHERAL_BURST(BURST) (((BURST) == DMA_PeripheralBurst_Single) || \
+                                        ((BURST) == DMA_PeripheralBurst_INC4)  || \
+                                        ((BURST) == DMA_PeripheralBurst_INC8)  || \
+                                        ((BURST) == DMA_PeripheralBurst_INC16))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_fifo_status_level 
+  * @{
+  */
+#define DMA_FIFOStatus_Less1QuarterFull   ((uint32_t)0x00000000 << 3)
+#define DMA_FIFOStatus_1QuarterFull       ((uint32_t)0x00000001 << 3)
+#define DMA_FIFOStatus_HalfFull           ((uint32_t)0x00000002 << 3) 
+#define DMA_FIFOStatus_3QuartersFull      ((uint32_t)0x00000003 << 3)
+#define DMA_FIFOStatus_Empty              ((uint32_t)0x00000004 << 3)
+#define DMA_FIFOStatus_Full               ((uint32_t)0x00000005 << 3)
+
+#define IS_DMA_FIFO_STATUS(STATUS) (((STATUS) == DMA_FIFOStatus_Less1QuarterFull ) || \
+                                    ((STATUS) == DMA_FIFOStatus_HalfFull)          || \
+                                    ((STATUS) == DMA_FIFOStatus_1QuarterFull)      || \
+                                    ((STATUS) == DMA_FIFOStatus_3QuartersFull)     || \
+                                    ((STATUS) == DMA_FIFOStatus_Full)              || \
+                                    ((STATUS) == DMA_FIFOStatus_Empty)) 
+/**
+  * @}
+  */ 
+
+/** @defgroup DMA_flags_definition 
+  * @{
+  */
+#define DMA_FLAG_FEIF0                    ((uint32_t)0x10800001)
+#define DMA_FLAG_DMEIF0                   ((uint32_t)0x10800004)
+#define DMA_FLAG_TEIF0                    ((uint32_t)0x10000008)
+#define DMA_FLAG_HTIF0                    ((uint32_t)0x10000010)
+#define DMA_FLAG_TCIF0                    ((uint32_t)0x10000020)
+#define DMA_FLAG_FEIF1                    ((uint32_t)0x10000040)
+#define DMA_FLAG_DMEIF1                   ((uint32_t)0x10000100)
+#define DMA_FLAG_TEIF1                    ((uint32_t)0x10000200)
+#define DMA_FLAG_HTIF1                    ((uint32_t)0x10000400)
+#define DMA_FLAG_TCIF1                    ((uint32_t)0x10000800)
+#define DMA_FLAG_FEIF2                    ((uint32_t)0x10010000)
+#define DMA_FLAG_DMEIF2                   ((uint32_t)0x10040000)
+#define DMA_FLAG_TEIF2                    ((uint32_t)0x10080000)
+#define DMA_FLAG_HTIF2                    ((uint32_t)0x10100000)
+#define DMA_FLAG_TCIF2                    ((uint32_t)0x10200000)
+#define DMA_FLAG_FEIF3                    ((uint32_t)0x10400000)
+#define DMA_FLAG_DMEIF3                   ((uint32_t)0x11000000)
+#define DMA_FLAG_TEIF3                    ((uint32_t)0x12000000)
+#define DMA_FLAG_HTIF3                    ((uint32_t)0x14000000)
+#define DMA_FLAG_TCIF3                    ((uint32_t)0x18000000)
+#define DMA_FLAG_FEIF4                    ((uint32_t)0x20000001)
+#define DMA_FLAG_DMEIF4                   ((uint32_t)0x20000004)
+#define DMA_FLAG_TEIF4                    ((uint32_t)0x20000008)
+#define DMA_FLAG_HTIF4                    ((uint32_t)0x20000010)
+#define DMA_FLAG_TCIF4                    ((uint32_t)0x20000020)
+#define DMA_FLAG_FEIF5                    ((uint32_t)0x20000040)
+#define DMA_FLAG_DMEIF5                   ((uint32_t)0x20000100)
+#define DMA_FLAG_TEIF5                    ((uint32_t)0x20000200)
+#define DMA_FLAG_HTIF5                    ((uint32_t)0x20000400)
+#define DMA_FLAG_TCIF5                    ((uint32_t)0x20000800)
+#define DMA_FLAG_FEIF6                    ((uint32_t)0x20010000)
+#define DMA_FLAG_DMEIF6                   ((uint32_t)0x20040000)
+#define DMA_FLAG_TEIF6                    ((uint32_t)0x20080000)
+#define DMA_FLAG_HTIF6                    ((uint32_t)0x20100000)
+#define DMA_FLAG_TCIF6                    ((uint32_t)0x20200000)
+#define DMA_FLAG_FEIF7                    ((uint32_t)0x20400000)
+#define DMA_FLAG_DMEIF7                   ((uint32_t)0x21000000)
+#define DMA_FLAG_TEIF7                    ((uint32_t)0x22000000)
+#define DMA_FLAG_HTIF7                    ((uint32_t)0x24000000)
+#define DMA_FLAG_TCIF7                    ((uint32_t)0x28000000)
+
+#define IS_DMA_CLEAR_FLAG(FLAG) ((((FLAG) & 0x30000000) != 0x30000000) && (((FLAG) & 0x30000000) != 0) && \
+                                 (((FLAG) & 0xC082F082) == 0x00) && ((FLAG) != 0x00))
+
+#define IS_DMA_GET_FLAG(FLAG) (((FLAG) == DMA_FLAG_TCIF0)  || ((FLAG) == DMA_FLAG_HTIF0)  || \
+                               ((FLAG) == DMA_FLAG_TEIF0)  || ((FLAG) == DMA_FLAG_DMEIF0) || \
+                               ((FLAG) == DMA_FLAG_FEIF0)  || ((FLAG) == DMA_FLAG_TCIF1)  || \
+                               ((FLAG) == DMA_FLAG_HTIF1)  || ((FLAG) == DMA_FLAG_TEIF1)  || \
+                               ((FLAG) == DMA_FLAG_DMEIF1) || ((FLAG) == DMA_FLAG_FEIF1)  || \
+                               ((FLAG) == DMA_FLAG_TCIF2)  || ((FLAG) == DMA_FLAG_HTIF2)  || \
+                               ((FLAG) == DMA_FLAG_TEIF2)  || ((FLAG) == DMA_FLAG_DMEIF2) || \
+                               ((FLAG) == DMA_FLAG_FEIF2)  || ((FLAG) == DMA_FLAG_TCIF3)  || \
+                               ((FLAG) == DMA_FLAG_HTIF3)  || ((FLAG) == DMA_FLAG_TEIF3)  || \
+                               ((FLAG) == DMA_FLAG_DMEIF3) || ((FLAG) == DMA_FLAG_FEIF3)  || \
+                               ((FLAG) == DMA_FLAG_TCIF4)  || ((FLAG) == DMA_FLAG_HTIF4)  || \
+                               ((FLAG) == DMA_FLAG_TEIF4)  || ((FLAG) == DMA_FLAG_DMEIF4) || \
+                               ((FLAG) == DMA_FLAG_FEIF4)  || ((FLAG) == DMA_FLAG_TCIF5)  || \
+                               ((FLAG) == DMA_FLAG_HTIF5)  || ((FLAG) == DMA_FLAG_TEIF5)  || \
+                               ((FLAG) == DMA_FLAG_DMEIF5) || ((FLAG) == DMA_FLAG_FEIF5)  || \
+                               ((FLAG) == DMA_FLAG_TCIF6)  || ((FLAG) == DMA_FLAG_HTIF6)  || \
+                               ((FLAG) == DMA_FLAG_TEIF6)  || ((FLAG) == DMA_FLAG_DMEIF6) || \
+                               ((FLAG) == DMA_FLAG_FEIF6)  || ((FLAG) == DMA_FLAG_TCIF7)  || \
+                               ((FLAG) == DMA_FLAG_HTIF7)  || ((FLAG) == DMA_FLAG_TEIF7)  || \
+                               ((FLAG) == DMA_FLAG_DMEIF7) || ((FLAG) == DMA_FLAG_FEIF7))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_interrupt_enable_definitions 
+  * @{
+  */ 
+#define DMA_IT_TC                         ((uint32_t)0x00000010)
+#define DMA_IT_HT                         ((uint32_t)0x00000008)
+#define DMA_IT_TE                         ((uint32_t)0x00000004)
+#define DMA_IT_DME                        ((uint32_t)0x00000002)
+#define DMA_IT_FE                         ((uint32_t)0x00000080)
+
+#define IS_DMA_CONFIG_IT(IT) ((((IT) & 0xFFFFFF61) == 0x00) && ((IT) != 0x00))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_interrupts_definitions 
+  * @{
+  */ 
+#define DMA_IT_FEIF0                      ((uint32_t)0x90000001)
+#define DMA_IT_DMEIF0                     ((uint32_t)0x10001004)
+#define DMA_IT_TEIF0                      ((uint32_t)0x10002008)
+#define DMA_IT_HTIF0                      ((uint32_t)0x10004010)
+#define DMA_IT_TCIF0                      ((uint32_t)0x10008020)
+#define DMA_IT_FEIF1                      ((uint32_t)0x90000040)
+#define DMA_IT_DMEIF1                     ((uint32_t)0x10001100)
+#define DMA_IT_TEIF1                      ((uint32_t)0x10002200)
+#define DMA_IT_HTIF1                      ((uint32_t)0x10004400)
+#define DMA_IT_TCIF1                      ((uint32_t)0x10008800)
+#define DMA_IT_FEIF2                      ((uint32_t)0x90010000)
+#define DMA_IT_DMEIF2                     ((uint32_t)0x10041000)
+#define DMA_IT_TEIF2                      ((uint32_t)0x10082000)
+#define DMA_IT_HTIF2                      ((uint32_t)0x10104000)
+#define DMA_IT_TCIF2                      ((uint32_t)0x10208000)
+#define DMA_IT_FEIF3                      ((uint32_t)0x90400000)
+#define DMA_IT_DMEIF3                     ((uint32_t)0x11001000)
+#define DMA_IT_TEIF3                      ((uint32_t)0x12002000)
+#define DMA_IT_HTIF3                      ((uint32_t)0x14004000)
+#define DMA_IT_TCIF3                      ((uint32_t)0x18008000)
+#define DMA_IT_FEIF4                      ((uint32_t)0xA0000001)
+#define DMA_IT_DMEIF4                     ((uint32_t)0x20001004)
+#define DMA_IT_TEIF4                      ((uint32_t)0x20002008)
+#define DMA_IT_HTIF4                      ((uint32_t)0x20004010)
+#define DMA_IT_TCIF4                      ((uint32_t)0x20008020)
+#define DMA_IT_FEIF5                      ((uint32_t)0xA0000040)
+#define DMA_IT_DMEIF5                     ((uint32_t)0x20001100)
+#define DMA_IT_TEIF5                      ((uint32_t)0x20002200)
+#define DMA_IT_HTIF5                      ((uint32_t)0x20004400)
+#define DMA_IT_TCIF5                      ((uint32_t)0x20008800)
+#define DMA_IT_FEIF6                      ((uint32_t)0xA0010000)
+#define DMA_IT_DMEIF6                     ((uint32_t)0x20041000)
+#define DMA_IT_TEIF6                      ((uint32_t)0x20082000)
+#define DMA_IT_HTIF6                      ((uint32_t)0x20104000)
+#define DMA_IT_TCIF6                      ((uint32_t)0x20208000)
+#define DMA_IT_FEIF7                      ((uint32_t)0xA0400000)
+#define DMA_IT_DMEIF7                     ((uint32_t)0x21001000)
+#define DMA_IT_TEIF7                      ((uint32_t)0x22002000)
+#define DMA_IT_HTIF7                      ((uint32_t)0x24004000)
+#define DMA_IT_TCIF7                      ((uint32_t)0x28008000)
+
+#define IS_DMA_CLEAR_IT(IT) ((((IT) & 0x30000000) != 0x30000000) && \
+                             (((IT) & 0x30000000) != 0) && ((IT) != 0x00) && \
+                             (((IT) & 0x40820082) == 0x00))
+
+#define IS_DMA_GET_IT(IT) (((IT) == DMA_IT_TCIF0) || ((IT) == DMA_IT_HTIF0)  || \
+                           ((IT) == DMA_IT_TEIF0) || ((IT) == DMA_IT_DMEIF0) || \
+                           ((IT) == DMA_IT_FEIF0) || ((IT) == DMA_IT_TCIF1)  || \
+                           ((IT) == DMA_IT_HTIF1) || ((IT) == DMA_IT_TEIF1)  || \
+                           ((IT) == DMA_IT_DMEIF1)|| ((IT) == DMA_IT_FEIF1)  || \
+                           ((IT) == DMA_IT_TCIF2) || ((IT) == DMA_IT_HTIF2)  || \
+                           ((IT) == DMA_IT_TEIF2) || ((IT) == DMA_IT_DMEIF2) || \
+                           ((IT) == DMA_IT_FEIF2) || ((IT) == DMA_IT_TCIF3)  || \
+                           ((IT) == DMA_IT_HTIF3) || ((IT) == DMA_IT_TEIF3)  || \
+                           ((IT) == DMA_IT_DMEIF3)|| ((IT) == DMA_IT_FEIF3)  || \
+                           ((IT) == DMA_IT_TCIF4) || ((IT) == DMA_IT_HTIF4)  || \
+                           ((IT) == DMA_IT_TEIF4) || ((IT) == DMA_IT_DMEIF4) || \
+                           ((IT) == DMA_IT_FEIF4) || ((IT) == DMA_IT_TCIF5)  || \
+                           ((IT) == DMA_IT_HTIF5) || ((IT) == DMA_IT_TEIF5)  || \
+                           ((IT) == DMA_IT_DMEIF5)|| ((IT) == DMA_IT_FEIF5)  || \
+                           ((IT) == DMA_IT_TCIF6) || ((IT) == DMA_IT_HTIF6)  || \
+                           ((IT) == DMA_IT_TEIF6) || ((IT) == DMA_IT_DMEIF6) || \
+                           ((IT) == DMA_IT_FEIF6) || ((IT) == DMA_IT_TCIF7)  || \
+                           ((IT) == DMA_IT_HTIF7) || ((IT) == DMA_IT_TEIF7)  || \
+                           ((IT) == DMA_IT_DMEIF7)|| ((IT) == DMA_IT_FEIF7))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_peripheral_increment_offset 
+  * @{
+  */ 
+#define DMA_PINCOS_Psize                  ((uint32_t)0x00000000)
+#define DMA_PINCOS_WordAligned            ((uint32_t)0x00008000)
+
+#define IS_DMA_PINCOS_SIZE(SIZE) (((SIZE) == DMA_PINCOS_Psize) || \
+                                  ((SIZE) == DMA_PINCOS_WordAligned))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_flow_controller_definitions 
+  * @{
+  */ 
+#define DMA_FlowCtrl_Memory               ((uint32_t)0x00000000)
+#define DMA_FlowCtrl_Peripheral           ((uint32_t)0x00000020)
+
+#define IS_DMA_FLOW_CTRL(CTRL) (((CTRL) == DMA_FlowCtrl_Memory) || \
+                                ((CTRL) == DMA_FlowCtrl_Peripheral))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup DMA_memory_targets_definitions 
+  * @{
+  */ 
+#define DMA_Memory_0                      ((uint32_t)0x00000000)
+#define DMA_Memory_1                      ((uint32_t)0x00080000)
+
+#define IS_DMA_CURRENT_MEM(MEM) (((MEM) == DMA_Memory_0) || ((MEM) == DMA_Memory_1))
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the DMA configuration to the default reset state *****/ 
+void DMA_DeInit(DMA_Stream_TypeDef* DMAy_Streamx);
+
+/* Initialization and Configuration functions *********************************/
+void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct);
+void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);
+void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState);
+
+/* Optional Configuration functions *******************************************/
+void DMA_PeriphIncOffsetSizeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_Pincos);
+void DMA_FlowControllerConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FlowCtrl);
+
+/* Data Counter functions *****************************************************/
+void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);
+uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);
+
+/* Double Buffer mode functions ***********************************************/
+void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr,
+                                uint32_t DMA_CurrentMemory);
+void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState);
+void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr,
+                            uint32_t DMA_MemoryTarget);
+uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx);
+
+/* Interrupts and flags management functions **********************************/
+FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx);
+uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx);
+FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
+void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
+void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState);
+ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
+void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_DMA_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+

+ 175 - 0
app/Libraries/inc/stm32f2xx_exti.h

@@ -0,0 +1,175 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_exti.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the EXTI firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_EXTI_H
+#define __STM32F2xx_EXTI_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup EXTI
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  EXTI mode enumeration  
+  */
+
+typedef enum
+{
+  EXTI_Mode_Interrupt = 0x00,
+  EXTI_Mode_Event = 0x04
+}EXTIMode_TypeDef;
+
+#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event))
+
+/** 
+  * @brief  EXTI Trigger enumeration  
+  */
+
+typedef enum
+{
+  EXTI_Trigger_Rising = 0x08,
+  EXTI_Trigger_Falling = 0x0C,  
+  EXTI_Trigger_Rising_Falling = 0x10
+}EXTITrigger_TypeDef;
+
+#define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \
+                                  ((TRIGGER) == EXTI_Trigger_Falling) || \
+                                  ((TRIGGER) == EXTI_Trigger_Rising_Falling))
+/** 
+  * @brief  EXTI Init Structure definition  
+  */
+
+typedef struct
+{
+  uint32_t EXTI_Line;               /*!< Specifies the EXTI lines to be enabled or disabled.
+                                         This parameter can be any combination value of @ref EXTI_Lines */
+   
+  EXTIMode_TypeDef EXTI_Mode;       /*!< Specifies the mode for the EXTI lines.
+                                         This parameter can be a value of @ref EXTIMode_TypeDef */
+
+  EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
+                                         This parameter can be a value of @ref EXTITrigger_TypeDef */
+
+  FunctionalState EXTI_LineCmd;     /*!< Specifies the new state of the selected EXTI lines.
+                                         This parameter can be set either to ENABLE or DISABLE */ 
+}EXTI_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup EXTI_Exported_Constants
+  * @{
+  */
+
+/** @defgroup EXTI_Lines 
+  * @{
+  */
+
+#define EXTI_Line0       ((uint32_t)0x00001)     /*!< External interrupt line 0 */
+#define EXTI_Line1       ((uint32_t)0x00002)     /*!< External interrupt line 1 */
+#define EXTI_Line2       ((uint32_t)0x00004)     /*!< External interrupt line 2 */
+#define EXTI_Line3       ((uint32_t)0x00008)     /*!< External interrupt line 3 */
+#define EXTI_Line4       ((uint32_t)0x00010)     /*!< External interrupt line 4 */
+#define EXTI_Line5       ((uint32_t)0x00020)     /*!< External interrupt line 5 */
+#define EXTI_Line6       ((uint32_t)0x00040)     /*!< External interrupt line 6 */
+#define EXTI_Line7       ((uint32_t)0x00080)     /*!< External interrupt line 7 */
+#define EXTI_Line8       ((uint32_t)0x00100)     /*!< External interrupt line 8 */
+#define EXTI_Line9       ((uint32_t)0x00200)     /*!< External interrupt line 9 */
+#define EXTI_Line10      ((uint32_t)0x00400)     /*!< External interrupt line 10 */
+#define EXTI_Line11      ((uint32_t)0x00800)     /*!< External interrupt line 11 */
+#define EXTI_Line12      ((uint32_t)0x01000)     /*!< External interrupt line 12 */
+#define EXTI_Line13      ((uint32_t)0x02000)     /*!< External interrupt line 13 */
+#define EXTI_Line14      ((uint32_t)0x04000)     /*!< External interrupt line 14 */
+#define EXTI_Line15      ((uint32_t)0x08000)     /*!< External interrupt line 15 */
+#define EXTI_Line16      ((uint32_t)0x10000)     /*!< External interrupt line 16 Connected to the PVD Output */
+#define EXTI_Line17      ((uint32_t)0x20000)     /*!< External interrupt line 17 Connected to the RTC Alarm event */
+#define EXTI_Line18      ((uint32_t)0x40000)     /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */                                    
+#define EXTI_Line19      ((uint32_t)0x80000)     /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
+#define EXTI_Line20      ((uint32_t)0x00100000)  /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event  */
+#define EXTI_Line21      ((uint32_t)0x00200000)  /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */                                               
+#define EXTI_Line22      ((uint32_t)0x00400000)  /*!< External interrupt line 22 Connected to the RTC Wakeup event */                                               
+                                          
+#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFF800000) == 0x00) && ((LINE) != (uint16_t)0x00))
+
+#define IS_GET_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \
+                                ((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \
+                                ((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5) || \
+                                ((LINE) == EXTI_Line6) || ((LINE) == EXTI_Line7) || \
+                                ((LINE) == EXTI_Line8) || ((LINE) == EXTI_Line9) || \
+                                ((LINE) == EXTI_Line10) || ((LINE) == EXTI_Line11) || \
+                                ((LINE) == EXTI_Line12) || ((LINE) == EXTI_Line13) || \
+                                ((LINE) == EXTI_Line14) || ((LINE) == EXTI_Line15) || \
+                                ((LINE) == EXTI_Line16) || ((LINE) == EXTI_Line17) || \
+                                ((LINE) == EXTI_Line18) || ((LINE) == EXTI_Line19) || \
+                                ((LINE) == EXTI_Line20) || ((LINE) == EXTI_Line21) ||\
+                                ((LINE) == EXTI_Line22))
+                    
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/*  Function used to set the EXTI configuration to the default reset state *****/
+void EXTI_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
+void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
+void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
+
+/* Interrupts and flags management functions **********************************/
+FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
+void EXTI_ClearFlag(uint32_t EXTI_Line);
+ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
+void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_EXTI_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 332 - 0
app/Libraries/inc/stm32f2xx_flash.h

@@ -0,0 +1,332 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_flash.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the FLASH 
+  *          firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_FLASH_H
+#define __STM32F2xx_FLASH_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup FLASH
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/** 
+  * @brief FLASH Status  
+  */ 
+typedef enum
+{ 
+  FLASH_BUSY = 1,
+  FLASH_ERROR_PGS,
+  FLASH_ERROR_PGP,
+  FLASH_ERROR_PGA,
+  FLASH_ERROR_WRP,
+  FLASH_ERROR_PROGRAM,
+  FLASH_ERROR_OPERATION,
+  FLASH_COMPLETE
+}FLASH_Status;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup FLASH_Exported_Constants
+  * @{
+  */  
+
+/** @defgroup Flash_Latency 
+  * @{
+  */ 
+#define FLASH_Latency_0                ((uint8_t)0x0000)  /*!< FLASH Zero Latency cycle */
+#define FLASH_Latency_1                ((uint8_t)0x0001)  /*!< FLASH One Latency cycle */
+#define FLASH_Latency_2                ((uint8_t)0x0002)  /*!< FLASH Two Latency cycles */
+#define FLASH_Latency_3                ((uint8_t)0x0003)  /*!< FLASH Three Latency cycles */
+#define FLASH_Latency_4                ((uint8_t)0x0004)  /*!< FLASH Four Latency cycles */
+#define FLASH_Latency_5                ((uint8_t)0x0005)  /*!< FLASH Five Latency cycles */
+#define FLASH_Latency_6                ((uint8_t)0x0006)  /*!< FLASH Six Latency cycles */
+#define FLASH_Latency_7                ((uint8_t)0x0007)  /*!< FLASH Seven Latency cycles */
+
+#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_Latency_0) || \
+                                   ((LATENCY) == FLASH_Latency_1) || \
+                                   ((LATENCY) == FLASH_Latency_2) || \
+                                   ((LATENCY) == FLASH_Latency_3) || \
+                                   ((LATENCY) == FLASH_Latency_4) || \
+                                   ((LATENCY) == FLASH_Latency_5) || \
+                                   ((LATENCY) == FLASH_Latency_6) || \
+                                   ((LATENCY) == FLASH_Latency_7))
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Voltage_Range 
+  * @{
+  */ 
+#define VoltageRange_1        ((uint8_t)0x00)  /*!< Device operating range: 1.8V to 2.1V */
+#define VoltageRange_2        ((uint8_t)0x01)  /*!<Device operating range: 2.1V to 2.7V */
+#define VoltageRange_3        ((uint8_t)0x02)  /*!<Device operating range: 2.7V to 3.6V */
+#define VoltageRange_4        ((uint8_t)0x03)  /*!<Device operating range: 2.7V to 3.6V + External Vpp */
+
+#define IS_VOLTAGERANGE(RANGE)(((RANGE) == VoltageRange_1) || \
+                               ((RANGE) == VoltageRange_2) || \
+                               ((RANGE) == VoltageRange_3) || \
+                               ((RANGE) == VoltageRange_4))                                                                                                               
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Sectors
+  * @{
+  */ 
+#define FLASH_Sector_0     ((uint16_t)0x0000) /*!< Sector Number 0 */
+#define FLASH_Sector_1     ((uint16_t)0x0008) /*!< Sector Number 1 */
+#define FLASH_Sector_2     ((uint16_t)0x0010) /*!< Sector Number 2 */
+#define FLASH_Sector_3     ((uint16_t)0x0018) /*!< Sector Number 3 */
+#define FLASH_Sector_4     ((uint16_t)0x0020) /*!< Sector Number 4 */
+#define FLASH_Sector_5     ((uint16_t)0x0028) /*!< Sector Number 5 */
+#define FLASH_Sector_6     ((uint16_t)0x0030) /*!< Sector Number 6 */
+#define FLASH_Sector_7     ((uint16_t)0x0038) /*!< Sector Number 7 */
+#define FLASH_Sector_8     ((uint16_t)0x0040) /*!< Sector Number 8 */
+#define FLASH_Sector_9     ((uint16_t)0x0048) /*!< Sector Number 9 */
+#define FLASH_Sector_10    ((uint16_t)0x0050) /*!< Sector Number 10 */
+#define FLASH_Sector_11    ((uint16_t)0x0058) /*!< Sector Number 11 */
+#define IS_FLASH_SECTOR(SECTOR) (((SECTOR) == FLASH_Sector_0) || ((SECTOR) == FLASH_Sector_1) ||\
+                                 ((SECTOR) == FLASH_Sector_2) || ((SECTOR) == FLASH_Sector_3) ||\
+                                 ((SECTOR) == FLASH_Sector_4) || ((SECTOR) == FLASH_Sector_5) ||\
+                                 ((SECTOR) == FLASH_Sector_6) || ((SECTOR) == FLASH_Sector_7) ||\
+                                 ((SECTOR) == FLASH_Sector_8) || ((SECTOR) == FLASH_Sector_9) ||\
+                                 ((SECTOR) == FLASH_Sector_10) || ((SECTOR) == FLASH_Sector_11))
+#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x080FFFFF)) ||\
+                                   (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) < 0x1FFF7A0F)))  
+/**
+  * @}
+  */ 
+
+/** @defgroup Option_Bytes_Write_Protection 
+  * @{
+  */ 
+#define OB_WRP_Sector_0       ((uint32_t)0x00000001) /*!< Write protection of Sector0 */
+#define OB_WRP_Sector_1       ((uint32_t)0x00000002) /*!< Write protection of Sector1 */
+#define OB_WRP_Sector_2       ((uint32_t)0x00000004) /*!< Write protection of Sector2 */
+#define OB_WRP_Sector_3       ((uint32_t)0x00000008) /*!< Write protection of Sector3 */
+#define OB_WRP_Sector_4       ((uint32_t)0x00000010) /*!< Write protection of Sector4 */
+#define OB_WRP_Sector_5       ((uint32_t)0x00000020) /*!< Write protection of Sector5 */
+#define OB_WRP_Sector_6       ((uint32_t)0x00000040) /*!< Write protection of Sector6 */
+#define OB_WRP_Sector_7       ((uint32_t)0x00000080) /*!< Write protection of Sector7 */
+#define OB_WRP_Sector_8       ((uint32_t)0x00000100) /*!< Write protection of Sector8 */
+#define OB_WRP_Sector_9       ((uint32_t)0x00000200) /*!< Write protection of Sector9 */
+#define OB_WRP_Sector_10      ((uint32_t)0x00000400) /*!< Write protection of Sector10 */
+#define OB_WRP_Sector_11      ((uint32_t)0x00000800) /*!< Write protection of Sector11 */
+#define OB_WRP_Sector_All     ((uint32_t)0x00000FFF) /*!< Write protection of all Sectors */
+
+#define IS_OB_WRP(SECTOR)((((SECTOR) & (uint32_t)0xFFFFF000) == 0x00000000) && ((SECTOR) != 0x00000000))
+/**
+  * @}
+  */
+
+/** @defgroup FLASH_Option_Bytes_Read_Protection 
+  * @{
+  */
+#define OB_RDP_Level_0   ((uint8_t)0xAA)
+#define OB_RDP_Level_1   ((uint8_t)0x55)
+/*#define OB_RDP_Level_2   ((uint8_t)0xCC)*/ /*!< Warning: When enabling read protection level 2 
+                                                  it's no more possible to go back to level 1 or 0 */
+#define IS_OB_RDP(LEVEL) (((LEVEL) == OB_RDP_Level_0)||\
+                          ((LEVEL) == OB_RDP_Level_1))/*||\
+                          ((LEVEL) == OB_RDP_Level_2))*/
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Option_Bytes_IWatchdog 
+  * @{
+  */ 
+#define OB_IWDG_SW                     ((uint8_t)0x20)  /*!< Software IWDG selected */
+#define OB_IWDG_HW                     ((uint8_t)0x00)  /*!< Hardware IWDG selected */
+#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW))
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Option_Bytes_nRST_STOP 
+  * @{
+  */ 
+#define OB_STOP_NoRST                  ((uint8_t)0x40) /*!< No reset generated when entering in STOP */
+#define OB_STOP_RST                    ((uint8_t)0x00) /*!< Reset generated when entering in STOP */
+#define IS_OB_STOP_SOURCE(SOURCE) (((SOURCE) == OB_STOP_NoRST) || ((SOURCE) == OB_STOP_RST))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FLASH_Option_Bytes_nRST_STDBY 
+  * @{
+  */ 
+#define OB_STDBY_NoRST                 ((uint8_t)0x80) /*!< No reset generated when entering in STANDBY */
+#define OB_STDBY_RST                   ((uint8_t)0x00) /*!< Reset generated when entering in STANDBY */
+#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NoRST) || ((SOURCE) == OB_STDBY_RST))
+/**
+  * @}
+  */
+  
+/** @defgroup FLASH_BOR_Reset_Level 
+  * @{
+  */  
+#define OB_BOR_LEVEL3          ((uint8_t)0x00)  /*!< Supply voltage ranges from 2.70 to 3.60 V */
+#define OB_BOR_LEVEL2          ((uint8_t)0x04)  /*!< Supply voltage ranges from 2.40 to 2.70 V */
+#define OB_BOR_LEVEL1          ((uint8_t)0x08)  /*!< Supply voltage ranges from 2.10 to 2.40 V */
+#define OB_BOR_OFF             ((uint8_t)0x0C)  /*!< Supply voltage ranges from 1.62 to 2.10 V */
+#define IS_OB_BOR(LEVEL) (((LEVEL) == OB_BOR_LEVEL1) || ((LEVEL) == OB_BOR_LEVEL2) ||\
+                          ((LEVEL) == OB_BOR_LEVEL3) || ((LEVEL) == OB_BOR_OFF))
+/**
+  * @}
+  */
+
+/** @defgroup FLASH_Interrupts 
+  * @{
+  */ 
+#define FLASH_IT_EOP                   ((uint32_t)0x01000000)  /*!< End of FLASH Operation Interrupt source */
+#define FLASH_IT_ERR                   ((uint32_t)0x02000000)  /*!< Error Interrupt source */
+#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0xFCFFFFFF) == 0x00000000) && ((IT) != 0x00000000))
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Flags 
+  * @{
+  */ 
+#define FLASH_FLAG_EOP                 ((uint32_t)0x00000001)  /*!< FLASH End of Operation flag */
+#define FLASH_FLAG_OPERR               ((uint32_t)0x00000002)  /*!< FLASH operation Error flag */
+#define FLASH_FLAG_WRPERR              ((uint32_t)0x00000010)  /*!< FLASH Write protected error flag */
+#define FLASH_FLAG_PGAERR              ((uint32_t)0x00000020)  /*!< FLASH Programming Alignment error flag */
+#define FLASH_FLAG_PGPERR              ((uint32_t)0x00000040)  /*!< FLASH Programming Parallelism error flag  */
+#define FLASH_FLAG_PGSERR              ((uint32_t)0x00000080)  /*!< FLASH Programming Sequence error flag  */
+#define FLASH_FLAG_BSY                 ((uint32_t)0x00010000)  /*!< FLASH Busy flag */ 
+#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFF0C) == 0x00000000) && ((FLAG) != 0x00000000))
+#define IS_FLASH_GET_FLAG(FLAG)  (((FLAG) == FLASH_FLAG_EOP) || ((FLAG) == FLASH_FLAG_OPERR) || \
+                                  ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_PGAERR) || \
+                                  ((FLAG) == FLASH_FLAG_PGPERR) || ((FLAG) == FLASH_FLAG_PGSERR) || \
+                                  ((FLAG) == FLASH_FLAG_BSY))
+/**
+  * @}
+  */
+
+/** @defgroup FLASH_Program_Parallelism   
+  * @{
+  */
+#define FLASH_PSIZE_BYTE           ((uint32_t)0x00000000)
+#define FLASH_PSIZE_HALF_WORD      ((uint32_t)0x00000100)
+#define FLASH_PSIZE_WORD           ((uint32_t)0x00000200)
+#define FLASH_PSIZE_DOUBLE_WORD    ((uint32_t)0x00000300)
+#define CR_PSIZE_MASK              ((uint32_t)0xFFFFFCFF)
+/**
+  * @}
+  */ 
+
+/** @defgroup FLASH_Keys 
+  * @{
+  */ 
+#define RDP_KEY                  ((uint16_t)0x00A5)
+#define FLASH_KEY1               ((uint32_t)0x45670123)
+#define FLASH_KEY2               ((uint32_t)0xCDEF89AB)
+#define FLASH_OPT_KEY1           ((uint32_t)0x08192A3B)
+#define FLASH_OPT_KEY2           ((uint32_t)0x4C5D6E7F)
+/**
+  * @}
+  */ 
+
+/** 
+  * @brief   ACR register byte 0 (Bits[8:0]) base address  
+  */ 
+#define ACR_BYTE0_ADDRESS           ((uint32_t)0x40023C00) 
+/** 
+  * @brief   OPTCR register byte 3 (Bits[24:16]) base address  
+  */ 
+#define OPTCR_BYTE0_ADDRESS         ((uint32_t)0x40023C14)
+#define OPTCR_BYTE1_ADDRESS         ((uint32_t)0x40023C15)
+#define OPTCR_BYTE2_ADDRESS         ((uint32_t)0x40023C16)
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+ 
+/* FLASH Interface configuration functions ************************************/
+void FLASH_SetLatency(uint32_t FLASH_Latency);
+void FLASH_PrefetchBufferCmd(FunctionalState NewState);
+void FLASH_InstructionCacheCmd(FunctionalState NewState);
+void FLASH_DataCacheCmd(FunctionalState NewState);
+void FLASH_InstructionCacheReset(void);
+void FLASH_DataCacheReset(void);
+
+/* FLASH Memory Programming functions *****************************************/   
+void FLASH_Unlock(void);
+void FLASH_Lock(void);
+FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange);
+FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange);
+FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data);
+FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);
+FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
+FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data);
+
+/* Option Bytes Programming functions *****************************************/ 
+void FLASH_OB_Unlock(void);
+void FLASH_OB_Lock(void);
+void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState);
+void FLASH_OB_RDPConfig(uint8_t OB_RDP);
+void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY);
+void FLASH_OB_BORConfig(uint8_t OB_BOR);
+FLASH_Status FLASH_OB_Launch(void);
+uint8_t FLASH_OB_GetUser(void);
+uint16_t FLASH_OB_GetWRP(void);
+FlagStatus FLASH_OB_GetRDP(void);
+uint8_t FLASH_OB_GetBOR(void);
+
+/* Interrupts and flags management functions **********************************/
+void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState);
+FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);
+void FLASH_ClearFlag(uint32_t FLASH_FLAG);
+FLASH_Status FLASH_GetStatus(void);
+FLASH_Status FLASH_WaitForLastOperation(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_FLASH_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 667 - 0
app/Libraries/inc/stm32f2xx_fsmc.h

@@ -0,0 +1,667 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_fsmc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the FSMC firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_FSMC_H
+#define __STM32F2xx_FSMC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup FSMC
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  Timing parameters For NOR/SRAM Banks  
+  */
+typedef struct
+{
+  uint32_t FSMC_AddressSetupTime;       /*!< Defines the number of HCLK cycles to configure
+                                             the duration of the address setup time. 
+                                             This parameter can be a value between 0 and 0xF.
+                                             @note This parameter is not used with synchronous NOR Flash memories. */
+
+  uint32_t FSMC_AddressHoldTime;        /*!< Defines the number of HCLK cycles to configure
+                                             the duration of the address hold time.
+                                             This parameter can be a value between 0 and 0xF. 
+                                             @note This parameter is not used with synchronous NOR Flash memories.*/
+
+  uint32_t FSMC_DataSetupTime;          /*!< Defines the number of HCLK cycles to configure
+                                             the duration of the data setup time.
+                                             This parameter can be a value between 0 and 0xFF.
+                                             @note This parameter is used for SRAMs, ROMs and asynchronous multiplexed NOR Flash memories. */
+
+  uint32_t FSMC_BusTurnAroundDuration;  /*!< Defines the number of HCLK cycles to configure
+                                             the duration of the bus turnaround.
+                                             This parameter can be a value between 0 and 0xF.
+                                             @note This parameter is only used for multiplexed NOR Flash memories. */
+
+  uint32_t FSMC_CLKDivision;            /*!< Defines the period of CLK clock output signal, expressed in number of HCLK cycles.
+                                             This parameter can be a value between 1 and 0xF.
+                                             @note This parameter is not used for asynchronous NOR Flash, SRAM or ROM accesses. */
+
+  uint32_t FSMC_DataLatency;            /*!< Defines the number of memory clock cycles to issue
+                                             to the memory before getting the first data.
+                                             The parameter value depends on the memory type as shown below:
+                                              - It must be set to 0 in case of a CRAM
+                                              - It is don't care in asynchronous NOR, SRAM or ROM accesses
+                                              - It may assume a value between 0 and 0xF in NOR Flash memories
+                                                with synchronous burst mode enable */
+
+  uint32_t FSMC_AccessMode;             /*!< Specifies the asynchronous access mode. 
+                                             This parameter can be a value of @ref FSMC_Access_Mode */
+}FSMC_NORSRAMTimingInitTypeDef;
+
+/** 
+  * @brief  FSMC NOR/SRAM Init structure definition
+  */
+typedef struct
+{
+  uint32_t FSMC_Bank;                /*!< Specifies the NOR/SRAM memory bank that will be used.
+                                          This parameter can be a value of @ref FSMC_NORSRAM_Bank */
+
+  uint32_t FSMC_DataAddressMux;      /*!< Specifies whether the address and data values are
+                                          multiplexed on the databus or not. 
+                                          This parameter can be a value of @ref FSMC_Data_Address_Bus_Multiplexing */
+
+  uint32_t FSMC_MemoryType;          /*!< Specifies the type of external memory attached to
+                                          the corresponding memory bank.
+                                          This parameter can be a value of @ref FSMC_Memory_Type */
+
+  uint32_t FSMC_MemoryDataWidth;     /*!< Specifies the external memory device width.
+                                          This parameter can be a value of @ref FSMC_Data_Width */
+
+  uint32_t FSMC_BurstAccessMode;     /*!< Enables or disables the burst access mode for Flash memory,
+                                          valid only with synchronous burst Flash memories.
+                                          This parameter can be a value of @ref FSMC_Burst_Access_Mode */
+
+  uint32_t FSMC_AsynchronousWait;     /*!< Enables or disables wait signal during asynchronous transfers,
+                                          valid only with asynchronous Flash memories.
+                                          This parameter can be a value of @ref FSMC_AsynchronousWait */                                          
+
+  uint32_t FSMC_WaitSignalPolarity;  /*!< Specifies the wait signal polarity, valid only when accessing
+                                          the Flash memory in burst mode.
+                                          This parameter can be a value of @ref FSMC_Wait_Signal_Polarity */
+
+  uint32_t FSMC_WrapMode;            /*!< Enables or disables the Wrapped burst access mode for Flash
+                                          memory, valid only when accessing Flash memories in burst mode.
+                                          This parameter can be a value of @ref FSMC_Wrap_Mode */
+
+  uint32_t FSMC_WaitSignalActive;    /*!< Specifies if the wait signal is asserted by the memory one
+                                          clock cycle before the wait state or during the wait state,
+                                          valid only when accessing memories in burst mode. 
+                                          This parameter can be a value of @ref FSMC_Wait_Timing */
+
+  uint32_t FSMC_WriteOperation;      /*!< Enables or disables the write operation in the selected bank by the FSMC. 
+                                          This parameter can be a value of @ref FSMC_Write_Operation */
+
+  uint32_t FSMC_WaitSignal;          /*!< Enables or disables the wait-state insertion via wait
+                                          signal, valid for Flash memory access in burst mode. 
+                                          This parameter can be a value of @ref FSMC_Wait_Signal */
+
+  uint32_t FSMC_ExtendedMode;        /*!< Enables or disables the extended mode.
+                                          This parameter can be a value of @ref FSMC_Extended_Mode */
+
+  uint32_t FSMC_WriteBurst;          /*!< Enables or disables the write burst operation.
+                                          This parameter can be a value of @ref FSMC_Write_Burst */ 
+
+  FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /*!< Timing Parameters for write and read access if the  ExtendedMode is not used*/  
+
+  FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;     /*!< Timing Parameters for write access if the  ExtendedMode is used*/      
+}FSMC_NORSRAMInitTypeDef;
+
+/** 
+  * @brief  Timing parameters For FSMC NAND and PCCARD Banks
+  */
+typedef struct
+{
+  uint32_t FSMC_SetupTime;      /*!< Defines the number of HCLK cycles to setup address before
+                                     the command assertion for NAND-Flash read or write access
+                                     to common/Attribute or I/O memory space (depending on
+                                     the memory space timing to be configured).
+                                     This parameter can be a value between 0 and 0xFF.*/
+
+  uint32_t FSMC_WaitSetupTime;  /*!< Defines the minimum number of HCLK cycles to assert the
+                                     command for NAND-Flash read or write access to
+                                     common/Attribute or I/O memory space (depending on the
+                                     memory space timing to be configured). 
+                                     This parameter can be a number between 0x00 and 0xFF */
+
+  uint32_t FSMC_HoldSetupTime;  /*!< Defines the number of HCLK clock cycles to hold address
+                                     (and data for write access) after the command deassertion
+                                     for NAND-Flash read or write access to common/Attribute
+                                     or I/O memory space (depending on the memory space timing
+                                     to be configured).
+                                     This parameter can be a number between 0x00 and 0xFF */
+
+  uint32_t FSMC_HiZSetupTime;   /*!< Defines the number of HCLK clock cycles during which the
+                                     databus is kept in HiZ after the start of a NAND-Flash
+                                     write access to common/Attribute or I/O memory space (depending
+                                     on the memory space timing to be configured).
+                                     This parameter can be a number between 0x00 and 0xFF */
+}FSMC_NAND_PCCARDTimingInitTypeDef;
+
+/** 
+  * @brief  FSMC NAND Init structure definition
+  */
+typedef struct
+{
+  uint32_t FSMC_Bank;              /*!< Specifies the NAND memory bank that will be used.
+                                      This parameter can be a value of @ref FSMC_NAND_Bank */
+
+  uint32_t FSMC_Waitfeature;      /*!< Enables or disables the Wait feature for the NAND Memory Bank.
+                                       This parameter can be any value of @ref FSMC_Wait_feature */
+
+  uint32_t FSMC_MemoryDataWidth;  /*!< Specifies the external memory device width.
+                                       This parameter can be any value of @ref FSMC_Data_Width */
+
+  uint32_t FSMC_ECC;              /*!< Enables or disables the ECC computation.
+                                       This parameter can be any value of @ref FSMC_ECC */
+
+  uint32_t FSMC_ECCPageSize;      /*!< Defines the page size for the extended ECC.
+                                       This parameter can be any value of @ref FSMC_ECC_Page_Size */
+
+  uint32_t FSMC_TCLRSetupTime;    /*!< Defines the number of HCLK cycles to configure the
+                                       delay between CLE low and RE low.
+                                       This parameter can be a value between 0 and 0xFF. */
+
+  uint32_t FSMC_TARSetupTime;     /*!< Defines the number of HCLK cycles to configure the
+                                       delay between ALE low and RE low.
+                                       This parameter can be a number between 0x0 and 0xFF */ 
+
+  FSMC_NAND_PCCARDTimingInitTypeDef*  FSMC_CommonSpaceTimingStruct;   /*!< FSMC Common Space Timing */ 
+
+  FSMC_NAND_PCCARDTimingInitTypeDef*  FSMC_AttributeSpaceTimingStruct; /*!< FSMC Attribute Space Timing */
+}FSMC_NANDInitTypeDef;
+
+/** 
+  * @brief  FSMC PCCARD Init structure definition
+  */
+
+typedef struct
+{
+  uint32_t FSMC_Waitfeature;    /*!< Enables or disables the Wait feature for the Memory Bank.
+                                    This parameter can be any value of @ref FSMC_Wait_feature */
+
+  uint32_t FSMC_TCLRSetupTime;  /*!< Defines the number of HCLK cycles to configure the
+                                     delay between CLE low and RE low.
+                                     This parameter can be a value between 0 and 0xFF. */
+
+  uint32_t FSMC_TARSetupTime;   /*!< Defines the number of HCLK cycles to configure the
+                                     delay between ALE low and RE low.
+                                     This parameter can be a number between 0x0 and 0xFF */ 
+
+  
+  FSMC_NAND_PCCARDTimingInitTypeDef*  FSMC_CommonSpaceTimingStruct; /*!< FSMC Common Space Timing */
+
+  FSMC_NAND_PCCARDTimingInitTypeDef*  FSMC_AttributeSpaceTimingStruct;  /*!< FSMC Attribute Space Timing */ 
+  
+  FSMC_NAND_PCCARDTimingInitTypeDef*  FSMC_IOSpaceTimingStruct; /*!< FSMC IO Space Timing */  
+}FSMC_PCCARDInitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup FSMC_Exported_Constants
+  * @{
+  */
+
+/** @defgroup FSMC_NORSRAM_Bank 
+  * @{
+  */
+#define FSMC_Bank1_NORSRAM1                      ((uint32_t)0x00000000)
+#define FSMC_Bank1_NORSRAM2                      ((uint32_t)0x00000002)
+#define FSMC_Bank1_NORSRAM3                      ((uint32_t)0x00000004)
+#define FSMC_Bank1_NORSRAM4                      ((uint32_t)0x00000006)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_NAND_Bank 
+  * @{
+  */  
+#define FSMC_Bank2_NAND                          ((uint32_t)0x00000010)
+#define FSMC_Bank3_NAND                          ((uint32_t)0x00000100)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_PCCARD_Bank 
+  * @{
+  */    
+#define FSMC_Bank4_PCCARD                        ((uint32_t)0x00001000)
+/**
+  * @}
+  */
+
+#define IS_FSMC_NORSRAM_BANK(BANK) (((BANK) == FSMC_Bank1_NORSRAM1) || \
+                                    ((BANK) == FSMC_Bank1_NORSRAM2) || \
+                                    ((BANK) == FSMC_Bank1_NORSRAM3) || \
+                                    ((BANK) == FSMC_Bank1_NORSRAM4))
+
+#define IS_FSMC_NAND_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
+                                 ((BANK) == FSMC_Bank3_NAND))
+
+#define IS_FSMC_GETFLAG_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
+                                    ((BANK) == FSMC_Bank3_NAND) || \
+                                    ((BANK) == FSMC_Bank4_PCCARD))
+
+#define IS_FSMC_IT_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
+                               ((BANK) == FSMC_Bank3_NAND) || \
+                               ((BANK) == FSMC_Bank4_PCCARD))
+
+/** @defgroup FSMC_NOR_SRAM_Controller 
+  * @{
+  */
+
+/** @defgroup FSMC_Data_Address_Bus_Multiplexing 
+  * @{
+  */
+
+#define FSMC_DataAddressMux_Disable                ((uint32_t)0x00000000)
+#define FSMC_DataAddressMux_Enable                 ((uint32_t)0x00000002)
+#define IS_FSMC_MUX(MUX) (((MUX) == FSMC_DataAddressMux_Disable) || \
+                          ((MUX) == FSMC_DataAddressMux_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Memory_Type 
+  * @{
+  */
+
+#define FSMC_MemoryType_SRAM                     ((uint32_t)0x00000000)
+#define FSMC_MemoryType_PSRAM                    ((uint32_t)0x00000004)
+#define FSMC_MemoryType_NOR                      ((uint32_t)0x00000008)
+#define IS_FSMC_MEMORY(MEMORY) (((MEMORY) == FSMC_MemoryType_SRAM) || \
+                                ((MEMORY) == FSMC_MemoryType_PSRAM)|| \
+                                ((MEMORY) == FSMC_MemoryType_NOR))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Data_Width 
+  * @{
+  */
+
+#define FSMC_MemoryDataWidth_8b                  ((uint32_t)0x00000000)
+#define FSMC_MemoryDataWidth_16b                 ((uint32_t)0x00000010)
+#define IS_FSMC_MEMORY_WIDTH(WIDTH) (((WIDTH) == FSMC_MemoryDataWidth_8b) || \
+                                     ((WIDTH) == FSMC_MemoryDataWidth_16b))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Burst_Access_Mode 
+  * @{
+  */
+
+#define FSMC_BurstAccessMode_Disable             ((uint32_t)0x00000000) 
+#define FSMC_BurstAccessMode_Enable              ((uint32_t)0x00000100)
+#define IS_FSMC_BURSTMODE(STATE) (((STATE) == FSMC_BurstAccessMode_Disable) || \
+                                  ((STATE) == FSMC_BurstAccessMode_Enable))
+/**
+  * @}
+  */
+    
+/** @defgroup FSMC_AsynchronousWait 
+  * @{
+  */
+#define FSMC_AsynchronousWait_Disable            ((uint32_t)0x00000000)
+#define FSMC_AsynchronousWait_Enable             ((uint32_t)0x00008000)
+#define IS_FSMC_ASYNWAIT(STATE) (((STATE) == FSMC_AsynchronousWait_Disable) || \
+                                 ((STATE) == FSMC_AsynchronousWait_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Wait_Signal_Polarity 
+  * @{
+  */
+#define FSMC_WaitSignalPolarity_Low              ((uint32_t)0x00000000)
+#define FSMC_WaitSignalPolarity_High             ((uint32_t)0x00000200)
+#define IS_FSMC_WAIT_POLARITY(POLARITY) (((POLARITY) == FSMC_WaitSignalPolarity_Low) || \
+                                         ((POLARITY) == FSMC_WaitSignalPolarity_High))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Wrap_Mode 
+  * @{
+  */
+#define FSMC_WrapMode_Disable                    ((uint32_t)0x00000000)
+#define FSMC_WrapMode_Enable                     ((uint32_t)0x00000400) 
+#define IS_FSMC_WRAP_MODE(MODE) (((MODE) == FSMC_WrapMode_Disable) || \
+                                 ((MODE) == FSMC_WrapMode_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Wait_Timing 
+  * @{
+  */
+#define FSMC_WaitSignalActive_BeforeWaitState    ((uint32_t)0x00000000)
+#define FSMC_WaitSignalActive_DuringWaitState    ((uint32_t)0x00000800) 
+#define IS_FSMC_WAIT_SIGNAL_ACTIVE(ACTIVE) (((ACTIVE) == FSMC_WaitSignalActive_BeforeWaitState) || \
+                                            ((ACTIVE) == FSMC_WaitSignalActive_DuringWaitState))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Write_Operation 
+  * @{
+  */
+#define FSMC_WriteOperation_Disable                     ((uint32_t)0x00000000)
+#define FSMC_WriteOperation_Enable                      ((uint32_t)0x00001000)
+#define IS_FSMC_WRITE_OPERATION(OPERATION) (((OPERATION) == FSMC_WriteOperation_Disable) || \
+                                            ((OPERATION) == FSMC_WriteOperation_Enable))                         
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Wait_Signal 
+  * @{
+  */
+#define FSMC_WaitSignal_Disable                  ((uint32_t)0x00000000)
+#define FSMC_WaitSignal_Enable                   ((uint32_t)0x00002000) 
+#define IS_FSMC_WAITE_SIGNAL(SIGNAL) (((SIGNAL) == FSMC_WaitSignal_Disable) || \
+                                      ((SIGNAL) == FSMC_WaitSignal_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Extended_Mode 
+  * @{
+  */
+#define FSMC_ExtendedMode_Disable                ((uint32_t)0x00000000)
+#define FSMC_ExtendedMode_Enable                 ((uint32_t)0x00004000)
+
+#define IS_FSMC_EXTENDED_MODE(MODE) (((MODE) == FSMC_ExtendedMode_Disable) || \
+                                     ((MODE) == FSMC_ExtendedMode_Enable)) 
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Write_Burst 
+  * @{
+  */
+
+#define FSMC_WriteBurst_Disable                  ((uint32_t)0x00000000)
+#define FSMC_WriteBurst_Enable                   ((uint32_t)0x00080000) 
+#define IS_FSMC_WRITE_BURST(BURST) (((BURST) == FSMC_WriteBurst_Disable) || \
+                                    ((BURST) == FSMC_WriteBurst_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Address_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_ADDRESS_SETUP_TIME(TIME) ((TIME) <= 0xF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Address_Hold_Time 
+  * @{
+  */
+#define IS_FSMC_ADDRESS_HOLD_TIME(TIME) ((TIME) <= 0xF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Data_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_DATASETUP_TIME(TIME) (((TIME) > 0) && ((TIME) <= 0xFF))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Bus_Turn_around_Duration 
+  * @{
+  */
+#define IS_FSMC_TURNAROUND_TIME(TIME) ((TIME) <= 0xF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_CLK_Division 
+  * @{
+  */
+#define IS_FSMC_CLK_DIV(DIV) ((DIV) <= 0xF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Data_Latency 
+  * @{
+  */
+#define IS_FSMC_DATA_LATENCY(LATENCY) ((LATENCY) <= 0xF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Access_Mode 
+  * @{
+  */
+#define FSMC_AccessMode_A                        ((uint32_t)0x00000000)
+#define FSMC_AccessMode_B                        ((uint32_t)0x10000000) 
+#define FSMC_AccessMode_C                        ((uint32_t)0x20000000)
+#define FSMC_AccessMode_D                        ((uint32_t)0x30000000)
+#define IS_FSMC_ACCESS_MODE(MODE) (((MODE) == FSMC_AccessMode_A) || \
+                                   ((MODE) == FSMC_AccessMode_B) || \
+                                   ((MODE) == FSMC_AccessMode_C) || \
+                                   ((MODE) == FSMC_AccessMode_D))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+  
+/** @defgroup FSMC_NAND_PCCARD_Controller 
+  * @{
+  */
+
+/** @defgroup FSMC_Wait_feature 
+  * @{
+  */
+#define FSMC_Waitfeature_Disable                 ((uint32_t)0x00000000)
+#define FSMC_Waitfeature_Enable                  ((uint32_t)0x00000002)
+#define IS_FSMC_WAIT_FEATURE(FEATURE) (((FEATURE) == FSMC_Waitfeature_Disable) || \
+                                       ((FEATURE) == FSMC_Waitfeature_Enable))
+/**
+  * @}
+  */
+
+
+/** @defgroup FSMC_ECC 
+  * @{
+  */
+#define FSMC_ECC_Disable                         ((uint32_t)0x00000000)
+#define FSMC_ECC_Enable                          ((uint32_t)0x00000040)
+#define IS_FSMC_ECC_STATE(STATE) (((STATE) == FSMC_ECC_Disable) || \
+                                  ((STATE) == FSMC_ECC_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_ECC_Page_Size 
+  * @{
+  */
+#define FSMC_ECCPageSize_256Bytes                ((uint32_t)0x00000000)
+#define FSMC_ECCPageSize_512Bytes                ((uint32_t)0x00020000)
+#define FSMC_ECCPageSize_1024Bytes               ((uint32_t)0x00040000)
+#define FSMC_ECCPageSize_2048Bytes               ((uint32_t)0x00060000)
+#define FSMC_ECCPageSize_4096Bytes               ((uint32_t)0x00080000)
+#define FSMC_ECCPageSize_8192Bytes               ((uint32_t)0x000A0000)
+#define IS_FSMC_ECCPAGE_SIZE(SIZE) (((SIZE) == FSMC_ECCPageSize_256Bytes) || \
+                                    ((SIZE) == FSMC_ECCPageSize_512Bytes) || \
+                                    ((SIZE) == FSMC_ECCPageSize_1024Bytes) || \
+                                    ((SIZE) == FSMC_ECCPageSize_2048Bytes) || \
+                                    ((SIZE) == FSMC_ECCPageSize_4096Bytes) || \
+                                    ((SIZE) == FSMC_ECCPageSize_8192Bytes))
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_TCLR_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_TCLR_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_TAR_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_TAR_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_SETUP_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Wait_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_WAIT_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Hold_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_HOLD_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_HiZ_Setup_Time 
+  * @{
+  */
+#define IS_FSMC_HIZ_TIME(TIME) ((TIME) <= 0xFF)
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Interrupt_sources 
+  * @{
+  */
+#define FSMC_IT_RisingEdge                       ((uint32_t)0x00000008)
+#define FSMC_IT_Level                            ((uint32_t)0x00000010)
+#define FSMC_IT_FallingEdge                      ((uint32_t)0x00000020)
+#define IS_FSMC_IT(IT) ((((IT) & (uint32_t)0xFFFFFFC7) == 0x00000000) && ((IT) != 0x00000000))
+#define IS_FSMC_GET_IT(IT) (((IT) == FSMC_IT_RisingEdge) || \
+                            ((IT) == FSMC_IT_Level) || \
+                            ((IT) == FSMC_IT_FallingEdge)) 
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Flags 
+  * @{
+  */
+#define FSMC_FLAG_RisingEdge                     ((uint32_t)0x00000001)
+#define FSMC_FLAG_Level                          ((uint32_t)0x00000002)
+#define FSMC_FLAG_FallingEdge                    ((uint32_t)0x00000004)
+#define FSMC_FLAG_FEMPT                          ((uint32_t)0x00000040)
+#define IS_FSMC_GET_FLAG(FLAG) (((FLAG) == FSMC_FLAG_RisingEdge) || \
+                                ((FLAG) == FSMC_FLAG_Level) || \
+                                ((FLAG) == FSMC_FLAG_FallingEdge) || \
+                                ((FLAG) == FSMC_FLAG_FEMPT))
+
+#define IS_FSMC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFFF8) == 0x00000000) && ((FLAG) != 0x00000000))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/* NOR/SRAM Controller functions **********************************************/
+void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank);
+void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);
+void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);
+void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState);
+
+/* NAND Controller functions **************************************************/
+void FSMC_NANDDeInit(uint32_t FSMC_Bank);
+void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct);
+void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct);
+void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState);
+void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState);
+uint32_t FSMC_GetECC(uint32_t FSMC_Bank);
+
+/* PCCARD Controller functions ************************************************/
+void FSMC_PCCARDDeInit(void);
+void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct);
+void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct);
+void FSMC_PCCARDCmd(FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState);
+FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG);
+void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG);
+ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT);
+void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_FSMC_H */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+

+ 403 - 0
app/Libraries/inc/stm32f2xx_gpio.h

@@ -0,0 +1,403 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_gpio.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the GPIO firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_GPIO_H
+#define __STM32F2xx_GPIO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup GPIO
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \
+                                    ((PERIPH) == GPIOB) || \
+                                    ((PERIPH) == GPIOC) || \
+                                    ((PERIPH) == GPIOD) || \
+                                    ((PERIPH) == GPIOE) || \
+                                    ((PERIPH) == GPIOF) || \
+                                    ((PERIPH) == GPIOG) || \
+                                    ((PERIPH) == GPIOH) || \
+                                    ((PERIPH) == GPIOI))
+                                                                
+/** 
+  * @brief  GPIO Configuration Mode enumeration 
+  */   
+typedef enum
+{ 
+  GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */
+  GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */
+  GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */
+  GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
+}GPIOMode_TypeDef;
+#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_IN)  || ((MODE) == GPIO_Mode_OUT) || \
+                            ((MODE) == GPIO_Mode_AF)|| ((MODE) == GPIO_Mode_AN))
+
+/** 
+  * @brief  GPIO Output type enumeration 
+  */  
+typedef enum
+{ 
+  GPIO_OType_PP = 0x00,
+  GPIO_OType_OD = 0x01
+}GPIOOType_TypeDef;
+#define IS_GPIO_OTYPE(OTYPE) (((OTYPE) == GPIO_OType_PP) || ((OTYPE) == GPIO_OType_OD))
+
+
+/** 
+  * @brief  GPIO Output Maximum frequency enumeration 
+  */  
+typedef enum
+{ 
+  GPIO_Speed_2MHz   = 0x00, /*!< Low speed */
+  GPIO_Speed_25MHz  = 0x01, /*!< Medium speed */
+  GPIO_Speed_50MHz  = 0x02, /*!< Fast speed */
+  GPIO_Speed_100MHz = 0x03  /*!< High speed on 30 pF (80 MHz Output max speed on 15 pF) */
+}GPIOSpeed_TypeDef;
+#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_2MHz) || ((SPEED) == GPIO_Speed_25MHz) || \
+                              ((SPEED) == GPIO_Speed_50MHz)||  ((SPEED) == GPIO_Speed_100MHz)) 
+
+/** 
+  * @brief  GPIO Configuration PullUp PullDown enumeration 
+  */ 
+typedef enum
+{ 
+  GPIO_PuPd_NOPULL = 0x00,
+  GPIO_PuPd_UP     = 0x01,
+  GPIO_PuPd_DOWN   = 0x02
+}GPIOPuPd_TypeDef;
+#define IS_GPIO_PUPD(PUPD) (((PUPD) == GPIO_PuPd_NOPULL) || ((PUPD) == GPIO_PuPd_UP) || \
+                            ((PUPD) == GPIO_PuPd_DOWN))
+
+/** 
+  * @brief  GPIO Bit SET and Bit RESET enumeration 
+  */ 
+typedef enum
+{ 
+  Bit_RESET = 0,
+  Bit_SET
+}BitAction;
+#define IS_GPIO_BIT_ACTION(ACTION) (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET))
+
+
+/** 
+  * @brief   GPIO Init structure definition  
+  */ 
+typedef struct
+{
+  uint32_t GPIO_Pin;              /*!< Specifies the GPIO pins to be configured.
+                                       This parameter can be any value of @ref GPIO_pins_define */
+
+  GPIOMode_TypeDef GPIO_Mode;     /*!< Specifies the operating mode for the selected pins.
+                                       This parameter can be a value of @ref GPIOMode_TypeDef */
+
+  GPIOSpeed_TypeDef GPIO_Speed;   /*!< Specifies the speed for the selected pins.
+                                       This parameter can be a value of @ref GPIOSpeed_TypeDef */
+
+  GPIOOType_TypeDef GPIO_OType;   /*!< Specifies the operating output type for the selected pins.
+                                       This parameter can be a value of @ref GPIOOType_TypeDef */
+
+  GPIOPuPd_TypeDef GPIO_PuPd;     /*!< Specifies the operating Pull-up/Pull down for the selected pins.
+                                       This parameter can be a value of @ref GPIOPuPd_TypeDef */
+}GPIO_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup GPIO_Exported_Constants
+  * @{
+  */ 
+
+/** @defgroup GPIO_pins_define 
+  * @{
+  */ 
+#define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */
+#define GPIO_Pin_1                 ((uint16_t)0x0002)  /* Pin 1 selected */
+#define GPIO_Pin_2                 ((uint16_t)0x0004)  /* Pin 2 selected */
+#define GPIO_Pin_3                 ((uint16_t)0x0008)  /* Pin 3 selected */
+#define GPIO_Pin_4                 ((uint16_t)0x0010)  /* Pin 4 selected */
+#define GPIO_Pin_5                 ((uint16_t)0x0020)  /* Pin 5 selected */
+#define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */
+#define GPIO_Pin_7                 ((uint16_t)0x0080)  /* Pin 7 selected */
+#define GPIO_Pin_8                 ((uint16_t)0x0100)  /* Pin 8 selected */
+#define GPIO_Pin_9                 ((uint16_t)0x0200)  /* Pin 9 selected */
+#define GPIO_Pin_10                ((uint16_t)0x0400)  /* Pin 10 selected */
+#define GPIO_Pin_11                ((uint16_t)0x0800)  /* Pin 11 selected */
+#define GPIO_Pin_12                ((uint16_t)0x1000)  /* Pin 12 selected */
+#define GPIO_Pin_13                ((uint16_t)0x2000)  /* Pin 13 selected */
+#define GPIO_Pin_14                ((uint16_t)0x4000)  /* Pin 14 selected */
+#define GPIO_Pin_15                ((uint16_t)0x8000)  /* Pin 15 selected */
+#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /* All pins selected */
+
+#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))
+#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \
+                              ((PIN) == GPIO_Pin_1) || \
+                              ((PIN) == GPIO_Pin_2) || \
+                              ((PIN) == GPIO_Pin_3) || \
+                              ((PIN) == GPIO_Pin_4) || \
+                              ((PIN) == GPIO_Pin_5) || \
+                              ((PIN) == GPIO_Pin_6) || \
+                              ((PIN) == GPIO_Pin_7) || \
+                              ((PIN) == GPIO_Pin_8) || \
+                              ((PIN) == GPIO_Pin_9) || \
+                              ((PIN) == GPIO_Pin_10) || \
+                              ((PIN) == GPIO_Pin_11) || \
+                              ((PIN) == GPIO_Pin_12) || \
+                              ((PIN) == GPIO_Pin_13) || \
+                              ((PIN) == GPIO_Pin_14) || \
+                              ((PIN) == GPIO_Pin_15))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup GPIO_Pin_sources 
+  * @{
+  */ 
+#define GPIO_PinSource0            ((uint8_t)0x00)
+#define GPIO_PinSource1            ((uint8_t)0x01)
+#define GPIO_PinSource2            ((uint8_t)0x02)
+#define GPIO_PinSource3            ((uint8_t)0x03)
+#define GPIO_PinSource4            ((uint8_t)0x04)
+#define GPIO_PinSource5            ((uint8_t)0x05)
+#define GPIO_PinSource6            ((uint8_t)0x06)
+#define GPIO_PinSource7            ((uint8_t)0x07)
+#define GPIO_PinSource8            ((uint8_t)0x08)
+#define GPIO_PinSource9            ((uint8_t)0x09)
+#define GPIO_PinSource10           ((uint8_t)0x0A)
+#define GPIO_PinSource11           ((uint8_t)0x0B)
+#define GPIO_PinSource12           ((uint8_t)0x0C)
+#define GPIO_PinSource13           ((uint8_t)0x0D)
+#define GPIO_PinSource14           ((uint8_t)0x0E)
+#define GPIO_PinSource15           ((uint8_t)0x0F)
+
+#define IS_GPIO_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == GPIO_PinSource0) || \
+                                       ((PINSOURCE) == GPIO_PinSource1) || \
+                                       ((PINSOURCE) == GPIO_PinSource2) || \
+                                       ((PINSOURCE) == GPIO_PinSource3) || \
+                                       ((PINSOURCE) == GPIO_PinSource4) || \
+                                       ((PINSOURCE) == GPIO_PinSource5) || \
+                                       ((PINSOURCE) == GPIO_PinSource6) || \
+                                       ((PINSOURCE) == GPIO_PinSource7) || \
+                                       ((PINSOURCE) == GPIO_PinSource8) || \
+                                       ((PINSOURCE) == GPIO_PinSource9) || \
+                                       ((PINSOURCE) == GPIO_PinSource10) || \
+                                       ((PINSOURCE) == GPIO_PinSource11) || \
+                                       ((PINSOURCE) == GPIO_PinSource12) || \
+                                       ((PINSOURCE) == GPIO_PinSource13) || \
+                                       ((PINSOURCE) == GPIO_PinSource14) || \
+                                       ((PINSOURCE) == GPIO_PinSource15))
+/**
+  * @}
+  */ 
+
+/** @defgroup GPIO_Alternat_function_selection_define 
+  * @{
+  */ 
+/** 
+  * @brief   AF 0 selection  
+  */ 
+#define GPIO_AF_RTC_50Hz      ((uint8_t)0x00)  /* RTC_50Hz Alternate Function mapping */
+#define GPIO_AF_MCO           ((uint8_t)0x00)  /* MCO (MCO1 and MCO2) Alternate Function mapping */
+#define GPIO_AF_TAMPER        ((uint8_t)0x00)  /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */
+#define GPIO_AF_SWJ           ((uint8_t)0x00)  /* SWJ (SWD and JTAG) Alternate Function mapping */
+#define GPIO_AF_TRACE         ((uint8_t)0x00)  /* TRACE Alternate Function mapping */
+
+/** 
+  * @brief   AF 1 selection  
+  */ 
+#define GPIO_AF_TIM1          ((uint8_t)0x01)  /* TIM1 Alternate Function mapping */
+#define GPIO_AF_TIM2          ((uint8_t)0x01)  /* TIM2 Alternate Function mapping */
+
+/** 
+  * @brief   AF 2 selection  
+  */ 
+#define GPIO_AF_TIM3          ((uint8_t)0x02)  /* TIM3 Alternate Function mapping */
+#define GPIO_AF_TIM4          ((uint8_t)0x02)  /* TIM4 Alternate Function mapping */
+#define GPIO_AF_TIM5          ((uint8_t)0x02)  /* TIM5 Alternate Function mapping */
+
+/** 
+  * @brief   AF 3 selection  
+  */ 
+#define GPIO_AF_TIM8          ((uint8_t)0x03)  /* TIM8 Alternate Function mapping */
+#define GPIO_AF_TIM9          ((uint8_t)0x03)  /* TIM9 Alternate Function mapping */
+#define GPIO_AF_TIM10         ((uint8_t)0x03)  /* TIM10 Alternate Function mapping */
+#define GPIO_AF_TIM11         ((uint8_t)0x03)  /* TIM11 Alternate Function mapping */
+
+/** 
+  * @brief   AF 4 selection  
+  */ 
+#define GPIO_AF_I2C1          ((uint8_t)0x04)  /* I2C1 Alternate Function mapping */
+#define GPIO_AF_I2C2          ((uint8_t)0x04)  /* I2C2 Alternate Function mapping */
+#define GPIO_AF_I2C3          ((uint8_t)0x04)  /* I2C3 Alternate Function mapping */
+
+/** 
+  * @brief   AF 5 selection  
+  */ 
+#define GPIO_AF_SPI1          ((uint8_t)0x05)  /* SPI1 Alternate Function mapping */
+#define GPIO_AF_SPI2          ((uint8_t)0x05)  /* SPI2/I2S2 Alternate Function mapping */
+
+/** 
+  * @brief   AF 6 selection  
+  */ 
+#define GPIO_AF_SPI3          ((uint8_t)0x06)  /* SPI3/I2S3 Alternate Function mapping */
+
+/** 
+  * @brief   AF 7 selection  
+  */ 
+#define GPIO_AF_USART1        ((uint8_t)0x07)  /* USART1 Alternate Function mapping */
+#define GPIO_AF_USART2        ((uint8_t)0x07)  /* USART2 Alternate Function mapping */
+#define GPIO_AF_USART3        ((uint8_t)0x07)  /* USART3 Alternate Function mapping */
+
+/** 
+  * @brief   AF 8 selection  
+  */ 
+#define GPIO_AF_UART4         ((uint8_t)0x08)  /* UART4 Alternate Function mapping */
+#define GPIO_AF_UART5         ((uint8_t)0x08)  /* UART5 Alternate Function mapping */
+#define GPIO_AF_USART6        ((uint8_t)0x08)  /* USART6 Alternate Function mapping */
+
+/** 
+  * @brief   AF 9 selection 
+  */ 
+#define GPIO_AF_CAN1          ((uint8_t)0x09)  /* CAN1 Alternate Function mapping */
+#define GPIO_AF_CAN2          ((uint8_t)0x09)  /* CAN2 Alternate Function mapping */
+#define GPIO_AF_TIM12         ((uint8_t)0x09)  /* TIM12 Alternate Function mapping */
+#define GPIO_AF_TIM13         ((uint8_t)0x09)  /* TIM13 Alternate Function mapping */
+#define GPIO_AF_TIM14         ((uint8_t)0x09)  /* TIM14 Alternate Function mapping */
+
+/** 
+  * @brief   AF 10 selection  
+  */ 
+#define GPIO_AF_OTG_FS         ((uint8_t)0xA)  /* OTG_FS Alternate Function mapping */
+#define GPIO_AF_OTG_HS         ((uint8_t)0xA)  /* OTG_HS Alternate Function mapping */
+
+/** 
+  * @brief   AF 11 selection  
+  */ 
+#define GPIO_AF_ETH             ((uint8_t)0x0B)  /* ETHERNET Alternate Function mapping */
+
+/** 
+  * @brief   AF 12 selection  
+  */ 
+#define GPIO_AF_FSMC            ((uint8_t)0xC)  /* FSMC Alternate Function mapping */
+#define GPIO_AF_OTG_HS_FS       ((uint8_t)0xC)  /* OTG HS configured in FS, Alternate Function mapping */
+#define GPIO_AF_SDIO            ((uint8_t)0xC)  /* SDIO Alternate Function mapping */
+
+/** 
+  * @brief   AF 13 selection  
+  */ 
+#define GPIO_AF_DCMI          ((uint8_t)0x0D)  /* DCMI Alternate Function mapping */
+
+/** 
+  * @brief   AF 15 selection  
+  */ 
+#define GPIO_AF_EVENTOUT      ((uint8_t)0x0F)  /* EVENTOUT Alternate Function mapping */
+
+#define IS_GPIO_AF(AF)   (((AF) == GPIO_AF_RTC_50Hz)  || ((AF) == GPIO_AF_TIM14)  || \
+                          ((AF) == GPIO_AF_MCO)       || ((AF) == GPIO_AF_TAMPER) || \
+                          ((AF) == GPIO_AF_SWJ)       || ((AF) == GPIO_AF_TRACE)  || \
+                          ((AF) == GPIO_AF_TIM1)      || ((AF) == GPIO_AF_TIM2)   || \
+                          ((AF) == GPIO_AF_TIM3)      || ((AF) == GPIO_AF_TIM4)   || \
+                          ((AF) == GPIO_AF_TIM5)      || ((AF) == GPIO_AF_TIM8)   || \
+                          ((AF) == GPIO_AF_I2C1)      || ((AF) == GPIO_AF_I2C2)   || \
+                          ((AF) == GPIO_AF_I2C3)      || ((AF) == GPIO_AF_SPI1)   || \
+                          ((AF) == GPIO_AF_SPI2)      || ((AF) == GPIO_AF_TIM13)  || \
+                          ((AF) == GPIO_AF_SPI3)      || ((AF) == GPIO_AF_TIM14)  || \
+                          ((AF) == GPIO_AF_USART1)    || ((AF) == GPIO_AF_USART2) || \
+                          ((AF) == GPIO_AF_USART3)    || ((AF) == GPIO_AF_UART4)  || \
+                          ((AF) == GPIO_AF_UART5)     || ((AF) == GPIO_AF_USART6) || \
+                          ((AF) == GPIO_AF_CAN1)      || ((AF) == GPIO_AF_CAN2)   || \
+                          ((AF) == GPIO_AF_OTG_FS)    || ((AF) == GPIO_AF_OTG_HS) || \
+                          ((AF) == GPIO_AF_ETH)       || ((AF) == GPIO_AF_FSMC)   || \
+                          ((AF) == GPIO_AF_OTG_HS_FS) || ((AF) == GPIO_AF_SDIO)   || \
+                          ((AF) == GPIO_AF_DCMI)      || ((AF) == GPIO_AF_EVENTOUT))
+/**
+  * @}
+  */ 
+
+/** @defgroup GPIO_Legacy 
+  * @{
+  */
+    
+#define GPIO_Mode_AIN           GPIO_Mode_AN
+
+#define GPIO_AF_OTG1_FS         GPIO_AF_OTG_FS
+#define GPIO_AF_OTG2_HS         GPIO_AF_OTG_HS
+#define GPIO_AF_OTG2_FS         GPIO_AF_OTG_HS_FS
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the GPIO configuration to the default reset state ****/
+void GPIO_DeInit(GPIO_TypeDef* GPIOx);
+
+/* Initialization and Configuration functions *********************************/
+void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
+void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
+void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+
+/* GPIO Read and Write functions **********************************************/
+uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
+uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
+void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
+void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
+void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
+
+/* GPIO Alternate functions configuration function ****************************/
+void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_GPIO_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 242 - 0
app/Libraries/inc/stm32f2xx_hash.h

@@ -0,0 +1,242 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_hash.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the HASH 
+  *          firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_HASH_H
+#define __STM32F2xx_HASH_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup HASH
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief   HASH Init structure definition
+  */ 
+typedef struct
+{
+  uint32_t HASH_AlgoSelection; /*!< SHA-1 or MD5. This parameter can be a value 
+                                    of @ref HASH_Algo_Selection */
+  uint32_t HASH_AlgoMode;      /*!< HASH or HMAC. This parameter can be a value 
+                                    of @ref HASH_processor_Algorithm_Mode */
+  uint32_t HASH_DataType;      /*!< 32-bit data, 16-bit data, 8-bit data or 
+                                    bit-string. This parameter can be a value of
+                                    @ref HASH_Data_Type */
+  uint32_t HASH_HMACKeyType;   /*!< HMAC Short key or HMAC Long Key. This parameter
+                                    can be a value of @ref HASH_HMAC_Long_key_only_for_HMAC_mode */
+}HASH_InitTypeDef;
+
+/** 
+  * @brief  HASH message digest result structure definition  
+  */ 
+typedef struct
+{
+  uint32_t Data[5];      /*!< Message digest result : 5x 32bit words for SHA1 or 
+                                                      4x 32bit words for MD5  */
+} HASH_MsgDigest; 
+
+/** 
+  * @brief  HASH context swapping structure definition  
+  */ 
+typedef struct
+{
+  uint32_t HASH_IMR; 
+  uint32_t HASH_STR;      
+  uint32_t HASH_CR;     
+  uint32_t HASH_CSR[51];       
+}HASH_Context;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup HASH_Exported_Constants
+  * @{
+  */ 
+
+/** @defgroup HASH_Algo_Selection 
+  * @{
+  */ 
+#define HASH_AlgoSelection_SHA1    ((uint16_t)0x0000) /*!< HASH function is SHA1 */
+#define HASH_AlgoSelection_MD5     ((uint16_t)0x0080) /*!< HASH function is MD5 */
+
+#define IS_HASH_ALGOSELECTION(ALGOSELECTION) (((ALGOSELECTION) == HASH_AlgoSelection_SHA1) || \
+                                              ((ALGOSELECTION) == HASH_AlgoSelection_MD5))
+/**
+  * @}
+  */
+
+/** @defgroup HASH_processor_Algorithm_Mode 
+  * @{
+  */ 
+#define HASH_AlgoMode_HASH         ((uint16_t)0x0000) /*!< Algorithm is HASH */ 
+#define HASH_AlgoMode_HMAC         ((uint16_t)0x0040) /*!< Algorithm is HMAC */
+
+#define IS_HASH_ALGOMODE(ALGOMODE) (((ALGOMODE) == HASH_AlgoMode_HASH) || \
+                                    ((ALGOMODE) == HASH_AlgoMode_HMAC))
+/**
+  * @}
+  */
+
+/** @defgroup HASH_Data_Type  
+  * @{
+  */  
+#define HASH_DataType_32b          ((uint16_t)0x0000)
+#define HASH_DataType_16b          ((uint16_t)0x0010)
+#define HASH_DataType_8b           ((uint16_t)0x0020)
+#define HASH_DataType_1b           ((uint16_t)0x0030)
+
+#define IS_HASH_DATATYPE(DATATYPE) (((DATATYPE) == HASH_DataType_32b)|| \
+                                    ((DATATYPE) == HASH_DataType_16b)|| \
+                                    ((DATATYPE) == HASH_DataType_8b)|| \
+                                    ((DATATYPE) == HASH_DataType_1b))
+/**
+  * @}
+  */
+
+/** @defgroup HASH_HMAC_Long_key_only_for_HMAC_mode  
+  * @{
+  */ 
+#define HASH_HMACKeyType_ShortKey      ((uint32_t)0x00000000) /*!< HMAC Key is <= 64 bytes */
+#define HASH_HMACKeyType_LongKey       ((uint32_t)0x00010000) /*!< HMAC Key is > 64 bytes */
+
+#define IS_HASH_HMAC_KEYTYPE(KEYTYPE) (((KEYTYPE) == HASH_HMACKeyType_ShortKey) || \
+                                  ((KEYTYPE) == HASH_HMACKeyType_LongKey))
+/**
+  * @}
+  */
+
+/** @defgroup Number_of_valid_bits_in_last_word_of_the_message   
+  * @{
+  */  
+#define IS_HASH_VALIDBITSNUMBER(VALIDBITS) ((VALIDBITS) <= 0x1F)
+
+/**
+  * @}
+  */
+
+/** @defgroup HASH_interrupts_definition   
+  * @{
+  */  
+#define HASH_IT_DINI               ((uint8_t)0x01)  /*!< A new block can be entered into the input buffer (DIN)*/
+#define HASH_IT_DCI                ((uint8_t)0x02)  /*!< Digest calculation complete */
+
+#define IS_HASH_IT(IT) ((((IT) & (uint8_t)0xFC) == 0x00) && ((IT) != 0x00))
+#define IS_HASH_GET_IT(IT) (((IT) == HASH_IT_DINI) || ((IT) == HASH_IT_DCI))
+				   
+/**
+  * @}
+  */
+
+/** @defgroup HASH_flags_definition   
+  * @{
+  */  
+#define HASH_FLAG_DINIS            ((uint16_t)0x0001)  /*!< 16 locations are free in the DIN : A new block can be entered into the input buffer.*/
+#define HASH_FLAG_DCIS             ((uint16_t)0x0002)  /*!< Digest calculation complete */
+#define HASH_FLAG_DMAS             ((uint16_t)0x0004)  /*!< DMA interface is enabled (DMAE=1) or a transfer is ongoing */
+#define HASH_FLAG_BUSY             ((uint16_t)0x0008)  /*!< The hash core is Busy : processing a block of data */
+#define HASH_FLAG_DINNE            ((uint16_t)0x1000)  /*!< DIN not empty : The input buffer contains at least one word of data */
+
+#define IS_HASH_GET_FLAG(FLAG) (((FLAG) == HASH_FLAG_DINIS) || \
+                                ((FLAG) == HASH_FLAG_DCIS)  || \
+                                ((FLAG) == HASH_FLAG_DMAS)  || \
+                                ((FLAG) == HASH_FLAG_BUSY)  || \
+                                ((FLAG) == HASH_FLAG_DINNE)) 
+
+#define IS_HASH_CLEAR_FLAG(FLAG)(((FLAG) == HASH_FLAG_DINIS) || \
+                                 ((FLAG) == HASH_FLAG_DCIS))                                 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+  
+/*  Function used to set the HASH configuration to the default reset state ****/
+void HASH_DeInit(void);
+
+/* HASH Configuration function ************************************************/
+void HASH_Init(HASH_InitTypeDef* HASH_InitStruct);
+void HASH_StructInit(HASH_InitTypeDef* HASH_InitStruct);
+void HASH_Reset(void);
+
+/* HASH Message Digest generation functions ***********************************/
+void HASH_DataIn(uint32_t Data);
+uint8_t HASH_GetInFIFOWordsNbr(void);
+void HASH_SetLastWordValidBitsNbr(uint16_t ValidNumber);
+void HASH_StartDigest(void);
+void HASH_GetDigest(HASH_MsgDigest* HASH_MessageDigest);
+
+/* HASH Context swapping functions ********************************************/
+void HASH_SaveContext(HASH_Context* HASH_ContextSave);
+void HASH_RestoreContext(HASH_Context* HASH_ContextRestore);
+
+/* HASH's DMA interface function **********************************************/
+void HASH_DMACmd(FunctionalState NewState);
+
+/* HASH Interrupts and flags management functions *****************************/
+void HASH_ITConfig(uint8_t HASH_IT, FunctionalState NewState);
+FlagStatus HASH_GetFlagStatus(uint16_t HASH_FLAG);
+void HASH_ClearFlag(uint16_t HASH_FLAG);
+ITStatus HASH_GetITStatus(uint8_t HASH_IT);
+void HASH_ClearITPendingBit(uint8_t HASH_IT);
+
+/* High Level SHA1 functions **************************************************/
+ErrorStatus HASH_SHA1(uint8_t *Input, uint32_t Ilen, uint8_t Output[20]);
+ErrorStatus HMAC_SHA1(uint8_t *Key, uint32_t Keylen,
+                      uint8_t *Input, uint32_t Ilen,
+                      uint8_t Output[20]);
+
+/* High Level MD5 functions ***************************************************/
+ErrorStatus HASH_MD5(uint8_t *Input, uint32_t Ilen, uint8_t Output[16]);
+ErrorStatus HMAC_MD5(uint8_t *Key, uint32_t Keylen,
+                     uint8_t *Input, uint32_t Ilen,
+                     uint8_t Output[16]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_HASH_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 690 - 0
app/Libraries/inc/stm32f2xx_i2c.h

@@ -0,0 +1,690 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_i2c.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the I2C firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_I2C_H
+#define __STM32F2xx_I2C_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup I2C
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  I2C Init structure definition  
+  */
+
+typedef struct
+{
+  uint32_t I2C_ClockSpeed;          /*!< Specifies the clock frequency.
+                                         This parameter must be set to a value lower than 400kHz */
+
+  uint16_t I2C_Mode;                /*!< Specifies the I2C mode.
+                                         This parameter can be a value of @ref I2C_mode */
+
+  uint16_t I2C_DutyCycle;           /*!< Specifies the I2C fast mode duty cycle.
+                                         This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */
+
+  uint16_t I2C_OwnAddress1;         /*!< Specifies the first device own address.
+                                         This parameter can be a 7-bit or 10-bit address. */
+
+  uint16_t I2C_Ack;                 /*!< Enables or disables the acknowledgement.
+                                         This parameter can be a value of @ref I2C_acknowledgement */
+
+  uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged.
+                                         This parameter can be a value of @ref I2C_acknowledged_address */
+}I2C_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+
+/** @defgroup I2C_Exported_Constants
+  * @{
+  */
+
+#define IS_I2C_ALL_PERIPH(PERIPH) (((PERIPH) == I2C1) || \
+                                   ((PERIPH) == I2C2) || \
+                                   ((PERIPH) == I2C3))
+/** @defgroup I2C_mode 
+  * @{
+  */
+
+#define I2C_Mode_I2C                    ((uint16_t)0x0000)
+#define I2C_Mode_SMBusDevice            ((uint16_t)0x0002)  
+#define I2C_Mode_SMBusHost              ((uint16_t)0x000A)
+#define IS_I2C_MODE(MODE) (((MODE) == I2C_Mode_I2C) || \
+                           ((MODE) == I2C_Mode_SMBusDevice) || \
+                           ((MODE) == I2C_Mode_SMBusHost))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_duty_cycle_in_fast_mode 
+  * @{
+  */
+
+#define I2C_DutyCycle_16_9              ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */
+#define I2C_DutyCycle_2                 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */
+#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DutyCycle_16_9) || \
+                                  ((CYCLE) == I2C_DutyCycle_2))
+/**
+  * @}
+  */ 
+
+/** @defgroup I2C_acknowledgement
+  * @{
+  */
+
+#define I2C_Ack_Enable                  ((uint16_t)0x0400)
+#define I2C_Ack_Disable                 ((uint16_t)0x0000)
+#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_Ack_Enable) || \
+                                 ((STATE) == I2C_Ack_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_transfer_direction 
+  * @{
+  */
+
+#define  I2C_Direction_Transmitter      ((uint8_t)0x00)
+#define  I2C_Direction_Receiver         ((uint8_t)0x01)
+#define IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_Direction_Transmitter) || \
+                                     ((DIRECTION) == I2C_Direction_Receiver))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_acknowledged_address 
+  * @{
+  */
+
+#define I2C_AcknowledgedAddress_7bit    ((uint16_t)0x4000)
+#define I2C_AcknowledgedAddress_10bit   ((uint16_t)0xC000)
+#define IS_I2C_ACKNOWLEDGE_ADDRESS(ADDRESS) (((ADDRESS) == I2C_AcknowledgedAddress_7bit) || \
+                                             ((ADDRESS) == I2C_AcknowledgedAddress_10bit))
+/**
+  * @}
+  */ 
+
+/** @defgroup I2C_registers 
+  * @{
+  */
+
+#define I2C_Register_CR1                ((uint8_t)0x00)
+#define I2C_Register_CR2                ((uint8_t)0x04)
+#define I2C_Register_OAR1               ((uint8_t)0x08)
+#define I2C_Register_OAR2               ((uint8_t)0x0C)
+#define I2C_Register_DR                 ((uint8_t)0x10)
+#define I2C_Register_SR1                ((uint8_t)0x14)
+#define I2C_Register_SR2                ((uint8_t)0x18)
+#define I2C_Register_CCR                ((uint8_t)0x1C)
+#define I2C_Register_TRISE              ((uint8_t)0x20)
+#define IS_I2C_REGISTER(REGISTER) (((REGISTER) == I2C_Register_CR1) || \
+                                   ((REGISTER) == I2C_Register_CR2) || \
+                                   ((REGISTER) == I2C_Register_OAR1) || \
+                                   ((REGISTER) == I2C_Register_OAR2) || \
+                                   ((REGISTER) == I2C_Register_DR) || \
+                                   ((REGISTER) == I2C_Register_SR1) || \
+                                   ((REGISTER) == I2C_Register_SR2) || \
+                                   ((REGISTER) == I2C_Register_CCR) || \
+                                   ((REGISTER) == I2C_Register_TRISE))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_NACK_position 
+  * @{
+  */
+
+#define I2C_NACKPosition_Next           ((uint16_t)0x0800)
+#define I2C_NACKPosition_Current        ((uint16_t)0xF7FF)
+#define IS_I2C_NACK_POSITION(POSITION)  (((POSITION) == I2C_NACKPosition_Next) || \
+                                         ((POSITION) == I2C_NACKPosition_Current))
+/**
+  * @}
+  */ 
+
+/** @defgroup I2C_SMBus_alert_pin_level 
+  * @{
+  */
+
+#define I2C_SMBusAlert_Low              ((uint16_t)0x2000)
+#define I2C_SMBusAlert_High             ((uint16_t)0xDFFF)
+#define IS_I2C_SMBUS_ALERT(ALERT) (((ALERT) == I2C_SMBusAlert_Low) || \
+                                   ((ALERT) == I2C_SMBusAlert_High))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_PEC_position 
+  * @{
+  */
+
+#define I2C_PECPosition_Next            ((uint16_t)0x0800)
+#define I2C_PECPosition_Current         ((uint16_t)0xF7FF)
+#define IS_I2C_PEC_POSITION(POSITION) (((POSITION) == I2C_PECPosition_Next) || \
+                                       ((POSITION) == I2C_PECPosition_Current))
+/**
+  * @}
+  */ 
+
+/** @defgroup I2C_interrupts_definition 
+  * @{
+  */
+
+#define I2C_IT_BUF                      ((uint16_t)0x0400)
+#define I2C_IT_EVT                      ((uint16_t)0x0200)
+#define I2C_IT_ERR                      ((uint16_t)0x0100)
+#define IS_I2C_CONFIG_IT(IT) ((((IT) & (uint16_t)0xF8FF) == 0x00) && ((IT) != 0x00))
+/**
+  * @}
+  */ 
+
+/** @defgroup I2C_interrupts_definition 
+  * @{
+  */
+
+#define I2C_IT_SMBALERT                 ((uint32_t)0x01008000)
+#define I2C_IT_TIMEOUT                  ((uint32_t)0x01004000)
+#define I2C_IT_PECERR                   ((uint32_t)0x01001000)
+#define I2C_IT_OVR                      ((uint32_t)0x01000800)
+#define I2C_IT_AF                       ((uint32_t)0x01000400)
+#define I2C_IT_ARLO                     ((uint32_t)0x01000200)
+#define I2C_IT_BERR                     ((uint32_t)0x01000100)
+#define I2C_IT_TXE                      ((uint32_t)0x06000080)
+#define I2C_IT_RXNE                     ((uint32_t)0x06000040)
+#define I2C_IT_STOPF                    ((uint32_t)0x02000010)
+#define I2C_IT_ADD10                    ((uint32_t)0x02000008)
+#define I2C_IT_BTF                      ((uint32_t)0x02000004)
+#define I2C_IT_ADDR                     ((uint32_t)0x02000002)
+#define I2C_IT_SB                       ((uint32_t)0x02000001)
+
+#define IS_I2C_CLEAR_IT(IT) ((((IT) & (uint16_t)0x20FF) == 0x00) && ((IT) != (uint16_t)0x00))
+
+#define IS_I2C_GET_IT(IT) (((IT) == I2C_IT_SMBALERT) || ((IT) == I2C_IT_TIMEOUT) || \
+                           ((IT) == I2C_IT_PECERR) || ((IT) == I2C_IT_OVR) || \
+                           ((IT) == I2C_IT_AF) || ((IT) == I2C_IT_ARLO) || \
+                           ((IT) == I2C_IT_BERR) || ((IT) == I2C_IT_TXE) || \
+                           ((IT) == I2C_IT_RXNE) || ((IT) == I2C_IT_STOPF) || \
+                           ((IT) == I2C_IT_ADD10) || ((IT) == I2C_IT_BTF) || \
+                           ((IT) == I2C_IT_ADDR) || ((IT) == I2C_IT_SB))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_flags_definition 
+  * @{
+  */
+
+/** 
+  * @brief  SR2 register flags  
+  */
+
+#define I2C_FLAG_DUALF                  ((uint32_t)0x00800000)
+#define I2C_FLAG_SMBHOST                ((uint32_t)0x00400000)
+#define I2C_FLAG_SMBDEFAULT             ((uint32_t)0x00200000)
+#define I2C_FLAG_GENCALL                ((uint32_t)0x00100000)
+#define I2C_FLAG_TRA                    ((uint32_t)0x00040000)
+#define I2C_FLAG_BUSY                   ((uint32_t)0x00020000)
+#define I2C_FLAG_MSL                    ((uint32_t)0x00010000)
+
+/** 
+  * @brief  SR1 register flags  
+  */
+
+#define I2C_FLAG_SMBALERT               ((uint32_t)0x10008000)
+#define I2C_FLAG_TIMEOUT                ((uint32_t)0x10004000)
+#define I2C_FLAG_PECERR                 ((uint32_t)0x10001000)
+#define I2C_FLAG_OVR                    ((uint32_t)0x10000800)
+#define I2C_FLAG_AF                     ((uint32_t)0x10000400)
+#define I2C_FLAG_ARLO                   ((uint32_t)0x10000200)
+#define I2C_FLAG_BERR                   ((uint32_t)0x10000100)
+#define I2C_FLAG_TXE                    ((uint32_t)0x10000080)
+#define I2C_FLAG_RXNE                   ((uint32_t)0x10000040)
+#define I2C_FLAG_STOPF                  ((uint32_t)0x10000010)
+#define I2C_FLAG_ADD10                  ((uint32_t)0x10000008)
+#define I2C_FLAG_BTF                    ((uint32_t)0x10000004)
+#define I2C_FLAG_ADDR                   ((uint32_t)0x10000002)
+#define I2C_FLAG_SB                     ((uint32_t)0x10000001)
+
+#define IS_I2C_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0x20FF) == 0x00) && ((FLAG) != (uint16_t)0x00))
+
+#define IS_I2C_GET_FLAG(FLAG) (((FLAG) == I2C_FLAG_DUALF) || ((FLAG) == I2C_FLAG_SMBHOST) || \
+                               ((FLAG) == I2C_FLAG_SMBDEFAULT) || ((FLAG) == I2C_FLAG_GENCALL) || \
+                               ((FLAG) == I2C_FLAG_TRA) || ((FLAG) == I2C_FLAG_BUSY) || \
+                               ((FLAG) == I2C_FLAG_MSL) || ((FLAG) == I2C_FLAG_SMBALERT) || \
+                               ((FLAG) == I2C_FLAG_TIMEOUT) || ((FLAG) == I2C_FLAG_PECERR) || \
+                               ((FLAG) == I2C_FLAG_OVR) || ((FLAG) == I2C_FLAG_AF) || \
+                               ((FLAG) == I2C_FLAG_ARLO) || ((FLAG) == I2C_FLAG_BERR) || \
+                               ((FLAG) == I2C_FLAG_TXE) || ((FLAG) == I2C_FLAG_RXNE) || \
+                               ((FLAG) == I2C_FLAG_STOPF) || ((FLAG) == I2C_FLAG_ADD10) || \
+                               ((FLAG) == I2C_FLAG_BTF) || ((FLAG) == I2C_FLAG_ADDR) || \
+                               ((FLAG) == I2C_FLAG_SB))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_Events 
+  * @{
+  */
+
+/**
+ ===============================================================================
+               I2C Master Events (Events grouped in order of communication)
+ ===============================================================================
+ */
+
+/** 
+  * @brief  Communication start
+  * 
+  * After sending the START condition (I2C_GenerateSTART() function) the master 
+  * has to wait for this event. It means that the Start condition has been correctly 
+  * released on the I2C bus (the bus is free, no other devices is communicating).
+  * 
+  */
+/* --EV5 */
+#define  I2C_EVENT_MASTER_MODE_SELECT                      ((uint32_t)0x00030001)  /* BUSY, MSL and SB flag */
+
+/** 
+  * @brief  Address Acknowledge
+  * 
+  * After checking on EV5 (start condition correctly released on the bus), the 
+  * master sends the address of the slave(s) with which it will communicate 
+  * (I2C_Send7bitAddress() function, it also determines the direction of the communication: 
+  * Master transmitter or Receiver). Then the master has to wait that a slave acknowledges 
+  * his address. If an acknowledge is sent on the bus, one of the following events will 
+  * be set:
+  * 
+  *  1) In case of Master Receiver (7-bit addressing): the I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED 
+  *     event is set.
+  *  
+  *  2) In case of Master Transmitter (7-bit addressing): the I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED 
+  *     is set
+  *  
+  *  3) In case of 10-Bit addressing mode, the master (just after generating the START 
+  *  and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData() 
+  *  function). Then master should wait on EV9. It means that the 10-bit addressing 
+  *  header has been correctly sent on the bus. Then master should send the second part of 
+  *  the 10-bit address (LSB) using the function I2C_Send7bitAddress(). Then master 
+  *  should wait for event EV6. 
+  *     
+  */
+
+/* --EV6 */
+#define  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED        ((uint32_t)0x00070082)  /* BUSY, MSL, ADDR, TXE and TRA flags */
+#define  I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED           ((uint32_t)0x00030002)  /* BUSY, MSL and ADDR flags */
+/* --EV9 */
+#define  I2C_EVENT_MASTER_MODE_ADDRESS10                   ((uint32_t)0x00030008)  /* BUSY, MSL and ADD10 flags */
+
+/** 
+  * @brief Communication events
+  * 
+  * If a communication is established (START condition generated and slave address 
+  * acknowledged) then the master has to check on one of the following events for 
+  * communication procedures:
+  *  
+  * 1) Master Receiver mode: The master has to wait on the event EV7 then to read 
+  *    the data received from the slave (I2C_ReceiveData() function).
+  * 
+  * 2) Master Transmitter mode: The master has to send data (I2C_SendData() 
+  *    function) then to wait on event EV8 or EV8_2.
+  *    These two events are similar: 
+  *     - EV8 means that the data has been written in the data register and is 
+  *       being shifted out.
+  *     - EV8_2 means that the data has been physically shifted out and output 
+  *       on the bus.
+  *     In most cases, using EV8 is sufficient for the application.
+  *     Using EV8_2 leads to a slower communication but ensure more reliable test.
+  *     EV8_2 is also more suitable than EV8 for testing on the last data transmission 
+  *     (before Stop condition generation).
+  *     
+  *  @note In case the  user software does not guarantee that this event EV7 is 
+  *        managed before the current byte end of transfer, then user may check on EV7 
+  *        and BTF flag at the same time (ie. (I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF)).
+  *        In this case the communication may be slower.
+  * 
+  */
+
+/* Master RECEIVER mode -----------------------------*/ 
+/* --EV7 */
+#define  I2C_EVENT_MASTER_BYTE_RECEIVED                    ((uint32_t)0x00030040)  /* BUSY, MSL and RXNE flags */
+
+/* Master TRANSMITTER mode --------------------------*/
+/* --EV8 */
+#define I2C_EVENT_MASTER_BYTE_TRANSMITTING                 ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */
+/* --EV8_2 */
+#define  I2C_EVENT_MASTER_BYTE_TRANSMITTED                 ((uint32_t)0x00070084)  /* TRA, BUSY, MSL, TXE and BTF flags */
+
+
+/**
+ ===============================================================================
+               I2C Slave Events (Events grouped in order of communication)
+ ===============================================================================
+ */
+
+
+/** 
+  * @brief  Communication start events
+  * 
+  * Wait on one of these events at the start of the communication. It means that 
+  * the I2C peripheral detected a Start condition on the bus (generated by master 
+  * device) followed by the peripheral address. The peripheral generates an ACK 
+  * condition on the bus (if the acknowledge feature is enabled through function 
+  * I2C_AcknowledgeConfig()) and the events listed above are set :
+  *  
+  * 1) In normal case (only one address managed by the slave), when the address 
+  *   sent by the master matches the own address of the peripheral (configured by 
+  *   I2C_OwnAddress1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set 
+  *   (where XXX could be TRANSMITTER or RECEIVER).
+  *    
+  * 2) In case the address sent by the master matches the second address of the 
+  *   peripheral (configured by the function I2C_OwnAddress2Config() and enabled 
+  *   by the function I2C_DualAddressCmd()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED 
+  *   (where XXX could be TRANSMITTER or RECEIVER) are set.
+  *   
+  * 3) In case the address sent by the master is General Call (address 0x00) and 
+  *   if the General Call is enabled for the peripheral (using function I2C_GeneralCallCmd()) 
+  *   the following event is set I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED.   
+  * 
+  */
+
+/* --EV1  (all the events below are variants of EV1) */   
+/* 1) Case of One Single Address managed by the slave */
+#define  I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED          ((uint32_t)0x00020002) /* BUSY and ADDR flags */
+#define  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED       ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */
+
+/* 2) Case of Dual address managed by the slave */
+#define  I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED    ((uint32_t)0x00820000)  /* DUALF and BUSY flags */
+#define  I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080)  /* DUALF, TRA, BUSY and TXE flags */
+
+/* 3) Case of General Call enabled for the slave */
+#define  I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED        ((uint32_t)0x00120000)  /* GENCALL and BUSY flags */
+
+/** 
+  * @brief  Communication events
+  * 
+  * Wait on one of these events when EV1 has already been checked and: 
+  * 
+  * - Slave RECEIVER mode:
+  *     - EV2: When the application is expecting a data byte to be received. 
+  *     - EV4: When the application is expecting the end of the communication: master 
+  *       sends a stop condition and data transmission is stopped.
+  *    
+  * - Slave Transmitter mode:
+  *    - EV3: When a byte has been transmitted by the slave and the application is expecting 
+  *      the end of the byte transmission. The two events I2C_EVENT_SLAVE_BYTE_TRANSMITTED and
+  *      I2C_EVENT_SLAVE_BYTE_TRANSMITTING are similar. The second one can optionally be 
+  *      used when the user software doesn't guarantee the EV3 is managed before the
+  *      current byte end of transfer.
+  *    - EV3_2: When the master sends a NACK in order to tell slave that data transmission 
+  *      shall end (before sending the STOP condition). In this case slave has to stop sending 
+  *      data bytes and expect a Stop condition on the bus.
+  *      
+  *  @note In case the  user software does not guarantee that the event EV2 is 
+  *        managed before the current byte end of transfer, then user may check on EV2 
+  *        and BTF flag at the same time (ie. (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_BTF)).
+  *        In this case the communication may be slower.
+  *
+  */
+
+/* Slave RECEIVER mode --------------------------*/ 
+/* --EV2 */
+#define  I2C_EVENT_SLAVE_BYTE_RECEIVED                     ((uint32_t)0x00020040)  /* BUSY and RXNE flags */
+/* --EV4  */
+#define  I2C_EVENT_SLAVE_STOP_DETECTED                     ((uint32_t)0x00000010)  /* STOPF flag */
+
+/* Slave TRANSMITTER mode -----------------------*/
+/* --EV3 */
+#define  I2C_EVENT_SLAVE_BYTE_TRANSMITTED                  ((uint32_t)0x00060084)  /* TRA, BUSY, TXE and BTF flags */
+#define  I2C_EVENT_SLAVE_BYTE_TRANSMITTING                 ((uint32_t)0x00060080)  /* TRA, BUSY and TXE flags */
+/* --EV3_2 */
+#define  I2C_EVENT_SLAVE_ACK_FAILURE                       ((uint32_t)0x00000400)  /* AF flag */
+
+/*
+ ===============================================================================
+                          End of Events Description
+ ===============================================================================
+ */
+
+#define IS_I2C_EVENT(EVENT) (((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_BYTE_RECEIVED) || \
+                             ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF)) || \
+                             ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL)) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) || \
+                             ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF)) || \
+                             ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL)) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_STOP_DETECTED) || \
+                             ((EVENT) == I2C_EVENT_MASTER_MODE_SELECT) || \
+                             ((EVENT) == I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || \
+                             ((EVENT) == I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || \
+                             ((EVENT) == I2C_EVENT_MASTER_BYTE_RECEIVED) || \
+                             ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTED) || \
+                             ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTING) || \
+                             ((EVENT) == I2C_EVENT_MASTER_MODE_ADDRESS10) || \
+                             ((EVENT) == I2C_EVENT_SLAVE_ACK_FAILURE))
+/**
+  * @}
+  */
+
+/** @defgroup I2C_own_address1 
+  * @{
+  */
+
+#define IS_I2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x3FF)
+/**
+  * @}
+  */
+
+/** @defgroup I2C_clock_speed 
+  * @{
+  */
+
+#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 400000))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the I2C configuration to the default reset state *****/
+void I2C_DeInit(I2C_TypeDef* I2Cx);
+
+/* Initialization and Configuration functions *********************************/
+void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
+void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
+void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
+void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
+void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle);
+void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition);
+void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert);
+void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+
+/* Data transfers functions ***************************************************/ 
+void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
+uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
+
+/* PEC management functions ***************************************************/ 
+void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition);
+void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
+uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);
+
+/* DMA transfers management functions *****************************************/
+void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+
+/* Interrupts, events and flags management functions **************************/
+uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);
+void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);
+
+/* 
+ ===============================================================================
+                          I2C State Monitoring Functions
+ ===============================================================================
+  This I2C driver provides three different ways for I2C state monitoring
+  depending on the application requirements and constraints:
+         
+   
+     1. Basic state monitoring (Using I2C_CheckEvent() function)
+     -----------------------------------------------------------
+        It compares the status registers (SR1 and SR2) content to a given event
+        (can be the combination of one or more flags).
+        It returns SUCCESS if the current status includes the given flags 
+        and returns ERROR if one or more flags are missing in the current status.
+
+          - When to use
+             - This function is suitable for most applications as well as for startup 
+               activity since the events are fully described in the product reference 
+               manual (RM0033).
+             - It is also suitable for users who need to define their own events.
+
+          - Limitations
+             - If an error occurs (ie. error flags are set besides to the monitored 
+               flags), the I2C_CheckEvent() function may return SUCCESS despite 
+               the communication hold or corrupted real state. 
+               In this case, it is advised to use error interrupts to monitor 
+               the error events and handle them in the interrupt IRQ handler.
+         
+     Note 
+         For error management, it is advised to use the following functions:
+           - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
+           - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs.
+             Where x is the peripheral instance (I2C1, I2C2 ...)
+           - I2C_GetFlagStatus() or I2C_GetITStatus()  to be called into the 
+             I2Cx_ER_IRQHandler() function in order to determine which error occurred.
+           - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd() 
+             and/or I2C_GenerateStop() in order to clear the error flag and source 
+             and return to correct  communication status.
+             
+ 
+     2. Advanced state monitoring (Using the function I2C_GetLastEvent())
+     -------------------------------------------------------------------- 
+        Using the function I2C_GetLastEvent() which returns the image of both status 
+        registers in a single word (uint32_t) (Status Register 2 value is shifted left 
+        by 16 bits and concatenated to Status Register 1).
+
+          - When to use
+             - This function is suitable for the same applications above but it 
+               allows to overcome the mentioned limitation of I2C_GetFlagStatus() 
+               function.
+             - The returned value could be compared to events already defined in 
+               this file or to custom values defined by user.
+               This function is suitable when multiple flags are monitored at the 
+               same time.
+             - At the opposite of I2C_CheckEvent() function, this function allows 
+               user to choose when an event is accepted (when all events flags are 
+               set and no other flags are set or just when the needed flags are set 
+               like I2C_CheckEvent() function.
+
+          - Limitations
+             - User may need to define his own events.
+             - Same remark concerning the error management is applicable for this 
+               function if user decides to check only regular communication flags 
+               (and ignores error flags).
+      
+ 
+     3. Flag-based state monitoring (Using the function I2C_GetFlagStatus())
+     -----------------------------------------------------------------------
+     
+      Using the function I2C_GetFlagStatus() which simply returns the status of 
+      one single flag (ie. I2C_FLAG_RXNE ...). 
+
+          - When to use
+             - This function could be used for specific applications or in debug 
+               phase.
+             - It is suitable when only one flag checking is needed (most I2C 
+               events are monitored through multiple flags).
+          - Limitations: 
+             - When calling this function, the Status register is accessed. 
+               Some flags are cleared when the status register is accessed. 
+               So checking the status of one Flag, may clear other ones.
+             - Function may need to be called twice or more in order to monitor 
+               one single event.           
+ */
+
+/*
+ ===============================================================================
+                          1. Basic state monitoring
+ ===============================================================================
+ */
+ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
+/*
+ ===============================================================================
+                          2. Advanced state monitoring
+ ===============================================================================
+ */
+uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx);
+/*
+ ===============================================================================
+                          3. Flag-based state monitoring
+ ===============================================================================
+ */
+FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
+
+
+void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
+ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
+void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_I2C_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 123 - 0
app/Libraries/inc/stm32f2xx_iwdg.h

@@ -0,0 +1,123 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_iwdg.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the IWDG 
+  *          firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_IWDG_H
+#define __STM32F2xx_IWDG_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup IWDG
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup IWDG_Exported_Constants
+  * @{
+  */
+  
+/** @defgroup IWDG_WriteAccess
+  * @{
+  */
+#define IWDG_WriteAccess_Enable     ((uint16_t)0x5555)
+#define IWDG_WriteAccess_Disable    ((uint16_t)0x0000)
+#define IS_IWDG_WRITE_ACCESS(ACCESS) (((ACCESS) == IWDG_WriteAccess_Enable) || \
+                                      ((ACCESS) == IWDG_WriteAccess_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup IWDG_prescaler 
+  * @{
+  */
+#define IWDG_Prescaler_4            ((uint8_t)0x00)
+#define IWDG_Prescaler_8            ((uint8_t)0x01)
+#define IWDG_Prescaler_16           ((uint8_t)0x02)
+#define IWDG_Prescaler_32           ((uint8_t)0x03)
+#define IWDG_Prescaler_64           ((uint8_t)0x04)
+#define IWDG_Prescaler_128          ((uint8_t)0x05)
+#define IWDG_Prescaler_256          ((uint8_t)0x06)
+#define IS_IWDG_PRESCALER(PRESCALER) (((PRESCALER) == IWDG_Prescaler_4)  || \
+                                      ((PRESCALER) == IWDG_Prescaler_8)  || \
+                                      ((PRESCALER) == IWDG_Prescaler_16) || \
+                                      ((PRESCALER) == IWDG_Prescaler_32) || \
+                                      ((PRESCALER) == IWDG_Prescaler_64) || \
+                                      ((PRESCALER) == IWDG_Prescaler_128)|| \
+                                      ((PRESCALER) == IWDG_Prescaler_256))
+/**
+  * @}
+  */
+
+/** @defgroup IWDG_Flag 
+  * @{
+  */
+#define IWDG_FLAG_PVU               ((uint16_t)0x0001)
+#define IWDG_FLAG_RVU               ((uint16_t)0x0002)
+#define IS_IWDG_FLAG(FLAG) (((FLAG) == IWDG_FLAG_PVU) || ((FLAG) == IWDG_FLAG_RVU))
+#define IS_IWDG_RELOAD(RELOAD) ((RELOAD) <= 0xFFF)
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/* Prescaler and Counter configuration functions ******************************/
+void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
+void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
+void IWDG_SetReload(uint16_t Reload);
+void IWDG_ReloadCounter(void);
+
+/* IWDG activation function ***************************************************/
+void IWDG_Enable(void);
+
+/* Flag management function ***************************************************/
+FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_IWDG_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 158 - 0
app/Libraries/inc/stm32f2xx_pwr.h

@@ -0,0 +1,158 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_pwr.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the PWR firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_PWR_H
+#define __STM32F2xx_PWR_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup PWR
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup PWR_Exported_Constants
+  * @{
+  */ 
+
+/** @defgroup PWR_PVD_detection_level 
+  * @{
+  */ 
+
+#define PWR_PVDLevel_0                  PWR_CR_PLS_LEV0
+#define PWR_PVDLevel_1                  PWR_CR_PLS_LEV1
+#define PWR_PVDLevel_2                  PWR_CR_PLS_LEV2
+#define PWR_PVDLevel_3                  PWR_CR_PLS_LEV3
+#define PWR_PVDLevel_4                  PWR_CR_PLS_LEV4
+#define PWR_PVDLevel_5                  PWR_CR_PLS_LEV5
+#define PWR_PVDLevel_6                  PWR_CR_PLS_LEV6
+#define PWR_PVDLevel_7                  PWR_CR_PLS_LEV7
+
+#define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLevel_0) || ((LEVEL) == PWR_PVDLevel_1)|| \
+                                 ((LEVEL) == PWR_PVDLevel_2) || ((LEVEL) == PWR_PVDLevel_3)|| \
+                                 ((LEVEL) == PWR_PVDLevel_4) || ((LEVEL) == PWR_PVDLevel_5)|| \
+                                 ((LEVEL) == PWR_PVDLevel_6) || ((LEVEL) == PWR_PVDLevel_7))
+/**
+  * @}
+  */
+
+  
+/** @defgroup PWR_Regulator_state_in_STOP_mode 
+  * @{
+  */
+
+#define PWR_Regulator_ON                ((uint32_t)0x00000000)
+#define PWR_Regulator_LowPower          PWR_CR_LPDS
+#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_Regulator_ON) || \
+                                     ((REGULATOR) == PWR_Regulator_LowPower))
+/**
+  * @}
+  */
+
+/** @defgroup PWR_STOP_mode_entry 
+  * @{
+  */
+
+#define PWR_STOPEntry_WFI               ((uint8_t)0x01)
+#define PWR_STOPEntry_WFE               ((uint8_t)0x02)
+#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPEntry_WFI) || ((ENTRY) == PWR_STOPEntry_WFE))
+ 
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Flag 
+  * @{
+  */
+
+#define PWR_FLAG_WU                     PWR_CSR_WUF
+#define PWR_FLAG_SB                     PWR_CSR_SBF
+#define PWR_FLAG_PVDO                   PWR_CSR_PVDO
+#define PWR_FLAG_BRR                    PWR_CSR_BRR
+
+#define IS_PWR_GET_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB) || \
+                               ((FLAG) == PWR_FLAG_PVDO) || ((FLAG) == PWR_FLAG_BRR))
+
+#define IS_PWR_CLEAR_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/* Function used to set the PWR configuration to the default reset state ******/ 
+void PWR_DeInit(void);
+
+/* Backup Domain Access function **********************************************/ 
+void PWR_BackupAccessCmd(FunctionalState NewState);
+
+/* PVD configuration functions ************************************************/ 
+void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel);
+void PWR_PVDCmd(FunctionalState NewState);
+
+/* WakeUp pins configuration functions ****************************************/ 
+void PWR_WakeUpPinCmd(FunctionalState NewState);
+
+/* Backup Regulator configuration functions ***********************************/ 
+void PWR_BackupRegulatorCmd(FunctionalState NewState);
+
+/* FLASH Power Down configuration functions ***********************************/ 
+void PWR_FlashPowerDownCmd(FunctionalState NewState);
+
+/* Low Power modes configuration functions ************************************/ 
+void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);
+void PWR_EnterSTANDBYMode(void);
+
+/* Flags management functions *************************************************/ 
+FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
+void PWR_ClearFlag(uint32_t PWR_FLAG);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_PWR_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 507 - 0
app/Libraries/inc/stm32f2xx_rcc.h

@@ -0,0 +1,507 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_rcc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the RCC firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_RCC_H
+#define __STM32F2xx_RCC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup RCC
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+typedef struct
+{
+  uint32_t SYSCLK_Frequency; /*!<  SYSCLK clock frequency expressed in Hz */
+  uint32_t HCLK_Frequency;   /*!<  HCLK clock frequency expressed in Hz */
+  uint32_t PCLK1_Frequency;  /*!<  PCLK1 clock frequency expressed in Hz */
+  uint32_t PCLK2_Frequency;  /*!<  PCLK2 clock frequency expressed in Hz */
+}RCC_ClocksTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup RCC_Exported_Constants
+  * @{
+  */
+  
+/** @defgroup RCC_HSE_configuration 
+  * @{
+  */
+#define RCC_HSE_OFF                      ((uint8_t)0x00)
+#define RCC_HSE_ON                       ((uint8_t)0x01)
+#define RCC_HSE_Bypass                   ((uint8_t)0x05)
+#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_OFF) || ((HSE) == RCC_HSE_ON) || \
+                         ((HSE) == RCC_HSE_Bypass))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_PLL_Clock_Source 
+  * @{
+  */
+#define RCC_PLLSource_HSI                ((uint32_t)0x00000000)
+#define RCC_PLLSource_HSE                ((uint32_t)0x00400000)
+#define IS_RCC_PLL_SOURCE(SOURCE) (((SOURCE) == RCC_PLLSource_HSI) || \
+                                   ((SOURCE) == RCC_PLLSource_HSE))
+#define IS_RCC_PLLM_VALUE(VALUE) ((VALUE) <= 63)
+#define IS_RCC_PLLN_VALUE(VALUE) ((192 <= (VALUE)) && ((VALUE) <= 432))
+#define IS_RCC_PLLP_VALUE(VALUE) (((VALUE) == 2) || ((VALUE) == 4) || ((VALUE) == 6) || ((VALUE) == 8))
+#define IS_RCC_PLLQ_VALUE(VALUE) ((4 <= (VALUE)) && ((VALUE) <= 15))
+ 
+#define IS_RCC_PLLI2SN_VALUE(VALUE) ((192 <= (VALUE)) && ((VALUE) <= 432))
+#define IS_RCC_PLLI2SR_VALUE(VALUE) ((2 <= (VALUE)) && ((VALUE) <= 7))   
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_System_Clock_Source 
+  * @{
+  */
+#define RCC_SYSCLKSource_HSI             ((uint32_t)0x00000000)
+#define RCC_SYSCLKSource_HSE             ((uint32_t)0x00000001)
+#define RCC_SYSCLKSource_PLLCLK          ((uint32_t)0x00000002)
+#define IS_RCC_SYSCLK_SOURCE(SOURCE) (((SOURCE) == RCC_SYSCLKSource_HSI) || \
+                                      ((SOURCE) == RCC_SYSCLKSource_HSE) || \
+                                      ((SOURCE) == RCC_SYSCLKSource_PLLCLK))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_AHB_Clock_Source
+  * @{
+  */
+#define RCC_SYSCLK_Div1                  ((uint32_t)0x00000000)
+#define RCC_SYSCLK_Div2                  ((uint32_t)0x00000080)
+#define RCC_SYSCLK_Div4                  ((uint32_t)0x00000090)
+#define RCC_SYSCLK_Div8                  ((uint32_t)0x000000A0)
+#define RCC_SYSCLK_Div16                 ((uint32_t)0x000000B0)
+#define RCC_SYSCLK_Div64                 ((uint32_t)0x000000C0)
+#define RCC_SYSCLK_Div128                ((uint32_t)0x000000D0)
+#define RCC_SYSCLK_Div256                ((uint32_t)0x000000E0)
+#define RCC_SYSCLK_Div512                ((uint32_t)0x000000F0)
+#define IS_RCC_HCLK(HCLK) (((HCLK) == RCC_SYSCLK_Div1) || ((HCLK) == RCC_SYSCLK_Div2) || \
+                           ((HCLK) == RCC_SYSCLK_Div4) || ((HCLK) == RCC_SYSCLK_Div8) || \
+                           ((HCLK) == RCC_SYSCLK_Div16) || ((HCLK) == RCC_SYSCLK_Div64) || \
+                           ((HCLK) == RCC_SYSCLK_Div128) || ((HCLK) == RCC_SYSCLK_Div256) || \
+                           ((HCLK) == RCC_SYSCLK_Div512))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_APB1_APB2_Clock_Source
+  * @{
+  */
+#define RCC_HCLK_Div1                    ((uint32_t)0x00000000)
+#define RCC_HCLK_Div2                    ((uint32_t)0x00001000)
+#define RCC_HCLK_Div4                    ((uint32_t)0x00001400)
+#define RCC_HCLK_Div8                    ((uint32_t)0x00001800)
+#define RCC_HCLK_Div16                   ((uint32_t)0x00001C00)
+#define IS_RCC_PCLK(PCLK) (((PCLK) == RCC_HCLK_Div1) || ((PCLK) == RCC_HCLK_Div2) || \
+                           ((PCLK) == RCC_HCLK_Div4) || ((PCLK) == RCC_HCLK_Div8) || \
+                           ((PCLK) == RCC_HCLK_Div16))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_Interrupt_Source 
+  * @{
+  */
+#define RCC_IT_LSIRDY                    ((uint8_t)0x01)
+#define RCC_IT_LSERDY                    ((uint8_t)0x02)
+#define RCC_IT_HSIRDY                    ((uint8_t)0x04)
+#define RCC_IT_HSERDY                    ((uint8_t)0x08)
+#define RCC_IT_PLLRDY                    ((uint8_t)0x10)
+#define RCC_IT_PLLI2SRDY                 ((uint8_t)0x20)
+#define RCC_IT_CSS                       ((uint8_t)0x80)
+#define IS_RCC_IT(IT) ((((IT) & (uint8_t)0xC0) == 0x00) && ((IT) != 0x00))
+#define IS_RCC_GET_IT(IT) (((IT) == RCC_IT_LSIRDY) || ((IT) == RCC_IT_LSERDY) || \
+                           ((IT) == RCC_IT_HSIRDY) || ((IT) == RCC_IT_HSERDY) || \
+                           ((IT) == RCC_IT_PLLRDY) || ((IT) == RCC_IT_CSS) || \
+                           ((IT) == RCC_IT_PLLI2SRDY))
+#define IS_RCC_CLEAR_IT(IT) ((((IT) & (uint8_t)0x40) == 0x00) && ((IT) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_LSE_Configuration 
+  * @{
+  */
+#define RCC_LSE_OFF                      ((uint8_t)0x00)
+#define RCC_LSE_ON                       ((uint8_t)0x01)
+#define RCC_LSE_Bypass                   ((uint8_t)0x04)
+#define IS_RCC_LSE(LSE) (((LSE) == RCC_LSE_OFF) || ((LSE) == RCC_LSE_ON) || \
+                         ((LSE) == RCC_LSE_Bypass))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_RTC_Clock_Source
+  * @{
+  */
+#define RCC_RTCCLKSource_LSE             ((uint32_t)0x00000100)
+#define RCC_RTCCLKSource_LSI             ((uint32_t)0x00000200)
+#define RCC_RTCCLKSource_HSE_Div2        ((uint32_t)0x00020300)
+#define RCC_RTCCLKSource_HSE_Div3        ((uint32_t)0x00030300)
+#define RCC_RTCCLKSource_HSE_Div4        ((uint32_t)0x00040300)
+#define RCC_RTCCLKSource_HSE_Div5        ((uint32_t)0x00050300)
+#define RCC_RTCCLKSource_HSE_Div6        ((uint32_t)0x00060300)
+#define RCC_RTCCLKSource_HSE_Div7        ((uint32_t)0x00070300)
+#define RCC_RTCCLKSource_HSE_Div8        ((uint32_t)0x00080300)
+#define RCC_RTCCLKSource_HSE_Div9        ((uint32_t)0x00090300)
+#define RCC_RTCCLKSource_HSE_Div10       ((uint32_t)0x000A0300)
+#define RCC_RTCCLKSource_HSE_Div11       ((uint32_t)0x000B0300)
+#define RCC_RTCCLKSource_HSE_Div12       ((uint32_t)0x000C0300)
+#define RCC_RTCCLKSource_HSE_Div13       ((uint32_t)0x000D0300)
+#define RCC_RTCCLKSource_HSE_Div14       ((uint32_t)0x000E0300)
+#define RCC_RTCCLKSource_HSE_Div15       ((uint32_t)0x000F0300)
+#define RCC_RTCCLKSource_HSE_Div16       ((uint32_t)0x00100300)
+#define RCC_RTCCLKSource_HSE_Div17       ((uint32_t)0x00110300)
+#define RCC_RTCCLKSource_HSE_Div18       ((uint32_t)0x00120300)
+#define RCC_RTCCLKSource_HSE_Div19       ((uint32_t)0x00130300)
+#define RCC_RTCCLKSource_HSE_Div20       ((uint32_t)0x00140300)
+#define RCC_RTCCLKSource_HSE_Div21       ((uint32_t)0x00150300)
+#define RCC_RTCCLKSource_HSE_Div22       ((uint32_t)0x00160300)
+#define RCC_RTCCLKSource_HSE_Div23       ((uint32_t)0x00170300)
+#define RCC_RTCCLKSource_HSE_Div24       ((uint32_t)0x00180300)
+#define RCC_RTCCLKSource_HSE_Div25       ((uint32_t)0x00190300)
+#define RCC_RTCCLKSource_HSE_Div26       ((uint32_t)0x001A0300)
+#define RCC_RTCCLKSource_HSE_Div27       ((uint32_t)0x001B0300)
+#define RCC_RTCCLKSource_HSE_Div28       ((uint32_t)0x001C0300)
+#define RCC_RTCCLKSource_HSE_Div29       ((uint32_t)0x001D0300)
+#define RCC_RTCCLKSource_HSE_Div30       ((uint32_t)0x001E0300)
+#define RCC_RTCCLKSource_HSE_Div31       ((uint32_t)0x001F0300)
+#define IS_RCC_RTCCLK_SOURCE(SOURCE) (((SOURCE) == RCC_RTCCLKSource_LSE) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_LSI) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div2) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div3) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div4) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div5) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div6) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div7) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div8) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div9) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div10) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div11) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div12) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div13) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div14) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div15) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div16) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div17) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div18) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div19) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div20) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div21) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div22) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div23) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div24) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div25) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div26) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div27) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div28) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div29) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div30) || \
+                                      ((SOURCE) == RCC_RTCCLKSource_HSE_Div31))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_I2S_Clock_Source
+  * @{
+  */
+#define RCC_I2S2CLKSource_PLLI2S             ((uint8_t)0x00)
+#define RCC_I2S2CLKSource_Ext                ((uint8_t)0x01)
+
+#define IS_RCC_I2SCLK_SOURCE(SOURCE) (((SOURCE) == RCC_I2S2CLKSource_PLLI2S) || ((SOURCE) == RCC_I2S2CLKSource_Ext))                                
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_AHB1_Peripherals 
+  * @{
+  */ 
+#define RCC_AHB1Periph_GPIOA             ((uint32_t)0x00000001)
+#define RCC_AHB1Periph_GPIOB             ((uint32_t)0x00000002)
+#define RCC_AHB1Periph_GPIOC             ((uint32_t)0x00000004)
+#define RCC_AHB1Periph_GPIOD             ((uint32_t)0x00000008)
+#define RCC_AHB1Periph_GPIOE             ((uint32_t)0x00000010)
+#define RCC_AHB1Periph_GPIOF             ((uint32_t)0x00000020)
+#define RCC_AHB1Periph_GPIOG             ((uint32_t)0x00000040)
+#define RCC_AHB1Periph_GPIOH             ((uint32_t)0x00000080)
+#define RCC_AHB1Periph_GPIOI             ((uint32_t)0x00000100)
+#define RCC_AHB1Periph_CRC               ((uint32_t)0x00001000)
+#define RCC_AHB1Periph_FLITF             ((uint32_t)0x00008000)
+#define RCC_AHB1Periph_SRAM1             ((uint32_t)0x00010000)
+#define RCC_AHB1Periph_SRAM2             ((uint32_t)0x00020000)
+#define RCC_AHB1Periph_BKPSRAM           ((uint32_t)0x00040000)
+#define RCC_AHB1Periph_DMA1              ((uint32_t)0x00200000)
+#define RCC_AHB1Periph_DMA2              ((uint32_t)0x00400000)
+#define RCC_AHB1Periph_ETH_MAC           ((uint32_t)0x02000000)
+#define RCC_AHB1Periph_ETH_MAC_Tx        ((uint32_t)0x04000000)
+#define RCC_AHB1Periph_ETH_MAC_Rx        ((uint32_t)0x08000000)
+#define RCC_AHB1Periph_ETH_MAC_PTP       ((uint32_t)0x10000000)
+#define RCC_AHB1Periph_OTG_HS            ((uint32_t)0x20000000)
+#define RCC_AHB1Periph_OTG_HS_ULPI       ((uint32_t)0x40000000)
+#define IS_RCC_AHB1_CLOCK_PERIPH(PERIPH) ((((PERIPH) & 0x819BEE00) == 0x00) && ((PERIPH) != 0x00))
+#define IS_RCC_AHB1_RESET_PERIPH(PERIPH) ((((PERIPH) & 0xDD9FEE00) == 0x00) && ((PERIPH) != 0x00))
+#define IS_RCC_AHB1_LPMODE_PERIPH(PERIPH) ((((PERIPH) & 0x81986E00) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_AHB2_Peripherals 
+  * @{
+  */  
+#define RCC_AHB2Periph_DCMI              ((uint32_t)0x00000001)
+#define RCC_AHB2Periph_CRYP              ((uint32_t)0x00000010)
+#define RCC_AHB2Periph_HASH              ((uint32_t)0x00000020)
+#define RCC_AHB2Periph_RNG               ((uint32_t)0x00000040)
+#define RCC_AHB2Periph_OTG_FS            ((uint32_t)0x00000080)
+#define IS_RCC_AHB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFF0E) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_AHB3_Peripherals 
+  * @{
+  */ 
+#define RCC_AHB3Periph_FSMC               ((uint32_t)0x00000001)
+#define IS_RCC_AHB3_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFFFE) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_APB1_Peripherals 
+  * @{
+  */ 
+#define RCC_APB1Periph_TIM2              ((uint32_t)0x00000001)
+#define RCC_APB1Periph_TIM3              ((uint32_t)0x00000002)
+#define RCC_APB1Periph_TIM4              ((uint32_t)0x00000004)
+#define RCC_APB1Periph_TIM5              ((uint32_t)0x00000008)
+#define RCC_APB1Periph_TIM6              ((uint32_t)0x00000010)
+#define RCC_APB1Periph_TIM7              ((uint32_t)0x00000020)
+#define RCC_APB1Periph_TIM12             ((uint32_t)0x00000040)
+#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)
+#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)
+#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)
+#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)
+#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)
+#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)
+#define RCC_APB1Periph_USART3            ((uint32_t)0x00040000)
+#define RCC_APB1Periph_UART4             ((uint32_t)0x00080000)
+#define RCC_APB1Periph_UART5             ((uint32_t)0x00100000)
+#define RCC_APB1Periph_I2C1              ((uint32_t)0x00200000)
+#define RCC_APB1Periph_I2C2              ((uint32_t)0x00400000)
+#define RCC_APB1Periph_I2C3              ((uint32_t)0x00800000)
+#define RCC_APB1Periph_CAN1              ((uint32_t)0x02000000)
+#define RCC_APB1Periph_CAN2              ((uint32_t)0x04000000)
+#define RCC_APB1Periph_PWR               ((uint32_t)0x10000000)
+#define RCC_APB1Periph_DAC               ((uint32_t)0x20000000)
+#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0xC9013600) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_APB2_Peripherals 
+  * @{
+  */ 
+#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000001)
+#define RCC_APB2Periph_TIM8              ((uint32_t)0x00000002)
+#define RCC_APB2Periph_USART1            ((uint32_t)0x00000010)
+#define RCC_APB2Periph_USART6            ((uint32_t)0x00000020)
+#define RCC_APB2Periph_ADC               ((uint32_t)0x00000100)
+#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000100)
+#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000200)
+#define RCC_APB2Periph_ADC3              ((uint32_t)0x00000400)
+#define RCC_APB2Periph_SDIO              ((uint32_t)0x00000800)
+#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
+#define RCC_APB2Periph_SYSCFG            ((uint32_t)0x00004000)
+#define RCC_APB2Periph_TIM9              ((uint32_t)0x00010000)
+#define RCC_APB2Periph_TIM10             ((uint32_t)0x00020000)
+#define RCC_APB2Periph_TIM11             ((uint32_t)0x00040000)
+#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFF8A0CC) == 0x00) && ((PERIPH) != 0x00))
+#define IS_RCC_APB2_RESET_PERIPH(PERIPH) ((((PERIPH) & 0xFFF8A6CC) == 0x00) && ((PERIPH) != 0x00))
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_MCO1_Clock_Source_Prescaler
+  * @{
+  */
+#define RCC_MCO1Source_HSI               ((uint32_t)0x00000000)
+#define RCC_MCO1Source_LSE               ((uint32_t)0x00200000)
+#define RCC_MCO1Source_HSE               ((uint32_t)0x00400000)
+#define RCC_MCO1Source_PLLCLK            ((uint32_t)0x00600000)
+#define RCC_MCO1Div_1                    ((uint32_t)0x00000000)
+#define RCC_MCO1Div_2                    ((uint32_t)0x04000000)
+#define RCC_MCO1Div_3                    ((uint32_t)0x05000000)
+#define RCC_MCO1Div_4                    ((uint32_t)0x06000000)
+#define RCC_MCO1Div_5                    ((uint32_t)0x07000000)
+#define IS_RCC_MCO1SOURCE(SOURCE) (((SOURCE) == RCC_MCO1Source_HSI) || ((SOURCE) == RCC_MCO1Source_LSE) || \
+                                   ((SOURCE) == RCC_MCO1Source_HSE) || ((SOURCE) == RCC_MCO1Source_PLLCLK))
+                                   
+#define IS_RCC_MCO1DIV(DIV) (((DIV) == RCC_MCO1Div_1) || ((DIV) == RCC_MCO1Div_2) || \
+                             ((DIV) == RCC_MCO1Div_3) || ((DIV) == RCC_MCO1Div_4) || \
+                             ((DIV) == RCC_MCO1Div_5)) 
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_MCO2_Clock_Source_Prescaler
+  * @{
+  */
+#define RCC_MCO2Source_SYSCLK            ((uint32_t)0x00000000)
+#define RCC_MCO2Source_PLLI2SCLK         ((uint32_t)0x40000000)
+#define RCC_MCO2Source_HSE               ((uint32_t)0x80000000)
+#define RCC_MCO2Source_PLLCLK            ((uint32_t)0xC0000000)
+#define RCC_MCO2Div_1                    ((uint32_t)0x00000000)
+#define RCC_MCO2Div_2                    ((uint32_t)0x20000000)
+#define RCC_MCO2Div_3                    ((uint32_t)0x28000000)
+#define RCC_MCO2Div_4                    ((uint32_t)0x30000000)
+#define RCC_MCO2Div_5                    ((uint32_t)0x38000000)
+#define IS_RCC_MCO2SOURCE(SOURCE) (((SOURCE) == RCC_MCO2Source_SYSCLK) || ((SOURCE) == RCC_MCO2Source_PLLI2SCLK)|| \
+                                   ((SOURCE) == RCC_MCO2Source_HSE) || ((SOURCE) == RCC_MCO2Source_PLLCLK))
+                                   
+#define IS_RCC_MCO2DIV(DIV) (((DIV) == RCC_MCO2Div_1) || ((DIV) == RCC_MCO2Div_2) || \
+                             ((DIV) == RCC_MCO2Div_3) || ((DIV) == RCC_MCO2Div_4) || \
+                             ((DIV) == RCC_MCO2Div_5))                             
+/**
+  * @}
+  */ 
+  
+/** @defgroup RCC_Flag 
+  * @{
+  */
+#define RCC_FLAG_HSIRDY                  ((uint8_t)0x21)
+#define RCC_FLAG_HSERDY                  ((uint8_t)0x31)
+#define RCC_FLAG_PLLRDY                  ((uint8_t)0x39)
+#define RCC_FLAG_PLLI2SRDY               ((uint8_t)0x3B)
+#define RCC_FLAG_LSERDY                  ((uint8_t)0x41)
+#define RCC_FLAG_LSIRDY                  ((uint8_t)0x61)
+#define RCC_FLAG_BORRST                  ((uint8_t)0x79)
+#define RCC_FLAG_PINRST                  ((uint8_t)0x7A)
+#define RCC_FLAG_PORRST                  ((uint8_t)0x7B)
+#define RCC_FLAG_SFTRST                  ((uint8_t)0x7C)
+#define RCC_FLAG_IWDGRST                 ((uint8_t)0x7D)
+#define RCC_FLAG_WWDGRST                 ((uint8_t)0x7E)
+#define RCC_FLAG_LPWRRST                 ((uint8_t)0x7F)
+#define IS_RCC_FLAG(FLAG) (((FLAG) == RCC_FLAG_HSIRDY) || ((FLAG) == RCC_FLAG_HSERDY) || \
+                           ((FLAG) == RCC_FLAG_PLLRDY) || ((FLAG) == RCC_FLAG_LSERDY) || \
+                           ((FLAG) == RCC_FLAG_LSIRDY) || ((FLAG) == RCC_FLAG_BORRST) || \
+                           ((FLAG) == RCC_FLAG_PINRST) || ((FLAG) == RCC_FLAG_PORRST) || \
+                           ((FLAG) == RCC_FLAG_SFTRST) || ((FLAG) == RCC_FLAG_IWDGRST)|| \
+                           ((FLAG) == RCC_FLAG_WWDGRST)|| ((FLAG) == RCC_FLAG_LPWRRST)|| \
+                           ((FLAG) == RCC_FLAG_PLLI2SRDY))
+#define IS_RCC_CALIBRATION_VALUE(VALUE) ((VALUE) <= 0x1F)
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/* Function used to set the RCC clock configuration to the default reset state */
+void RCC_DeInit(void);
+
+/* Internal/external clocks, PLL, CSS and MCO configuration functions *********/
+void RCC_HSEConfig(uint8_t RCC_HSE);
+ErrorStatus RCC_WaitForHSEStartUp(void);
+void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue);
+void RCC_HSICmd(FunctionalState NewState);
+void RCC_LSEConfig(uint8_t RCC_LSE);
+void RCC_LSICmd(FunctionalState NewState);
+
+void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ);
+void RCC_PLLCmd(FunctionalState NewState);
+void RCC_PLLI2SConfig(uint32_t PLLI2SN, uint32_t PLLI2SR);
+void RCC_PLLI2SCmd(FunctionalState NewState);
+
+void RCC_ClockSecuritySystemCmd(FunctionalState NewState);
+void RCC_MCO1Config(uint32_t RCC_MCO1Source, uint32_t RCC_MCO1Div);
+void RCC_MCO2Config(uint32_t RCC_MCO2Source, uint32_t RCC_MCO2Div);
+
+/* System, AHB and APB busses clocks configuration functions ******************/
+void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
+uint8_t RCC_GetSYSCLKSource(void);
+void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
+void RCC_PCLK1Config(uint32_t RCC_HCLK);
+void RCC_PCLK2Config(uint32_t RCC_HCLK);
+void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks);
+
+/* Peripheral clocks configuration functions **********************************/
+void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
+void RCC_RTCCLKCmd(FunctionalState NewState);
+void RCC_BackupResetCmd(FunctionalState NewState);
+void RCC_I2SCLKConfig(uint32_t RCC_I2SCLKSource); 
+
+void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
+void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
+void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
+void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
+void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
+
+void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
+void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
+void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
+void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
+void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
+
+void RCC_AHB1PeriphClockLPModeCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
+void RCC_AHB2PeriphClockLPModeCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
+void RCC_AHB3PeriphClockLPModeCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
+void RCC_APB1PeriphClockLPModeCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
+void RCC_APB2PeriphClockLPModeCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState);
+FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);
+void RCC_ClearFlag(void);
+ITStatus RCC_GetITStatus(uint8_t RCC_IT);
+void RCC_ClearITPendingBit(uint8_t RCC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_RCC_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 112 - 0
app/Libraries/inc/stm32f2xx_rng.h

@@ -0,0 +1,112 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_rng.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the Random 
+  *          Number Generator(RNG) firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_RNG_H
+#define __STM32F2xx_RNG_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup RNG
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/ 
+
+/** @defgroup RNG_Exported_Constants
+  * @{
+  */
+  
+/** @defgroup RNG_flags_definition  
+  * @{
+  */ 
+#define RNG_FLAG_DRDY               ((uint8_t)0x0001) /*!< Data ready */
+#define RNG_FLAG_CECS               ((uint8_t)0x0002) /*!< Clock error current status */
+#define RNG_FLAG_SECS               ((uint8_t)0x0004) /*!< Seed error current status */
+
+#define IS_RNG_GET_FLAG(RNG_FLAG) (((RNG_FLAG) == RNG_FLAG_DRDY) || \
+                                   ((RNG_FLAG) == RNG_FLAG_CECS) || \
+                                   ((RNG_FLAG) == RNG_FLAG_SECS))
+#define IS_RNG_CLEAR_FLAG(RNG_FLAG) (((RNG_FLAG) == RNG_FLAG_CECS) || \
+                                    ((RNG_FLAG) == RNG_FLAG_SECS))
+/**
+  * @}
+  */ 
+
+/** @defgroup RNG_interrupts_definition   
+  * @{
+  */  
+#define RNG_IT_CEI                  ((uint8_t)0x20) /*!< Clock error interrupt */
+#define RNG_IT_SEI                  ((uint8_t)0x40) /*!< Seed error interrupt */
+
+#define IS_RNG_IT(IT) ((((IT) & (uint8_t)0x9F) == 0x00) && ((IT) != 0x00))
+#define IS_RNG_GET_IT(RNG_IT) (((RNG_IT) == RNG_IT_CEI) || ((RNG_IT) == RNG_IT_SEI))
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the RNG configuration to the default reset state *****/ 
+void RNG_DeInit(void);
+
+/* Configuration function *****************************************************/
+void RNG_Cmd(FunctionalState NewState);
+
+/* Get 32 bit Random number function ******************************************/
+uint32_t RNG_GetRandomNumber(void);
+
+/* Interrupts and flags management functions **********************************/
+void RNG_ITConfig(FunctionalState NewState);
+FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG);
+void RNG_ClearFlag(uint8_t RNG_FLAG);
+ITStatus RNG_GetITStatus(uint8_t RNG_IT);
+void RNG_ClearITPendingBit(uint8_t RNG_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_RNG_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 642 - 0
app/Libraries/inc/stm32f2xx_rtc.h

@@ -0,0 +1,642 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_rtc.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the RTC firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_RTC_H
+#define __STM32F2xx_RTC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup RTC
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  RTC Init structures definition  
+  */ 
+typedef struct
+{
+  uint32_t RTC_HourFormat;   /*!< Specifies the RTC Hour Format.
+                             This parameter can be a value of @ref RTC_Hour_Formats */
+  
+  uint32_t RTC_AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value.
+                             This parameter must be set to a value lower than 0x7F */
+  
+  uint32_t RTC_SynchPrediv;  /*!< Specifies the RTC Synchronous Predivider value.
+                             This parameter must be set to a value lower than 0x1FFF */
+}RTC_InitTypeDef;
+
+/** 
+  * @brief  RTC Time structure definition  
+  */
+typedef struct
+{
+  uint8_t RTC_Hours;    /*!< Specifies the RTC Time Hour.
+                        This parameter must be set to a value in the 0-12 range
+                        if the RTC_HourFormat_12 is selected or 0-23 range if
+                        the RTC_HourFormat_24 is selected. */
+
+  uint8_t RTC_Minutes;  /*!< Specifies the RTC Time Minutes.
+                        This parameter must be set to a value in the 0-59 range. */
+  
+  uint8_t RTC_Seconds;  /*!< Specifies the RTC Time Seconds.
+                        This parameter must be set to a value in the 0-59 range. */
+
+  uint8_t RTC_H12;      /*!< Specifies the RTC AM/PM Time.
+                        This parameter can be a value of @ref RTC_AM_PM_Definitions */
+}RTC_TimeTypeDef; 
+
+/** 
+  * @brief  RTC Date structure definition  
+  */
+typedef struct
+{
+  uint8_t RTC_WeekDay; /*!< Specifies the RTC Date WeekDay.
+                        This parameter can be a value of @ref RTC_WeekDay_Definitions */
+  
+  uint8_t RTC_Month;   /*!< Specifies the RTC Date Month (in BCD format).
+                        This parameter can be a value of @ref RTC_Month_Date_Definitions */
+
+  uint8_t RTC_Date;     /*!< Specifies the RTC Date.
+                        This parameter must be set to a value in the 1-31 range. */
+  
+  uint8_t RTC_Year;     /*!< Specifies the RTC Date Year.
+                        This parameter must be set to a value in the 0-99 range. */
+}RTC_DateTypeDef;
+
+/** 
+  * @brief  RTC Alarm structure definition  
+  */
+typedef struct
+{
+  RTC_TimeTypeDef RTC_AlarmTime;     /*!< Specifies the RTC Alarm Time members. */
+
+  uint32_t RTC_AlarmMask;            /*!< Specifies the RTC Alarm Masks.
+                                     This parameter can be a value of @ref RTC_AlarmMask_Definitions */
+
+  uint32_t RTC_AlarmDateWeekDaySel;  /*!< Specifies the RTC Alarm is on Date or WeekDay.
+                                     This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */
+  
+  uint8_t RTC_AlarmDateWeekDay;      /*!< Specifies the RTC Alarm Date/WeekDay.
+                                     If the Alarm Date is selected, this parameter
+                                     must be set to a value in the 1-31 range.
+                                     If the Alarm WeekDay is selected, this 
+                                     parameter can be a value of @ref RTC_WeekDay_Definitions */
+}RTC_AlarmTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup RTC_Exported_Constants
+  * @{
+  */ 
+
+
+/** @defgroup RTC_Hour_Formats 
+  * @{
+  */ 
+#define RTC_HourFormat_24              ((uint32_t)0x00000000)
+#define RTC_HourFormat_12              ((uint32_t)0x00000040)
+#define IS_RTC_HOUR_FORMAT(FORMAT)     (((FORMAT) == RTC_HourFormat_12) || \
+                                        ((FORMAT) == RTC_HourFormat_24))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Asynchronous_Predivider 
+  * @{
+  */ 
+#define IS_RTC_ASYNCH_PREDIV(PREDIV)   ((PREDIV) <= 0x7F)
+ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_Synchronous_Predivider 
+  * @{
+  */ 
+#define IS_RTC_SYNCH_PREDIV(PREDIV)    ((PREDIV) <= 0x1FFF)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Time_Definitions 
+  * @{
+  */ 
+#define IS_RTC_HOUR12(HOUR)            (((HOUR) > 0) && ((HOUR) <= 12))
+#define IS_RTC_HOUR24(HOUR)            ((HOUR) <= 23)
+#define IS_RTC_MINUTES(MINUTES)        ((MINUTES) <= 59)
+#define IS_RTC_SECONDS(SECONDS)        ((SECONDS) <= 59)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_AM_PM_Definitions 
+  * @{
+  */ 
+#define RTC_H12_AM                     ((uint8_t)0x00)
+#define RTC_H12_PM                     ((uint8_t)0x40)
+#define IS_RTC_H12(PM) (((PM) == RTC_H12_AM) || ((PM) == RTC_H12_PM))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Year_Date_Definitions 
+  * @{
+  */ 
+#define IS_RTC_YEAR(YEAR)              ((YEAR) <= 99)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Month_Date_Definitions 
+  * @{
+  */ 
+
+/* Coded in BCD format */
+#define RTC_Month_January              ((uint8_t)0x01)
+#define RTC_Month_February             ((uint8_t)0x02)
+#define RTC_Month_March                ((uint8_t)0x03)
+#define RTC_Month_April                ((uint8_t)0x04)
+#define RTC_Month_May                  ((uint8_t)0x05)
+#define RTC_Month_June                 ((uint8_t)0x06)
+#define RTC_Month_July                 ((uint8_t)0x07)
+#define RTC_Month_August               ((uint8_t)0x08)
+#define RTC_Month_September            ((uint8_t)0x09)
+#define RTC_Month_October              ((uint8_t)0x10)
+#define RTC_Month_November             ((uint8_t)0x11)
+#define RTC_Month_December             ((uint8_t)0x12)
+#define IS_RTC_MONTH(MONTH)            (((MONTH) >= 1) && ((MONTH) <= 12))
+#define IS_RTC_DATE(DATE)              (((DATE) >= 1) && ((DATE) <= 31))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_WeekDay_Definitions 
+  * @{
+  */ 
+  
+#define	RTC_Weekday_Monday             ((uint8_t)0x01)
+#define	RTC_Weekday_Tuesday            ((uint8_t)0x02)
+#define	RTC_Weekday_Wednesday          ((uint8_t)0x03)
+#define	RTC_Weekday_Thursday           ((uint8_t)0x04)
+#define	RTC_Weekday_Friday             ((uint8_t)0x05)
+#define	RTC_Weekday_Saturday           ((uint8_t)0x06)
+#define	RTC_Weekday_Sunday             ((uint8_t)0x07)
+#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_Weekday_Monday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Tuesday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Wednesday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Thursday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Friday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Saturday) || \
+                                 ((WEEKDAY) == RTC_Weekday_Sunday))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_Alarm_Definitions
+  * @{
+  */ 
+#define IS_RTC_ALARM_DATE_WEEKDAY_DATE(DATE) (((DATE) > 0) && ((DATE) <= 31))
+#define IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_Weekday_Monday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Tuesday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Wednesday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Thursday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Friday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Saturday) || \
+                                                    ((WEEKDAY) == RTC_Weekday_Sunday))
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_AlarmDateWeekDay_Definitions 
+  * @{
+  */ 
+#define RTC_AlarmDateWeekDaySel_Date      ((uint32_t)0x00000000)
+#define RTC_AlarmDateWeekDaySel_WeekDay   ((uint32_t)0x40000000)
+
+#define IS_RTC_ALARM_DATE_WEEKDAY_SEL(SEL) (((SEL) == RTC_AlarmDateWeekDaySel_Date) || \
+                                            ((SEL) == RTC_AlarmDateWeekDaySel_WeekDay))
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_AlarmMask_Definitions 
+  * @{
+  */ 
+#define RTC_AlarmMask_None                ((uint32_t)0x00000000)
+#define RTC_AlarmMask_DateWeekDay         ((uint32_t)0x80000000)
+#define RTC_AlarmMask_Hours               ((uint32_t)0x00800000)
+#define RTC_AlarmMask_Minutes             ((uint32_t)0x00008000)
+#define RTC_AlarmMask_Seconds             ((uint32_t)0x00000080)
+#define RTC_AlarmMask_All                 ((uint32_t)0x80808080)
+#define IS_ALARM_MASK(MASK)  (((MASK) & 0x7F7F7F7F) == (uint32_t)RESET)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Alarms_Definitions 
+  * @{
+  */ 
+#define RTC_Alarm_A                       ((uint32_t)0x00000100)
+#define RTC_Alarm_B                       ((uint32_t)0x00000200)
+#define IS_RTC_ALARM(ALARM)     (((ALARM) == RTC_Alarm_A) || ((ALARM) == RTC_Alarm_B))
+#define IS_RTC_CMD_ALARM(ALARM) (((ALARM) & (RTC_Alarm_A | RTC_Alarm_B)) != (uint32_t)RESET)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Wakeup_Timer_Definitions 
+  * @{
+  */ 
+#define RTC_WakeUpClock_RTCCLK_Div16        ((uint32_t)0x00000000)
+#define RTC_WakeUpClock_RTCCLK_Div8         ((uint32_t)0x00000001)
+#define RTC_WakeUpClock_RTCCLK_Div4         ((uint32_t)0x00000002)
+#define RTC_WakeUpClock_RTCCLK_Div2         ((uint32_t)0x00000003)
+#define RTC_WakeUpClock_CK_SPRE_16bits      ((uint32_t)0x00000004)
+#define RTC_WakeUpClock_CK_SPRE_17bits      ((uint32_t)0x00000006)
+#define IS_RTC_WAKEUP_CLOCK(CLOCK) (((CLOCK) == RTC_WakeUpClock_RTCCLK_Div16) || \
+                                    ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div8) || \
+                                    ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div4) || \
+                                    ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div2) || \
+                                    ((CLOCK) == RTC_WakeUpClock_CK_SPRE_16bits) || \
+                                    ((CLOCK) == RTC_WakeUpClock_CK_SPRE_17bits))
+#define IS_RTC_WAKEUP_COUNTER(COUNTER)  ((COUNTER) <= 0xFFFF)
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Time_Stamp_Edges_definitions 
+  * @{
+  */ 
+#define RTC_TimeStampEdge_Rising          ((uint32_t)0x00000000)
+#define RTC_TimeStampEdge_Falling         ((uint32_t)0x00000008)
+#define IS_RTC_TIMESTAMP_EDGE(EDGE) (((EDGE) == RTC_TimeStampEdge_Rising) || \
+                                     ((EDGE) == RTC_TimeStampEdge_Falling))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Output_selection_Definitions 
+  * @{
+  */ 
+#define RTC_Output_Disable             ((uint32_t)0x00000000)
+#define RTC_Output_AlarmA              ((uint32_t)0x00200000)
+#define RTC_Output_AlarmB              ((uint32_t)0x00400000)
+#define RTC_Output_WakeUp              ((uint32_t)0x00600000)
+ 
+#define IS_RTC_OUTPUT(OUTPUT) (((OUTPUT) == RTC_Output_Disable) || \
+                               ((OUTPUT) == RTC_Output_AlarmA) || \
+                               ((OUTPUT) == RTC_Output_AlarmB) || \
+                               ((OUTPUT) == RTC_Output_WakeUp))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Output_Polarity_Definitions 
+  * @{
+  */ 
+#define RTC_OutputPolarity_High           ((uint32_t)0x00000000)
+#define RTC_OutputPolarity_Low            ((uint32_t)0x00100000)
+#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OutputPolarity_High) || \
+                                ((POL) == RTC_OutputPolarity_Low))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_Digital_Calibration_Definitions 
+  * @{
+  */ 
+#define RTC_CalibSign_Positive            ((uint32_t)0x00000000) 
+#define RTC_CalibSign_Negative            ((uint32_t)0x00000080)
+#define IS_RTC_CALIB_SIGN(SIGN) (((SIGN) == RTC_CalibSign_Positive) || \
+                                 ((SIGN) == RTC_CalibSign_Negative))
+#define IS_RTC_CALIB_VALUE(VALUE) ((VALUE) < 0x20)
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup RTC_DayLightSaving_Definitions 
+  * @{
+  */ 
+#define RTC_DayLightSaving_SUB1H   ((uint32_t)0x00020000)
+#define RTC_DayLightSaving_ADD1H   ((uint32_t)0x00010000)
+#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DayLightSaving_SUB1H) || \
+                                      ((SAVE) == RTC_DayLightSaving_ADD1H))
+
+#define RTC_StoreOperation_Reset        ((uint32_t)0x00000000)
+#define RTC_StoreOperation_Set          ((uint32_t)0x00040000)
+#define IS_RTC_STORE_OPERATION(OPERATION) (((OPERATION) == RTC_StoreOperation_Reset) || \
+                                           ((OPERATION) == RTC_StoreOperation_Set))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Tamper_Trigger_Definitions 
+  * @{
+  */ 
+#define RTC_TamperTrigger_RisingEdge            ((uint32_t)0x00000000)
+#define RTC_TamperTrigger_FallingEdge           ((uint32_t)0x00000001)
+#define IS_RTC_TAMPER_TRIGGER(TRIGGER) (((TRIGGER) == RTC_TamperTrigger_RisingEdge) || \
+                                        ((TRIGGER) == RTC_TamperTrigger_FallingEdge))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Tamper_Pins_Definitions 
+  * @{
+  */ 
+#define RTC_Tamper_1                    RTC_TAFCR_TAMP1E
+#define IS_RTC_TAMPER(TAMPER) (((TAMPER) == RTC_Tamper_1))
+
+/**
+  * @}
+  */
+
+/** @defgroup RTC_Tamper_Pin_Selection 
+  * @{
+  */ 
+#define RTC_TamperPin_PC13                 ((uint32_t)0x00000000)
+#define RTC_TamperPin_PI8                  ((uint32_t)0x00010000)
+#define IS_RTC_TAMPER_PIN(PIN) (((PIN) == RTC_TamperPin_PC13) || \
+                                ((PIN) == RTC_TamperPin_PI8))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_TimeStamp_Pin_Selection 
+  * @{
+  */ 
+#define RTC_TimeStampPin_PC13              ((uint32_t)0x00000000)
+#define RTC_TimeStampPin_PI8               ((uint32_t)0x00020000)
+#define IS_RTC_TIMESTAMP_PIN(PIN) (((PIN) == RTC_TimeStampPin_PC13) || \
+                                   ((PIN) == RTC_TimeStampPin_PI8))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Output_Type_ALARM_OUT 
+  * @{
+  */ 
+#define RTC_OutputType_OpenDrain           ((uint32_t)0x00000000)
+#define RTC_OutputType_PushPull            ((uint32_t)0x00040000)
+#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OutputType_OpenDrain) || \
+                                  ((TYPE) == RTC_OutputType_PushPull))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Backup_Registers_Definitions 
+  * @{
+  */
+
+#define RTC_BKP_DR0                       ((uint32_t)0x00000000)
+#define RTC_BKP_DR1                       ((uint32_t)0x00000001)
+#define RTC_BKP_DR2                       ((uint32_t)0x00000002)
+#define RTC_BKP_DR3                       ((uint32_t)0x00000003)
+#define RTC_BKP_DR4                       ((uint32_t)0x00000004)
+#define RTC_BKP_DR5                       ((uint32_t)0x00000005)
+#define RTC_BKP_DR6                       ((uint32_t)0x00000006)
+#define RTC_BKP_DR7                       ((uint32_t)0x00000007)
+#define RTC_BKP_DR8                       ((uint32_t)0x00000008)
+#define RTC_BKP_DR9                       ((uint32_t)0x00000009)
+#define RTC_BKP_DR10                      ((uint32_t)0x0000000A)
+#define RTC_BKP_DR11                      ((uint32_t)0x0000000B)
+#define RTC_BKP_DR12                      ((uint32_t)0x0000000C)
+#define RTC_BKP_DR13                      ((uint32_t)0x0000000D)
+#define RTC_BKP_DR14                      ((uint32_t)0x0000000E)
+#define RTC_BKP_DR15                      ((uint32_t)0x0000000F)
+#define RTC_BKP_DR16                      ((uint32_t)0x00000010)
+#define RTC_BKP_DR17                      ((uint32_t)0x00000011)
+#define RTC_BKP_DR18                      ((uint32_t)0x00000012)
+#define RTC_BKP_DR19                      ((uint32_t)0x00000013)
+#define IS_RTC_BKP(BKP)                   (((BKP) == RTC_BKP_DR0) || \
+                                           ((BKP) == RTC_BKP_DR1) || \
+                                           ((BKP) == RTC_BKP_DR2) || \
+                                           ((BKP) == RTC_BKP_DR3) || \
+                                           ((BKP) == RTC_BKP_DR4) || \
+                                           ((BKP) == RTC_BKP_DR5) || \
+                                           ((BKP) == RTC_BKP_DR6) || \
+                                           ((BKP) == RTC_BKP_DR7) || \
+                                           ((BKP) == RTC_BKP_DR8) || \
+                                           ((BKP) == RTC_BKP_DR9) || \
+                                           ((BKP) == RTC_BKP_DR10) || \
+                                           ((BKP) == RTC_BKP_DR11) || \
+                                           ((BKP) == RTC_BKP_DR12) || \
+                                           ((BKP) == RTC_BKP_DR13) || \
+                                           ((BKP) == RTC_BKP_DR14) || \
+                                           ((BKP) == RTC_BKP_DR15) || \
+                                           ((BKP) == RTC_BKP_DR16) || \
+                                           ((BKP) == RTC_BKP_DR17) || \
+                                           ((BKP) == RTC_BKP_DR18) || \
+                                           ((BKP) == RTC_BKP_DR19))
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Input_parameter_format_definitions 
+  * @{
+  */ 
+#define RTC_Format_BIN                    ((uint32_t)0x000000000)
+#define RTC_Format_BCD                    ((uint32_t)0x000000001)
+#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_Format_BIN) || ((FORMAT) == RTC_Format_BCD))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Flags_Definitions 
+  * @{
+  */ 
+#define RTC_FLAG_TAMP1F                   ((uint32_t)0x00002000)
+#define RTC_FLAG_TSOVF                    ((uint32_t)0x00001000)
+#define RTC_FLAG_TSF                      ((uint32_t)0x00000800)
+#define RTC_FLAG_WUTF                     ((uint32_t)0x00000400)
+#define RTC_FLAG_ALRBF                    ((uint32_t)0x00000200)
+#define RTC_FLAG_ALRAF                    ((uint32_t)0x00000100)
+#define RTC_FLAG_INITF                    ((uint32_t)0x00000040)
+#define RTC_FLAG_RSF                      ((uint32_t)0x00000020)
+#define RTC_FLAG_INITS                    ((uint32_t)0x00000010)
+#define RTC_FLAG_WUTWF                    ((uint32_t)0x00000004)
+#define RTC_FLAG_ALRBWF                   ((uint32_t)0x00000002)
+#define RTC_FLAG_ALRAWF                   ((uint32_t)0x00000001)
+#define IS_RTC_GET_FLAG(FLAG) (((FLAG) == RTC_FLAG_TSOVF) || ((FLAG) == RTC_FLAG_TSF) || \
+                               ((FLAG) == RTC_FLAG_WUTF) || ((FLAG) == RTC_FLAG_ALRBF) || \
+                               ((FLAG) == RTC_FLAG_ALRAF) || ((FLAG) == RTC_FLAG_INITF) || \
+                               ((FLAG) == RTC_FLAG_RSF) || ((FLAG) == RTC_FLAG_WUTWF) || \
+                               ((FLAG) == RTC_FLAG_ALRBWF) || ((FLAG) == RTC_FLAG_ALRAWF) || \
+                               ((FLAG) == RTC_FLAG_TAMP1F))
+#define IS_RTC_CLEAR_FLAG(FLAG) (((FLAG) != (uint32_t)RESET) && (((FLAG) & 0xFFFFC0DF) == (uint32_t)RESET))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Interrupts_Definitions 
+  * @{
+  */ 
+#define RTC_IT_TS                         ((uint32_t)0x00008000)
+#define RTC_IT_WUT                        ((uint32_t)0x00004000)
+#define RTC_IT_ALRB                       ((uint32_t)0x00002000)
+#define RTC_IT_ALRA                       ((uint32_t)0x00001000)
+#define RTC_IT_TAMP                       ((uint32_t)0x00000004) /* Used only to Enable the Tamper Interrupt */
+#define RTC_IT_TAMP1                      ((uint32_t)0x00020000)
+
+#define IS_RTC_CONFIG_IT(IT) (((IT) != (uint32_t)RESET) && (((IT) & 0xFFFF0FFB) == (uint32_t)RESET))
+#define IS_RTC_GET_IT(IT) (((IT) == RTC_IT_TS) || ((IT) == RTC_IT_WUT) || \
+                           ((IT) == RTC_IT_ALRB) || ((IT) == RTC_IT_ALRA) || \
+                           ((IT) == RTC_IT_TAMP1))
+#define IS_RTC_CLEAR_IT(IT) (((IT) != (uint32_t)RESET) && (((IT) & 0xFFFD0FFF) == (uint32_t)RESET))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup RTC_Legacy 
+  * @{
+  */ 
+#define RTC_DigitalCalibConfig  RTC_CoarseCalibConfig
+#define RTC_DigitalCalibCmd     RTC_CoarseCalibCmd
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the RTC configuration to the default reset state *****/
+ErrorStatus RTC_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);
+void RTC_StructInit(RTC_InitTypeDef* RTC_InitStruct);
+void RTC_WriteProtectionCmd(FunctionalState NewState);
+ErrorStatus RTC_EnterInitMode(void);
+void RTC_ExitInitMode(void);
+ErrorStatus RTC_WaitForSynchro(void);
+ErrorStatus RTC_RefClockCmd(FunctionalState NewState);
+
+/* Time and Date configuration functions **************************************/
+ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
+void RTC_TimeStructInit(RTC_TimeTypeDef* RTC_TimeStruct);
+void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
+ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
+void RTC_DateStructInit(RTC_DateTypeDef* RTC_DateStruct);
+void RTC_GetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
+
+/* Alarms (Alarm A and Alarm B) configuration functions  **********************/
+void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
+void RTC_AlarmStructInit(RTC_AlarmTypeDef* RTC_AlarmStruct);
+void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
+ErrorStatus RTC_AlarmCmd(uint32_t RTC_Alarm, FunctionalState NewState);
+
+/* WakeUp Timer configuration functions ***************************************/
+void RTC_WakeUpClockConfig(uint32_t RTC_WakeUpClock);
+void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter);
+uint32_t RTC_GetWakeUpCounter(void);
+ErrorStatus RTC_WakeUpCmd(FunctionalState NewState);
+
+/* Daylight Saving configuration functions ************************************/
+void RTC_DayLightSavingConfig(uint32_t RTC_DayLightSaving, uint32_t RTC_StoreOperation);
+uint32_t RTC_GetStoreOperation(void);
+
+/* Output pin Configuration function ******************************************/
+void RTC_OutputConfig(uint32_t RTC_Output, uint32_t RTC_OutputPolarity);
+
+/* Coarse Calibration configuration functions *********************************/
+ErrorStatus RTC_CoarseCalibConfig(uint32_t RTC_CalibSign, uint32_t Value);
+ErrorStatus RTC_CoarseCalibCmd(FunctionalState NewState);
+void RTC_CalibOutputCmd(FunctionalState NewState);
+
+/* TimeStamp configuration functions ******************************************/
+void RTC_TimeStampCmd(uint32_t RTC_TimeStampEdge, FunctionalState NewState);
+void RTC_GetTimeStamp(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_StampTimeStruct,
+                                      RTC_DateTypeDef* RTC_StampDateStruct);                                  
+
+/* Tampers configuration functions ********************************************/
+void RTC_TamperTriggerConfig(uint32_t RTC_Tamper, uint32_t RTC_TamperTrigger);
+void RTC_TamperCmd(uint32_t RTC_Tamper, FunctionalState NewState);
+
+/* Backup Data Registers configuration functions ******************************/
+void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data);
+uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR);
+
+/* RTC Tamper and TimeStamp Pins Selection and Output Type Config configuration
+   functions ******************************************************************/
+void RTC_TamperPinSelection(uint32_t RTC_TamperPin);
+void RTC_TimeStampPinSelection(uint32_t RTC_TimeStampPin);
+void RTC_OutputTypeConfig(uint32_t RTC_OutputType);
+
+/* Interrupts and flags management functions **********************************/
+void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState);
+FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG);
+void RTC_ClearFlag(uint32_t RTC_FLAG);
+ITStatus RTC_GetITStatus(uint32_t RTC_IT);
+void RTC_ClearITPendingBit(uint32_t RTC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_RTC_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 528 - 0
app/Libraries/inc/stm32f2xx_sdio.h

@@ -0,0 +1,528 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_sdio.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the SDIO firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_SDIO_H
+#define __STM32F2xx_SDIO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup SDIO
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+typedef struct
+{
+  uint32_t SDIO_ClockEdge;            /*!< Specifies the clock transition on which the bit capture is made.
+                                           This parameter can be a value of @ref SDIO_Clock_Edge */
+
+  uint32_t SDIO_ClockBypass;          /*!< Specifies whether the SDIO Clock divider bypass is
+                                           enabled or disabled.
+                                           This parameter can be a value of @ref SDIO_Clock_Bypass */
+
+  uint32_t SDIO_ClockPowerSave;       /*!< Specifies whether SDIO Clock output is enabled or
+                                           disabled when the bus is idle.
+                                           This parameter can be a value of @ref SDIO_Clock_Power_Save */
+
+  uint32_t SDIO_BusWide;              /*!< Specifies the SDIO bus width.
+                                           This parameter can be a value of @ref SDIO_Bus_Wide */
+
+  uint32_t SDIO_HardwareFlowControl;  /*!< Specifies whether the SDIO hardware flow control is enabled or disabled.
+                                           This parameter can be a value of @ref SDIO_Hardware_Flow_Control */
+
+  uint8_t SDIO_ClockDiv;              /*!< Specifies the clock frequency of the SDIO controller.
+                                           This parameter can be a value between 0x00 and 0xFF. */
+                                           
+} SDIO_InitTypeDef;
+
+typedef struct
+{
+  uint32_t SDIO_Argument;  /*!< Specifies the SDIO command argument which is sent
+                                to a card as part of a command message. If a command
+                                contains an argument, it must be loaded into this register
+                                before writing the command to the command register */
+
+  uint32_t SDIO_CmdIndex;  /*!< Specifies the SDIO command index. It must be lower than 0x40. */
+
+  uint32_t SDIO_Response;  /*!< Specifies the SDIO response type.
+                                This parameter can be a value of @ref SDIO_Response_Type */
+
+  uint32_t SDIO_Wait;      /*!< Specifies whether SDIO wait-for-interrupt request is enabled or disabled.
+                                This parameter can be a value of @ref SDIO_Wait_Interrupt_State */
+
+  uint32_t SDIO_CPSM;      /*!< Specifies whether SDIO Command path state machine (CPSM)
+                                is enabled or disabled.
+                                This parameter can be a value of @ref SDIO_CPSM_State */
+} SDIO_CmdInitTypeDef;
+
+typedef struct
+{
+  uint32_t SDIO_DataTimeOut;    /*!< Specifies the data timeout period in card bus clock periods. */
+
+  uint32_t SDIO_DataLength;     /*!< Specifies the number of data bytes to be transferred. */
+ 
+  uint32_t SDIO_DataBlockSize;  /*!< Specifies the data block size for block transfer.
+                                     This parameter can be a value of @ref SDIO_Data_Block_Size */
+ 
+  uint32_t SDIO_TransferDir;    /*!< Specifies the data transfer direction, whether the transfer
+                                     is a read or write.
+                                     This parameter can be a value of @ref SDIO_Transfer_Direction */
+ 
+  uint32_t SDIO_TransferMode;   /*!< Specifies whether data transfer is in stream or block mode.
+                                     This parameter can be a value of @ref SDIO_Transfer_Type */
+ 
+  uint32_t SDIO_DPSM;           /*!< Specifies whether SDIO Data path state machine (DPSM)
+                                     is enabled or disabled.
+                                     This parameter can be a value of @ref SDIO_DPSM_State */
+} SDIO_DataInitTypeDef;
+
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup SDIO_Exported_Constants
+  * @{
+  */
+
+/** @defgroup SDIO_Clock_Edge 
+  * @{
+  */
+
+#define SDIO_ClockEdge_Rising               ((uint32_t)0x00000000)
+#define SDIO_ClockEdge_Falling              ((uint32_t)0x00002000)
+#define IS_SDIO_CLOCK_EDGE(EDGE) (((EDGE) == SDIO_ClockEdge_Rising) || \
+                                  ((EDGE) == SDIO_ClockEdge_Falling))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Clock_Bypass 
+  * @{
+  */
+
+#define SDIO_ClockBypass_Disable             ((uint32_t)0x00000000)
+#define SDIO_ClockBypass_Enable              ((uint32_t)0x00000400)    
+#define IS_SDIO_CLOCK_BYPASS(BYPASS) (((BYPASS) == SDIO_ClockBypass_Disable) || \
+                                     ((BYPASS) == SDIO_ClockBypass_Enable))
+/**
+  * @}
+  */ 
+
+/** @defgroup SDIO_Clock_Power_Save 
+  * @{
+  */
+
+#define SDIO_ClockPowerSave_Disable         ((uint32_t)0x00000000)
+#define SDIO_ClockPowerSave_Enable          ((uint32_t)0x00000200) 
+#define IS_SDIO_CLOCK_POWER_SAVE(SAVE) (((SAVE) == SDIO_ClockPowerSave_Disable) || \
+                                        ((SAVE) == SDIO_ClockPowerSave_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Bus_Wide 
+  * @{
+  */
+
+#define SDIO_BusWide_1b                     ((uint32_t)0x00000000)
+#define SDIO_BusWide_4b                     ((uint32_t)0x00000800)
+#define SDIO_BusWide_8b                     ((uint32_t)0x00001000)
+#define IS_SDIO_BUS_WIDE(WIDE) (((WIDE) == SDIO_BusWide_1b) || ((WIDE) == SDIO_BusWide_4b) || \
+                                ((WIDE) == SDIO_BusWide_8b))
+
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Hardware_Flow_Control 
+  * @{
+  */
+
+#define SDIO_HardwareFlowControl_Disable    ((uint32_t)0x00000000)
+#define SDIO_HardwareFlowControl_Enable     ((uint32_t)0x00004000)
+#define IS_SDIO_HARDWARE_FLOW_CONTROL(CONTROL) (((CONTROL) == SDIO_HardwareFlowControl_Disable) || \
+                                                ((CONTROL) == SDIO_HardwareFlowControl_Enable))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Power_State 
+  * @{
+  */
+
+#define SDIO_PowerState_OFF                 ((uint32_t)0x00000000)
+#define SDIO_PowerState_ON                  ((uint32_t)0x00000003)
+#define IS_SDIO_POWER_STATE(STATE) (((STATE) == SDIO_PowerState_OFF) || ((STATE) == SDIO_PowerState_ON))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup SDIO_Interrupt_sources
+  * @{
+  */
+
+#define SDIO_IT_CCRCFAIL                    ((uint32_t)0x00000001)
+#define SDIO_IT_DCRCFAIL                    ((uint32_t)0x00000002)
+#define SDIO_IT_CTIMEOUT                    ((uint32_t)0x00000004)
+#define SDIO_IT_DTIMEOUT                    ((uint32_t)0x00000008)
+#define SDIO_IT_TXUNDERR                    ((uint32_t)0x00000010)
+#define SDIO_IT_RXOVERR                     ((uint32_t)0x00000020)
+#define SDIO_IT_CMDREND                     ((uint32_t)0x00000040)
+#define SDIO_IT_CMDSENT                     ((uint32_t)0x00000080)
+#define SDIO_IT_DATAEND                     ((uint32_t)0x00000100)
+#define SDIO_IT_STBITERR                    ((uint32_t)0x00000200)
+#define SDIO_IT_DBCKEND                     ((uint32_t)0x00000400)
+#define SDIO_IT_CMDACT                      ((uint32_t)0x00000800)
+#define SDIO_IT_TXACT                       ((uint32_t)0x00001000)
+#define SDIO_IT_RXACT                       ((uint32_t)0x00002000)
+#define SDIO_IT_TXFIFOHE                    ((uint32_t)0x00004000)
+#define SDIO_IT_RXFIFOHF                    ((uint32_t)0x00008000)
+#define SDIO_IT_TXFIFOF                     ((uint32_t)0x00010000)
+#define SDIO_IT_RXFIFOF                     ((uint32_t)0x00020000)
+#define SDIO_IT_TXFIFOE                     ((uint32_t)0x00040000)
+#define SDIO_IT_RXFIFOE                     ((uint32_t)0x00080000)
+#define SDIO_IT_TXDAVL                      ((uint32_t)0x00100000)
+#define SDIO_IT_RXDAVL                      ((uint32_t)0x00200000)
+#define SDIO_IT_SDIOIT                      ((uint32_t)0x00400000)
+#define SDIO_IT_CEATAEND                    ((uint32_t)0x00800000)
+#define IS_SDIO_IT(IT) ((((IT) & (uint32_t)0xFF000000) == 0x00) && ((IT) != (uint32_t)0x00))
+/**
+  * @}
+  */ 
+
+/** @defgroup SDIO_Command_Index
+  * @{
+  */
+
+#define IS_SDIO_CMD_INDEX(INDEX)            ((INDEX) < 0x40)
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Response_Type
+  * @{
+  */
+
+#define SDIO_Response_No                    ((uint32_t)0x00000000)
+#define SDIO_Response_Short                 ((uint32_t)0x00000040)
+#define SDIO_Response_Long                  ((uint32_t)0x000000C0)
+#define IS_SDIO_RESPONSE(RESPONSE) (((RESPONSE) == SDIO_Response_No) || \
+                                    ((RESPONSE) == SDIO_Response_Short) || \
+                                    ((RESPONSE) == SDIO_Response_Long))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Wait_Interrupt_State
+  * @{
+  */
+
+#define SDIO_Wait_No                        ((uint32_t)0x00000000) /*!< SDIO No Wait, TimeOut is enabled */
+#define SDIO_Wait_IT                        ((uint32_t)0x00000100) /*!< SDIO Wait Interrupt Request */
+#define SDIO_Wait_Pend                      ((uint32_t)0x00000200) /*!< SDIO Wait End of transfer */
+#define IS_SDIO_WAIT(WAIT) (((WAIT) == SDIO_Wait_No) || ((WAIT) == SDIO_Wait_IT) || \
+                            ((WAIT) == SDIO_Wait_Pend))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_CPSM_State
+  * @{
+  */
+
+#define SDIO_CPSM_Disable                    ((uint32_t)0x00000000)
+#define SDIO_CPSM_Enable                     ((uint32_t)0x00000400)
+#define IS_SDIO_CPSM(CPSM) (((CPSM) == SDIO_CPSM_Enable) || ((CPSM) == SDIO_CPSM_Disable))
+/**
+  * @}
+  */ 
+
+/** @defgroup SDIO_Response_Registers
+  * @{
+  */
+
+#define SDIO_RESP1                          ((uint32_t)0x00000000)
+#define SDIO_RESP2                          ((uint32_t)0x00000004)
+#define SDIO_RESP3                          ((uint32_t)0x00000008)
+#define SDIO_RESP4                          ((uint32_t)0x0000000C)
+#define IS_SDIO_RESP(RESP) (((RESP) == SDIO_RESP1) || ((RESP) == SDIO_RESP2) || \
+                            ((RESP) == SDIO_RESP3) || ((RESP) == SDIO_RESP4))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Data_Length 
+  * @{
+  */
+
+#define IS_SDIO_DATA_LENGTH(LENGTH) ((LENGTH) <= 0x01FFFFFF)
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Data_Block_Size 
+  * @{
+  */
+
+#define SDIO_DataBlockSize_1b               ((uint32_t)0x00000000)
+#define SDIO_DataBlockSize_2b               ((uint32_t)0x00000010)
+#define SDIO_DataBlockSize_4b               ((uint32_t)0x00000020)
+#define SDIO_DataBlockSize_8b               ((uint32_t)0x00000030)
+#define SDIO_DataBlockSize_16b              ((uint32_t)0x00000040)
+#define SDIO_DataBlockSize_32b              ((uint32_t)0x00000050)
+#define SDIO_DataBlockSize_64b              ((uint32_t)0x00000060)
+#define SDIO_DataBlockSize_128b             ((uint32_t)0x00000070)
+#define SDIO_DataBlockSize_256b             ((uint32_t)0x00000080)
+#define SDIO_DataBlockSize_512b             ((uint32_t)0x00000090)
+#define SDIO_DataBlockSize_1024b            ((uint32_t)0x000000A0)
+#define SDIO_DataBlockSize_2048b            ((uint32_t)0x000000B0)
+#define SDIO_DataBlockSize_4096b            ((uint32_t)0x000000C0)
+#define SDIO_DataBlockSize_8192b            ((uint32_t)0x000000D0)
+#define SDIO_DataBlockSize_16384b           ((uint32_t)0x000000E0)
+#define IS_SDIO_BLOCK_SIZE(SIZE) (((SIZE) == SDIO_DataBlockSize_1b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_2b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_4b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_8b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_16b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_32b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_64b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_128b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_256b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_512b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_1024b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_2048b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_4096b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_8192b) || \
+                                  ((SIZE) == SDIO_DataBlockSize_16384b)) 
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Transfer_Direction 
+  * @{
+  */
+
+#define SDIO_TransferDir_ToCard             ((uint32_t)0x00000000)
+#define SDIO_TransferDir_ToSDIO             ((uint32_t)0x00000002)
+#define IS_SDIO_TRANSFER_DIR(DIR) (((DIR) == SDIO_TransferDir_ToCard) || \
+                                   ((DIR) == SDIO_TransferDir_ToSDIO))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Transfer_Type 
+  * @{
+  */
+
+#define SDIO_TransferMode_Block             ((uint32_t)0x00000000)
+#define SDIO_TransferMode_Stream            ((uint32_t)0x00000004)
+#define IS_SDIO_TRANSFER_MODE(MODE) (((MODE) == SDIO_TransferMode_Stream) || \
+                                     ((MODE) == SDIO_TransferMode_Block))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_DPSM_State 
+  * @{
+  */
+
+#define SDIO_DPSM_Disable                    ((uint32_t)0x00000000)
+#define SDIO_DPSM_Enable                     ((uint32_t)0x00000001)
+#define IS_SDIO_DPSM(DPSM) (((DPSM) == SDIO_DPSM_Enable) || ((DPSM) == SDIO_DPSM_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Flags 
+  * @{
+  */
+
+#define SDIO_FLAG_CCRCFAIL                  ((uint32_t)0x00000001)
+#define SDIO_FLAG_DCRCFAIL                  ((uint32_t)0x00000002)
+#define SDIO_FLAG_CTIMEOUT                  ((uint32_t)0x00000004)
+#define SDIO_FLAG_DTIMEOUT                  ((uint32_t)0x00000008)
+#define SDIO_FLAG_TXUNDERR                  ((uint32_t)0x00000010)
+#define SDIO_FLAG_RXOVERR                   ((uint32_t)0x00000020)
+#define SDIO_FLAG_CMDREND                   ((uint32_t)0x00000040)
+#define SDIO_FLAG_CMDSENT                   ((uint32_t)0x00000080)
+#define SDIO_FLAG_DATAEND                   ((uint32_t)0x00000100)
+#define SDIO_FLAG_STBITERR                  ((uint32_t)0x00000200)
+#define SDIO_FLAG_DBCKEND                   ((uint32_t)0x00000400)
+#define SDIO_FLAG_CMDACT                    ((uint32_t)0x00000800)
+#define SDIO_FLAG_TXACT                     ((uint32_t)0x00001000)
+#define SDIO_FLAG_RXACT                     ((uint32_t)0x00002000)
+#define SDIO_FLAG_TXFIFOHE                  ((uint32_t)0x00004000)
+#define SDIO_FLAG_RXFIFOHF                  ((uint32_t)0x00008000)
+#define SDIO_FLAG_TXFIFOF                   ((uint32_t)0x00010000)
+#define SDIO_FLAG_RXFIFOF                   ((uint32_t)0x00020000)
+#define SDIO_FLAG_TXFIFOE                   ((uint32_t)0x00040000)
+#define SDIO_FLAG_RXFIFOE                   ((uint32_t)0x00080000)
+#define SDIO_FLAG_TXDAVL                    ((uint32_t)0x00100000)
+#define SDIO_FLAG_RXDAVL                    ((uint32_t)0x00200000)
+#define SDIO_FLAG_SDIOIT                    ((uint32_t)0x00400000)
+#define SDIO_FLAG_CEATAEND                  ((uint32_t)0x00800000)
+#define IS_SDIO_FLAG(FLAG) (((FLAG)  == SDIO_FLAG_CCRCFAIL) || \
+                            ((FLAG)  == SDIO_FLAG_DCRCFAIL) || \
+                            ((FLAG)  == SDIO_FLAG_CTIMEOUT) || \
+                            ((FLAG)  == SDIO_FLAG_DTIMEOUT) || \
+                            ((FLAG)  == SDIO_FLAG_TXUNDERR) || \
+                            ((FLAG)  == SDIO_FLAG_RXOVERR) || \
+                            ((FLAG)  == SDIO_FLAG_CMDREND) || \
+                            ((FLAG)  == SDIO_FLAG_CMDSENT) || \
+                            ((FLAG)  == SDIO_FLAG_DATAEND) || \
+                            ((FLAG)  == SDIO_FLAG_STBITERR) || \
+                            ((FLAG)  == SDIO_FLAG_DBCKEND) || \
+                            ((FLAG)  == SDIO_FLAG_CMDACT) || \
+                            ((FLAG)  == SDIO_FLAG_TXACT) || \
+                            ((FLAG)  == SDIO_FLAG_RXACT) || \
+                            ((FLAG)  == SDIO_FLAG_TXFIFOHE) || \
+                            ((FLAG)  == SDIO_FLAG_RXFIFOHF) || \
+                            ((FLAG)  == SDIO_FLAG_TXFIFOF) || \
+                            ((FLAG)  == SDIO_FLAG_RXFIFOF) || \
+                            ((FLAG)  == SDIO_FLAG_TXFIFOE) || \
+                            ((FLAG)  == SDIO_FLAG_RXFIFOE) || \
+                            ((FLAG)  == SDIO_FLAG_TXDAVL) || \
+                            ((FLAG)  == SDIO_FLAG_RXDAVL) || \
+                            ((FLAG)  == SDIO_FLAG_SDIOIT) || \
+                            ((FLAG)  == SDIO_FLAG_CEATAEND))
+
+#define IS_SDIO_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFF3FF800) == 0x00) && ((FLAG) != (uint32_t)0x00))
+
+#define IS_SDIO_GET_IT(IT) (((IT)  == SDIO_IT_CCRCFAIL) || \
+                            ((IT)  == SDIO_IT_DCRCFAIL) || \
+                            ((IT)  == SDIO_IT_CTIMEOUT) || \
+                            ((IT)  == SDIO_IT_DTIMEOUT) || \
+                            ((IT)  == SDIO_IT_TXUNDERR) || \
+                            ((IT)  == SDIO_IT_RXOVERR) || \
+                            ((IT)  == SDIO_IT_CMDREND) || \
+                            ((IT)  == SDIO_IT_CMDSENT) || \
+                            ((IT)  == SDIO_IT_DATAEND) || \
+                            ((IT)  == SDIO_IT_STBITERR) || \
+                            ((IT)  == SDIO_IT_DBCKEND) || \
+                            ((IT)  == SDIO_IT_CMDACT) || \
+                            ((IT)  == SDIO_IT_TXACT) || \
+                            ((IT)  == SDIO_IT_RXACT) || \
+                            ((IT)  == SDIO_IT_TXFIFOHE) || \
+                            ((IT)  == SDIO_IT_RXFIFOHF) || \
+                            ((IT)  == SDIO_IT_TXFIFOF) || \
+                            ((IT)  == SDIO_IT_RXFIFOF) || \
+                            ((IT)  == SDIO_IT_TXFIFOE) || \
+                            ((IT)  == SDIO_IT_RXFIFOE) || \
+                            ((IT)  == SDIO_IT_TXDAVL) || \
+                            ((IT)  == SDIO_IT_RXDAVL) || \
+                            ((IT)  == SDIO_IT_SDIOIT) || \
+                            ((IT)  == SDIO_IT_CEATAEND))
+
+#define IS_SDIO_CLEAR_IT(IT) ((((IT) & (uint32_t)0xFF3FF800) == 0x00) && ((IT) != (uint32_t)0x00))
+
+/**
+  * @}
+  */
+
+/** @defgroup SDIO_Read_Wait_Mode 
+  * @{
+  */
+
+#define SDIO_ReadWaitMode_CLK               ((uint32_t)0x00000000)
+#define SDIO_ReadWaitMode_DATA2             ((uint32_t)0x00000001)
+#define IS_SDIO_READWAIT_MODE(MODE) (((MODE) == SDIO_ReadWaitMode_CLK) || \
+                                     ((MODE) == SDIO_ReadWaitMode_DATA2))
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/*  Function used to set the SDIO configuration to the default reset state ****/
+void SDIO_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct);
+void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct);
+void SDIO_ClockCmd(FunctionalState NewState);
+void SDIO_SetPowerState(uint32_t SDIO_PowerState);
+uint32_t SDIO_GetPowerState(void);
+
+/* Command path state machine (CPSM) management functions *********************/
+void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct);
+void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct);
+uint8_t SDIO_GetCommandResponse(void);
+uint32_t SDIO_GetResponse(uint32_t SDIO_RESP);
+
+/* Data path state machine (DPSM) management functions ************************/
+void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct);
+void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct);
+uint32_t SDIO_GetDataCounter(void);
+uint32_t SDIO_ReadData(void);
+void SDIO_WriteData(uint32_t Data);
+uint32_t SDIO_GetFIFOCount(void);
+
+/* SDIO IO Cards mode management functions ************************************/
+void SDIO_StartSDIOReadWait(FunctionalState NewState);
+void SDIO_StopSDIOReadWait(FunctionalState NewState);
+void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode);
+void SDIO_SetSDIOOperation(FunctionalState NewState);
+void SDIO_SendSDIOSuspendCmd(FunctionalState NewState);
+
+/* CE-ATA mode management functions *******************************************/
+void SDIO_CommandCompletionCmd(FunctionalState NewState);
+void SDIO_CEATAITCmd(FunctionalState NewState);
+void SDIO_SendCEATACmd(FunctionalState NewState);
+
+/* DMA transfers management functions *****************************************/
+void SDIO_DMACmd(FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState);
+FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG);
+void SDIO_ClearFlag(uint32_t SDIO_FLAG);
+ITStatus SDIO_GetITStatus(uint32_t SDIO_IT);
+void SDIO_ClearITPendingBit(uint32_t SDIO_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_SDIO_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 518 - 0
app/Libraries/inc/stm32f2xx_spi.h

@@ -0,0 +1,518 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_spi.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the SPI 
+  *          firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_SPI_H
+#define __STM32F2xx_SPI_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup SPI
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  SPI Init structure definition  
+  */
+
+typedef struct
+{
+  uint16_t SPI_Direction;           /*!< Specifies the SPI unidirectional or bidirectional data mode.
+                                         This parameter can be a value of @ref SPI_data_direction */
+
+  uint16_t SPI_Mode;                /*!< Specifies the SPI operating mode.
+                                         This parameter can be a value of @ref SPI_mode */
+
+  uint16_t SPI_DataSize;            /*!< Specifies the SPI data size.
+                                         This parameter can be a value of @ref SPI_data_size */
+
+  uint16_t SPI_CPOL;                /*!< Specifies the serial clock steady state.
+                                         This parameter can be a value of @ref SPI_Clock_Polarity */
+
+  uint16_t SPI_CPHA;                /*!< Specifies the clock active edge for the bit capture.
+                                         This parameter can be a value of @ref SPI_Clock_Phase */
+
+  uint16_t SPI_NSS;                 /*!< Specifies whether the NSS signal is managed by
+                                         hardware (NSS pin) or by software using the SSI bit.
+                                         This parameter can be a value of @ref SPI_Slave_Select_management */
+ 
+  uint16_t SPI_BaudRatePrescaler;   /*!< Specifies the Baud Rate prescaler value which will be
+                                         used to configure the transmit and receive SCK clock.
+                                         This parameter can be a value of @ref SPI_BaudRate_Prescaler
+                                         @note The communication clock is derived from the master
+                                               clock. The slave clock does not need to be set. */
+
+  uint16_t SPI_FirstBit;            /*!< Specifies whether data transfers start from MSB or LSB bit.
+                                         This parameter can be a value of @ref SPI_MSB_LSB_transmission */
+
+  uint16_t SPI_CRCPolynomial;       /*!< Specifies the polynomial used for the CRC calculation. */
+}SPI_InitTypeDef;
+
+/** 
+  * @brief  I2S Init structure definition  
+  */
+
+typedef struct
+{
+
+  uint16_t I2S_Mode;         /*!< Specifies the I2S operating mode.
+                                  This parameter can be a value of @ref I2S_Mode */
+
+  uint16_t I2S_Standard;     /*!< Specifies the standard used for the I2S communication.
+                                  This parameter can be a value of @ref I2S_Standard */
+
+  uint16_t I2S_DataFormat;   /*!< Specifies the data format for the I2S communication.
+                                  This parameter can be a value of @ref I2S_Data_Format */
+
+  uint16_t I2S_MCLKOutput;   /*!< Specifies whether the I2S MCLK output is enabled or not.
+                                  This parameter can be a value of @ref I2S_MCLK_Output */
+
+  uint32_t I2S_AudioFreq;    /*!< Specifies the frequency selected for the I2S communication.
+                                  This parameter can be a value of @ref I2S_Audio_Frequency */
+
+  uint16_t I2S_CPOL;         /*!< Specifies the idle state of the I2S clock.
+                                  This parameter can be a value of @ref I2S_Clock_Polarity */
+}I2S_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup SPI_Exported_Constants
+  * @{
+  */
+
+#define IS_SPI_ALL_PERIPH(PERIPH) (((PERIPH) == SPI1) || \
+                                   ((PERIPH) == SPI2) || \
+                                   ((PERIPH) == SPI3))
+
+#define IS_SPI_23_PERIPH(PERIPH)  (((PERIPH) == SPI2) || \
+                                   ((PERIPH) == SPI3))
+
+/** @defgroup SPI_data_direction 
+  * @{
+  */
+  
+#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)
+#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)
+#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)
+#define SPI_Direction_1Line_Tx          ((uint16_t)0xC000)
+#define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \
+                                     ((MODE) == SPI_Direction_2Lines_RxOnly) || \
+                                     ((MODE) == SPI_Direction_1Line_Rx) || \
+                                     ((MODE) == SPI_Direction_1Line_Tx))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_mode 
+  * @{
+  */
+
+#define SPI_Mode_Master                 ((uint16_t)0x0104)
+#define SPI_Mode_Slave                  ((uint16_t)0x0000)
+#define IS_SPI_MODE(MODE) (((MODE) == SPI_Mode_Master) || \
+                           ((MODE) == SPI_Mode_Slave))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_data_size 
+  * @{
+  */
+
+#define SPI_DataSize_16b                ((uint16_t)0x0800)
+#define SPI_DataSize_8b                 ((uint16_t)0x0000)
+#define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DataSize_16b) || \
+                                   ((DATASIZE) == SPI_DataSize_8b))
+/**
+  * @}
+  */ 
+
+/** @defgroup SPI_Clock_Polarity 
+  * @{
+  */
+
+#define SPI_CPOL_Low                    ((uint16_t)0x0000)
+#define SPI_CPOL_High                   ((uint16_t)0x0002)
+#define IS_SPI_CPOL(CPOL) (((CPOL) == SPI_CPOL_Low) || \
+                           ((CPOL) == SPI_CPOL_High))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Clock_Phase 
+  * @{
+  */
+
+#define SPI_CPHA_1Edge                  ((uint16_t)0x0000)
+#define SPI_CPHA_2Edge                  ((uint16_t)0x0001)
+#define IS_SPI_CPHA(CPHA) (((CPHA) == SPI_CPHA_1Edge) || \
+                           ((CPHA) == SPI_CPHA_2Edge))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Slave_Select_management 
+  * @{
+  */
+
+#define SPI_NSS_Soft                    ((uint16_t)0x0200)
+#define SPI_NSS_Hard                    ((uint16_t)0x0000)
+#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_Soft) || \
+                         ((NSS) == SPI_NSS_Hard))
+/**
+  * @}
+  */ 
+
+/** @defgroup SPI_BaudRate_Prescaler 
+  * @{
+  */
+
+#define SPI_BaudRatePrescaler_2         ((uint16_t)0x0000)
+#define SPI_BaudRatePrescaler_4         ((uint16_t)0x0008)
+#define SPI_BaudRatePrescaler_8         ((uint16_t)0x0010)
+#define SPI_BaudRatePrescaler_16        ((uint16_t)0x0018)
+#define SPI_BaudRatePrescaler_32        ((uint16_t)0x0020)
+#define SPI_BaudRatePrescaler_64        ((uint16_t)0x0028)
+#define SPI_BaudRatePrescaler_128       ((uint16_t)0x0030)
+#define SPI_BaudRatePrescaler_256       ((uint16_t)0x0038)
+#define IS_SPI_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == SPI_BaudRatePrescaler_2) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_4) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_8) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_16) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_32) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_64) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_128) || \
+                                              ((PRESCALER) == SPI_BaudRatePrescaler_256))
+/**
+  * @}
+  */ 
+
+/** @defgroup SPI_MSB_LSB_transmission 
+  * @{
+  */
+
+#define SPI_FirstBit_MSB                ((uint16_t)0x0000)
+#define SPI_FirstBit_LSB                ((uint16_t)0x0080)
+#define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FirstBit_MSB) || \
+                               ((BIT) == SPI_FirstBit_LSB))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_Mode 
+  * @{
+  */
+
+#define I2S_Mode_SlaveTx                ((uint16_t)0x0000)
+#define I2S_Mode_SlaveRx                ((uint16_t)0x0100)
+#define I2S_Mode_MasterTx               ((uint16_t)0x0200)
+#define I2S_Mode_MasterRx               ((uint16_t)0x0300)
+#define IS_I2S_MODE(MODE) (((MODE) == I2S_Mode_SlaveTx) || \
+                           ((MODE) == I2S_Mode_SlaveRx) || \
+                           ((MODE) == I2S_Mode_MasterTx)|| \
+                           ((MODE) == I2S_Mode_MasterRx))
+/**
+  * @}
+  */
+  
+
+/** @defgroup SPI_I2S_Standard 
+  * @{
+  */
+
+#define I2S_Standard_Phillips           ((uint16_t)0x0000)
+#define I2S_Standard_MSB                ((uint16_t)0x0010)
+#define I2S_Standard_LSB                ((uint16_t)0x0020)
+#define I2S_Standard_PCMShort           ((uint16_t)0x0030)
+#define I2S_Standard_PCMLong            ((uint16_t)0x00B0)
+#define IS_I2S_STANDARD(STANDARD) (((STANDARD) == I2S_Standard_Phillips) || \
+                                   ((STANDARD) == I2S_Standard_MSB) || \
+                                   ((STANDARD) == I2S_Standard_LSB) || \
+                                   ((STANDARD) == I2S_Standard_PCMShort) || \
+                                   ((STANDARD) == I2S_Standard_PCMLong))
+/**
+  * @}
+  */
+  
+/** @defgroup SPI_I2S_Data_Format 
+  * @{
+  */
+
+#define I2S_DataFormat_16b              ((uint16_t)0x0000)
+#define I2S_DataFormat_16bextended      ((uint16_t)0x0001)
+#define I2S_DataFormat_24b              ((uint16_t)0x0003)
+#define I2S_DataFormat_32b              ((uint16_t)0x0005)
+#define IS_I2S_DATA_FORMAT(FORMAT) (((FORMAT) == I2S_DataFormat_16b) || \
+                                    ((FORMAT) == I2S_DataFormat_16bextended) || \
+                                    ((FORMAT) == I2S_DataFormat_24b) || \
+                                    ((FORMAT) == I2S_DataFormat_32b))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_MCLK_Output 
+  * @{
+  */
+
+#define I2S_MCLKOutput_Enable           ((uint16_t)0x0200)
+#define I2S_MCLKOutput_Disable          ((uint16_t)0x0000)
+#define IS_I2S_MCLK_OUTPUT(OUTPUT) (((OUTPUT) == I2S_MCLKOutput_Enable) || \
+                                    ((OUTPUT) == I2S_MCLKOutput_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_Audio_Frequency 
+  * @{
+  */
+
+#define I2S_AudioFreq_192k               ((uint32_t)192000)
+#define I2S_AudioFreq_96k                ((uint32_t)96000)
+#define I2S_AudioFreq_48k                ((uint32_t)48000)
+#define I2S_AudioFreq_44k                ((uint32_t)44100)
+#define I2S_AudioFreq_32k                ((uint32_t)32000)
+#define I2S_AudioFreq_22k                ((uint32_t)22050)
+#define I2S_AudioFreq_16k                ((uint32_t)16000)
+#define I2S_AudioFreq_11k                ((uint32_t)11025)
+#define I2S_AudioFreq_8k                 ((uint32_t)8000)
+#define I2S_AudioFreq_Default            ((uint32_t)2)
+
+#define IS_I2S_AUDIO_FREQ(FREQ) ((((FREQ) >= I2S_AudioFreq_8k) && \
+                                 ((FREQ) <= I2S_AudioFreq_192k)) || \
+                                 ((FREQ) == I2S_AudioFreq_Default))
+/**
+  * @}
+  */
+            
+/** @defgroup SPI_I2S_Clock_Polarity 
+  * @{
+  */
+
+#define I2S_CPOL_Low                    ((uint16_t)0x0000)
+#define I2S_CPOL_High                   ((uint16_t)0x0008)
+#define IS_I2S_CPOL(CPOL) (((CPOL) == I2S_CPOL_Low) || \
+                           ((CPOL) == I2S_CPOL_High))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_DMA_transfer_requests 
+  * @{
+  */
+
+#define SPI_I2S_DMAReq_Tx               ((uint16_t)0x0002)
+#define SPI_I2S_DMAReq_Rx               ((uint16_t)0x0001)
+#define IS_SPI_I2S_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFFFC) == 0x00) && ((DMAREQ) != 0x00))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_NSS_internal_software_management 
+  * @{
+  */
+
+#define SPI_NSSInternalSoft_Set         ((uint16_t)0x0100)
+#define SPI_NSSInternalSoft_Reset       ((uint16_t)0xFEFF)
+#define IS_SPI_NSS_INTERNAL(INTERNAL) (((INTERNAL) == SPI_NSSInternalSoft_Set) || \
+                                       ((INTERNAL) == SPI_NSSInternalSoft_Reset))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_CRC_Transmit_Receive 
+  * @{
+  */
+
+#define SPI_CRC_Tx                      ((uint8_t)0x00)
+#define SPI_CRC_Rx                      ((uint8_t)0x01)
+#define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_Tx) || ((CRC) == SPI_CRC_Rx))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_direction_transmit_receive 
+  * @{
+  */
+
+#define SPI_Direction_Rx                ((uint16_t)0xBFFF)
+#define SPI_Direction_Tx                ((uint16_t)0x4000)
+#define IS_SPI_DIRECTION(DIRECTION) (((DIRECTION) == SPI_Direction_Rx) || \
+                                     ((DIRECTION) == SPI_Direction_Tx))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_interrupts_definition 
+  * @{
+  */
+
+#define SPI_I2S_IT_TXE                  ((uint8_t)0x71)
+#define SPI_I2S_IT_RXNE                 ((uint8_t)0x60)
+#define SPI_I2S_IT_ERR                  ((uint8_t)0x50)
+#define I2S_IT_UDR                      ((uint8_t)0x53)
+#define SPI_I2S_IT_TIFRFE               ((uint8_t)0x58)
+
+#define IS_SPI_I2S_CONFIG_IT(IT) (((IT) == SPI_I2S_IT_TXE) || \
+                                  ((IT) == SPI_I2S_IT_RXNE) || \
+                                  ((IT) == SPI_I2S_IT_ERR))
+
+#define SPI_I2S_IT_OVR                  ((uint8_t)0x56)
+#define SPI_IT_MODF                     ((uint8_t)0x55)
+#define SPI_IT_CRCERR                   ((uint8_t)0x54)
+
+#define IS_SPI_I2S_CLEAR_IT(IT) (((IT) == SPI_IT_CRCERR))
+
+#define IS_SPI_I2S_GET_IT(IT) (((IT) == SPI_I2S_IT_RXNE)|| ((IT) == SPI_I2S_IT_TXE) || \
+                               ((IT) == SPI_IT_CRCERR)  || ((IT) == SPI_IT_MODF) || \
+                               ((IT) == SPI_I2S_IT_OVR) || ((IT) == I2S_IT_UDR) ||\
+                               ((IT) == SPI_I2S_IT_TIFRFE))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_flags_definition 
+  * @{
+  */
+
+#define SPI_I2S_FLAG_RXNE               ((uint16_t)0x0001)
+#define SPI_I2S_FLAG_TXE                ((uint16_t)0x0002)
+#define I2S_FLAG_CHSIDE                 ((uint16_t)0x0004)
+#define I2S_FLAG_UDR                    ((uint16_t)0x0008)
+#define SPI_FLAG_CRCERR                 ((uint16_t)0x0010)
+#define SPI_FLAG_MODF                   ((uint16_t)0x0020)
+#define SPI_I2S_FLAG_OVR                ((uint16_t)0x0040)
+#define SPI_I2S_FLAG_BSY                ((uint16_t)0x0080)
+#define SPI_I2S_FLAG_TIFRFE             ((uint16_t)0x0100)
+
+#define IS_SPI_I2S_CLEAR_FLAG(FLAG) (((FLAG) == SPI_FLAG_CRCERR))
+#define IS_SPI_I2S_GET_FLAG(FLAG) (((FLAG) == SPI_I2S_FLAG_BSY) || ((FLAG) == SPI_I2S_FLAG_OVR) || \
+                                   ((FLAG) == SPI_FLAG_MODF) || ((FLAG) == SPI_FLAG_CRCERR) || \
+                                   ((FLAG) == I2S_FLAG_UDR) || ((FLAG) == I2S_FLAG_CHSIDE) || \
+                                   ((FLAG) == SPI_I2S_FLAG_TXE) || ((FLAG) == SPI_I2S_FLAG_RXNE)|| \
+                                   ((FLAG) == SPI_I2S_FLAG_TIFRFE))
+/**
+  * @}
+  */
+
+/** @defgroup SPI_CRC_polynomial 
+  * @{
+  */
+
+#define IS_SPI_CRC_POLYNOMIAL(POLYNOMIAL) ((POLYNOMIAL) >= 0x1)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_I2S_Legacy 
+  * @{
+  */
+
+#define SPI_DMAReq_Tx                SPI_I2S_DMAReq_Tx
+#define SPI_DMAReq_Rx                SPI_I2S_DMAReq_Rx
+#define SPI_IT_TXE                   SPI_I2S_IT_TXE
+#define SPI_IT_RXNE                  SPI_I2S_IT_RXNE
+#define SPI_IT_ERR                   SPI_I2S_IT_ERR
+#define SPI_IT_OVR                   SPI_I2S_IT_OVR
+#define SPI_FLAG_RXNE                SPI_I2S_FLAG_RXNE
+#define SPI_FLAG_TXE                 SPI_I2S_FLAG_TXE
+#define SPI_FLAG_OVR                 SPI_I2S_FLAG_OVR
+#define SPI_FLAG_BSY                 SPI_I2S_FLAG_BSY
+#define SPI_DeInit                   SPI_I2S_DeInit
+#define SPI_ITConfig                 SPI_I2S_ITConfig
+#define SPI_DMACmd                   SPI_I2S_DMACmd
+#define SPI_SendData                 SPI_I2S_SendData
+#define SPI_ReceiveData              SPI_I2S_ReceiveData
+#define SPI_GetFlagStatus            SPI_I2S_GetFlagStatus
+#define SPI_ClearFlag                SPI_I2S_ClearFlag
+#define SPI_GetITStatus              SPI_I2S_GetITStatus
+#define SPI_ClearITPendingBit        SPI_I2S_ClearITPendingBit
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+
+/*  Function used to set the SPI configuration to the default reset state *****/ 
+void SPI_I2S_DeInit(SPI_TypeDef* SPIx);
+
+/* Initialization and Configuration functions *********************************/
+void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
+void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct);
+void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);
+void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct);
+void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);
+void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);
+void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);
+void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+void SPI_TIModeCmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+
+/* Data transfers functions ***************************************************/ 
+void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
+uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
+
+/* Hardware CRC Calculation functions *****************************************/
+void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);
+void SPI_TransmitCRC(SPI_TypeDef* SPIx);
+uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);
+uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);
+
+/* DMA transfers management functions *****************************************/
+void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
+FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
+void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
+ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
+void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_SPI_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 171 - 0
app/Libraries/inc/stm32f2xx_syscfg.h

@@ -0,0 +1,171 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_syscfg.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the SYSCFG firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_SYSCFG_H
+#define __STM32F2xx_SYSCFG_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup SYSCFG
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+  
+/** @defgroup SYSCFG_Exported_Constants 
+  * @{
+  */ 
+
+/** @defgroup SYSCFG_EXTI_Port_Sources 
+  * @{
+  */ 
+#define EXTI_PortSourceGPIOA       ((uint8_t)0x00)
+#define EXTI_PortSourceGPIOB       ((uint8_t)0x01)
+#define EXTI_PortSourceGPIOC       ((uint8_t)0x02)
+#define EXTI_PortSourceGPIOD       ((uint8_t)0x03)
+#define EXTI_PortSourceGPIOE       ((uint8_t)0x04)
+#define EXTI_PortSourceGPIOF       ((uint8_t)0x05)
+#define EXTI_PortSourceGPIOG       ((uint8_t)0x06)
+#define EXTI_PortSourceGPIOH       ((uint8_t)0x07)
+#define EXTI_PortSourceGPIOI       ((uint8_t)0x08)
+                                      
+#define IS_EXTI_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == EXTI_PortSourceGPIOA) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOB) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOC) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOD) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOE) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOF) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOG) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOH) || \
+                                        ((PORTSOURCE) == EXTI_PortSourceGPIOI)) 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup SYSCFG_EXTI_Pin_Sources 
+  * @{
+  */ 
+#define EXTI_PinSource0            ((uint8_t)0x00)
+#define EXTI_PinSource1            ((uint8_t)0x01)
+#define EXTI_PinSource2            ((uint8_t)0x02)
+#define EXTI_PinSource3            ((uint8_t)0x03)
+#define EXTI_PinSource4            ((uint8_t)0x04)
+#define EXTI_PinSource5            ((uint8_t)0x05)
+#define EXTI_PinSource6            ((uint8_t)0x06)
+#define EXTI_PinSource7            ((uint8_t)0x07)
+#define EXTI_PinSource8            ((uint8_t)0x08)
+#define EXTI_PinSource9            ((uint8_t)0x09)
+#define EXTI_PinSource10           ((uint8_t)0x0A)
+#define EXTI_PinSource11           ((uint8_t)0x0B)
+#define EXTI_PinSource12           ((uint8_t)0x0C)
+#define EXTI_PinSource13           ((uint8_t)0x0D)
+#define EXTI_PinSource14           ((uint8_t)0x0E)
+#define EXTI_PinSource15           ((uint8_t)0x0F)
+#define IS_EXTI_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == EXTI_PinSource0) || \
+                                       ((PINSOURCE) == EXTI_PinSource1) || \
+                                       ((PINSOURCE) == EXTI_PinSource2) || \
+                                       ((PINSOURCE) == EXTI_PinSource3) || \
+                                       ((PINSOURCE) == EXTI_PinSource4) || \
+                                       ((PINSOURCE) == EXTI_PinSource5) || \
+                                       ((PINSOURCE) == EXTI_PinSource6) || \
+                                       ((PINSOURCE) == EXTI_PinSource7) || \
+                                       ((PINSOURCE) == EXTI_PinSource8) || \
+                                       ((PINSOURCE) == EXTI_PinSource9) || \
+                                       ((PINSOURCE) == EXTI_PinSource10) || \
+                                       ((PINSOURCE) == EXTI_PinSource11) || \
+                                       ((PINSOURCE) == EXTI_PinSource12) || \
+                                       ((PINSOURCE) == EXTI_PinSource13) || \
+                                       ((PINSOURCE) == EXTI_PinSource14) || \
+                                       ((PINSOURCE) == EXTI_PinSource15))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup SYSCFG_Memory_Remap_Config 
+  * @{
+  */ 
+#define SYSCFG_MemoryRemap_Flash       ((uint8_t)0x00)
+#define SYSCFG_MemoryRemap_SystemFlash ((uint8_t)0x01)
+#define SYSCFG_MemoryRemap_FSMC        ((uint8_t)0x02)
+#define SYSCFG_MemoryRemap_SRAM        ((uint8_t)0x03)
+   
+#define IS_SYSCFG_MEMORY_REMAP_CONFING(REMAP) (((REMAP) == SYSCFG_MemoryRemap_Flash) || \
+                                                     ((REMAP) == SYSCFG_MemoryRemap_SystemFlash) || \
+                                                     ((REMAP) == SYSCFG_MemoryRemap_SRAM) || \
+                                                     ((REMAP) == SYSCFG_MemoryRemap_FSMC))
+/**
+  * @}
+  */ 
+
+
+/** @defgroup SYSCFG_ETHERNET_Media_Interface 
+  * @{
+  */ 
+#define SYSCFG_ETH_MediaInterface_MII    ((uint32_t)0x00000000) 
+#define SYSCFG_ETH_MediaInterface_RMII   ((uint32_t)0x00000001)                                       
+
+#define IS_SYSCFG_ETH_MEDIA_INTERFACE(INTERFACE) (((INTERFACE) == SYSCFG_ETH_MediaInterface_MII) || \
+                                                ((INTERFACE) == SYSCFG_ETH_MediaInterface_RMII))
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/ 
+ 
+void SYSCFG_DeInit(void);
+void SYSCFG_MemoryRemapConfig(uint8_t SYSCFG_MemoryRemap);
+void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);
+void SYSCFG_ETH_MediaInterfaceConfig(uint32_t SYSCFG_ETH_MediaInterface); 
+void SYSCFG_CompensationCellCmd(FunctionalState NewState); 
+FlagStatus SYSCFG_GetCompensationCellStatus(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F2xx_SYSCFG_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1142 - 0
app/Libraries/inc/stm32f2xx_tim.h


+ 421 - 0
app/Libraries/inc/stm32f2xx_usart.h

@@ -0,0 +1,421 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_usart.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the USART 
+  *          firmware library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_USART_H
+#define __STM32F2xx_USART_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup USART
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/ 
+
+/** 
+  * @brief  USART Init Structure definition  
+  */ 
+  
+typedef struct
+{
+  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
+                                           The baud rate is computed using the following formula:
+                                            - IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (USART_InitStruct->USART_BaudRate)))
+                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 8 * (OVR8+1)) + 0.5 
+                                           Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */
+
+  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
+                                           This parameter can be a value of @ref USART_Word_Length */
+
+  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
+                                           This parameter can be a value of @ref USART_Stop_Bits */
+
+  uint16_t USART_Parity;              /*!< Specifies the parity mode.
+                                           This parameter can be a value of @ref USART_Parity
+                                           @note When parity is enabled, the computed parity is inserted
+                                                 at the MSB position of the transmitted data (9th bit when
+                                                 the word length is set to 9 data bits; 8th bit when the
+                                                 word length is set to 8 data bits). */
+ 
+  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
+                                           This parameter can be a value of @ref USART_Mode */
+
+  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
+                                           or disabled.
+                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
+} USART_InitTypeDef;
+
+/** 
+  * @brief  USART Clock Init Structure definition  
+  */ 
+  
+typedef struct
+{
+
+  uint16_t USART_Clock;   /*!< Specifies whether the USART clock is enabled or disabled.
+                               This parameter can be a value of @ref USART_Clock */
+
+  uint16_t USART_CPOL;    /*!< Specifies the steady state of the serial clock.
+                               This parameter can be a value of @ref USART_Clock_Polarity */
+
+  uint16_t USART_CPHA;    /*!< Specifies the clock transition on which the bit capture is made.
+                               This parameter can be a value of @ref USART_Clock_Phase */
+
+  uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted
+                               data bit (MSB) has to be output on the SCLK pin in synchronous mode.
+                               This parameter can be a value of @ref USART_Last_Bit */
+} USART_ClockInitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup USART_Exported_Constants
+  * @{
+  */ 
+  
+#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
+                                     ((PERIPH) == USART2) || \
+                                     ((PERIPH) == USART3) || \
+                                     ((PERIPH) == UART4)  || \
+                                     ((PERIPH) == UART5)  || \
+                                     ((PERIPH) == USART6))
+
+#define IS_USART_1236_PERIPH(PERIPH) (((PERIPH) == USART1) || \
+                                      ((PERIPH) == USART2) || \
+                                      ((PERIPH) == USART3) || \
+                                      ((PERIPH) == USART6))
+
+/** @defgroup USART_Word_Length 
+  * @{
+  */ 
+  
+#define USART_WordLength_8b                  ((uint16_t)0x0000)
+#define USART_WordLength_9b                  ((uint16_t)0x1000)
+                                    
+#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \
+                                      ((LENGTH) == USART_WordLength_9b))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Stop_Bits 
+  * @{
+  */ 
+  
+#define USART_StopBits_1                     ((uint16_t)0x0000)
+#define USART_StopBits_0_5                   ((uint16_t)0x1000)
+#define USART_StopBits_2                     ((uint16_t)0x2000)
+#define USART_StopBits_1_5                   ((uint16_t)0x3000)
+#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \
+                                     ((STOPBITS) == USART_StopBits_0_5) || \
+                                     ((STOPBITS) == USART_StopBits_2) || \
+                                     ((STOPBITS) == USART_StopBits_1_5))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Parity 
+  * @{
+  */ 
+  
+#define USART_Parity_No                      ((uint16_t)0x0000)
+#define USART_Parity_Even                    ((uint16_t)0x0400)
+#define USART_Parity_Odd                     ((uint16_t)0x0600) 
+#define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \
+                                 ((PARITY) == USART_Parity_Even) || \
+                                 ((PARITY) == USART_Parity_Odd))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Mode 
+  * @{
+  */ 
+  
+#define USART_Mode_Rx                        ((uint16_t)0x0004)
+#define USART_Mode_Tx                        ((uint16_t)0x0008)
+#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Hardware_Flow_Control 
+  * @{
+  */ 
+#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
+#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
+#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
+#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
+#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\
+                              (((CONTROL) == USART_HardwareFlowControl_None) || \
+                               ((CONTROL) == USART_HardwareFlowControl_RTS) || \
+                               ((CONTROL) == USART_HardwareFlowControl_CTS) || \
+                               ((CONTROL) == USART_HardwareFlowControl_RTS_CTS))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Clock 
+  * @{
+  */ 
+#define USART_Clock_Disable                  ((uint16_t)0x0000)
+#define USART_Clock_Enable                   ((uint16_t)0x0800)
+#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) || \
+                               ((CLOCK) == USART_Clock_Enable))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Clock_Polarity 
+  * @{
+  */
+  
+#define USART_CPOL_Low                       ((uint16_t)0x0000)
+#define USART_CPOL_High                      ((uint16_t)0x0400)
+#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Clock_Phase
+  * @{
+  */
+
+#define USART_CPHA_1Edge                     ((uint16_t)0x0000)
+#define USART_CPHA_2Edge                     ((uint16_t)0x0200)
+#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge))
+
+/**
+  * @}
+  */
+
+/** @defgroup USART_Last_Bit
+  * @{
+  */
+
+#define USART_LastBit_Disable                ((uint16_t)0x0000)
+#define USART_LastBit_Enable                 ((uint16_t)0x0100)
+#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \
+                                   ((LASTBIT) == USART_LastBit_Enable))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Interrupt_definition 
+  * @{
+  */
+  
+#define USART_IT_PE                          ((uint16_t)0x0028)
+#define USART_IT_TXE                         ((uint16_t)0x0727)
+#define USART_IT_TC                          ((uint16_t)0x0626)
+#define USART_IT_RXNE                        ((uint16_t)0x0525)
+#define USART_IT_ORE_RX                      ((uint16_t)0x0325) /* In case interrupt is generated if the RXNEIE bit is set */
+#define USART_IT_IDLE                        ((uint16_t)0x0424)
+#define USART_IT_LBD                         ((uint16_t)0x0846)
+#define USART_IT_CTS                         ((uint16_t)0x096A)
+#define USART_IT_ERR                         ((uint16_t)0x0060)
+#define USART_IT_ORE_ER                      ((uint16_t)0x0360) /* In case interrupt is generated if the EIE bit is set */
+#define USART_IT_NE                          ((uint16_t)0x0260)
+#define USART_IT_FE                          ((uint16_t)0x0160)
+
+/** @defgroup USART_Legacy 
+  * @{
+  */
+#define USART_IT_ORE                          USART_IT_ORE_ER               
+/**
+  * @}
+  */
+
+#define IS_USART_CONFIG_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \
+                                ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \
+                                ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \
+                                ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ERR))
+#define IS_USART_GET_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \
+                             ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \
+                             ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \
+                             ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ORE) || \
+                             ((IT) == USART_IT_ORE_RX) || ((IT) == USART_IT_ORE_ER) || \
+                             ((IT) == USART_IT_NE) || ((IT) == USART_IT_FE))
+#define IS_USART_CLEAR_IT(IT) (((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \
+                               ((IT) == USART_IT_LBD) || ((IT) == USART_IT_CTS))
+/**
+  * @}
+  */
+
+/** @defgroup USART_DMA_Requests 
+  * @{
+  */
+
+#define USART_DMAReq_Tx                      ((uint16_t)0x0080)
+#define USART_DMAReq_Rx                      ((uint16_t)0x0040)
+#define IS_USART_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFF3F) == 0x00) && ((DMAREQ) != (uint16_t)0x00))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_WakeUp_methods
+  * @{
+  */
+
+#define USART_WakeUp_IdleLine                ((uint16_t)0x0000)
+#define USART_WakeUp_AddressMark             ((uint16_t)0x0800)
+#define IS_USART_WAKEUP(WAKEUP) (((WAKEUP) == USART_WakeUp_IdleLine) || \
+                                 ((WAKEUP) == USART_WakeUp_AddressMark))
+/**
+  * @}
+  */
+
+/** @defgroup USART_LIN_Break_Detection_Length 
+  * @{
+  */
+  
+#define USART_LINBreakDetectLength_10b      ((uint16_t)0x0000)
+#define USART_LINBreakDetectLength_11b      ((uint16_t)0x0020)
+#define IS_USART_LIN_BREAK_DETECT_LENGTH(LENGTH) \
+                               (((LENGTH) == USART_LINBreakDetectLength_10b) || \
+                                ((LENGTH) == USART_LINBreakDetectLength_11b))
+/**
+  * @}
+  */
+
+/** @defgroup USART_IrDA_Low_Power 
+  * @{
+  */
+
+#define USART_IrDAMode_LowPower              ((uint16_t)0x0004)
+#define USART_IrDAMode_Normal                ((uint16_t)0x0000)
+#define IS_USART_IRDA_MODE(MODE) (((MODE) == USART_IrDAMode_LowPower) || \
+                                  ((MODE) == USART_IrDAMode_Normal))
+/**
+  * @}
+  */ 
+
+/** @defgroup USART_Flags 
+  * @{
+  */
+
+#define USART_FLAG_CTS                       ((uint16_t)0x0200)
+#define USART_FLAG_LBD                       ((uint16_t)0x0100)
+#define USART_FLAG_TXE                       ((uint16_t)0x0080)
+#define USART_FLAG_TC                        ((uint16_t)0x0040)
+#define USART_FLAG_RXNE                      ((uint16_t)0x0020)
+#define USART_FLAG_IDLE                      ((uint16_t)0x0010)
+#define USART_FLAG_ORE                       ((uint16_t)0x0008)
+#define USART_FLAG_NE                        ((uint16_t)0x0004)
+#define USART_FLAG_FE                        ((uint16_t)0x0002)
+#define USART_FLAG_PE                        ((uint16_t)0x0001)
+#define IS_USART_FLAG(FLAG) (((FLAG) == USART_FLAG_PE) || ((FLAG) == USART_FLAG_TXE) || \
+                             ((FLAG) == USART_FLAG_TC) || ((FLAG) == USART_FLAG_RXNE) || \
+                             ((FLAG) == USART_FLAG_IDLE) || ((FLAG) == USART_FLAG_LBD) || \
+                             ((FLAG) == USART_FLAG_CTS) || ((FLAG) == USART_FLAG_ORE) || \
+                             ((FLAG) == USART_FLAG_NE) || ((FLAG) == USART_FLAG_FE))
+                              
+#define IS_USART_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFC9F) == 0x00) && ((FLAG) != (uint16_t)0x00))
+
+#define IS_USART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 7500001))
+#define IS_USART_ADDRESS(ADDRESS) ((ADDRESS) <= 0xF)
+#define IS_USART_DATA(DATA) ((DATA) <= 0x1FF)
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+/*  Function used to set the USART configuration to the default reset state ***/ 
+void USART_DeInit(USART_TypeDef* USARTx);
+
+/* Initialization and Configuration functions *********************************/
+void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
+void USART_StructInit(USART_InitTypeDef* USART_InitStruct);
+void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);
+void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);
+void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler);
+void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* Data transfers functions ***************************************************/ 
+void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
+uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
+
+/* Multi-Processor Communication functions ************************************/
+void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address);
+void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp);
+void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* LIN mode functions *********************************************************/
+void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength);
+void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SendBreak(USART_TypeDef* USARTx);
+
+/* Half-duplex mode function **************************************************/
+void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* Smartcard mode functions ***************************************************/
+void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime);
+
+/* IrDA mode functions ********************************************************/
+void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode);
+void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* DMA transfers management functions *****************************************/
+void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
+FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
+void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
+ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
+void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_USART_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 103 - 0
app/Libraries/inc/stm32f2xx_wwdg.h

@@ -0,0 +1,103 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_wwdg.h
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file contains all the functions prototypes for the WWDG firmware
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F2xx_WWDG_H
+#define __STM32F2xx_WWDG_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup WWDG
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup WWDG_Exported_Constants
+  * @{
+  */ 
+  
+/** @defgroup WWDG_Prescaler 
+  * @{
+  */
+  
+#define WWDG_Prescaler_1    ((uint32_t)0x00000000)
+#define WWDG_Prescaler_2    ((uint32_t)0x00000080)
+#define WWDG_Prescaler_4    ((uint32_t)0x00000100)
+#define WWDG_Prescaler_8    ((uint32_t)0x00000180)
+#define IS_WWDG_PRESCALER(PRESCALER) (((PRESCALER) == WWDG_Prescaler_1) || \
+                                      ((PRESCALER) == WWDG_Prescaler_2) || \
+                                      ((PRESCALER) == WWDG_Prescaler_4) || \
+                                      ((PRESCALER) == WWDG_Prescaler_8))
+#define IS_WWDG_WINDOW_VALUE(VALUE) ((VALUE) <= 0x7F)
+#define IS_WWDG_COUNTER(COUNTER) (((COUNTER) >= 0x40) && ((COUNTER) <= 0x7F))
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+  
+/*  Function used to set the WWDG configuration to the default reset state ****/  
+void WWDG_DeInit(void);
+
+/* Prescaler, Refresh window and Counter configuration functions **************/
+void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
+void WWDG_SetWindowValue(uint8_t WindowValue);
+void WWDG_EnableIT(void);
+void WWDG_SetCounter(uint8_t Counter);
+
+/* WWDG activation function ***************************************************/
+void WWDG_Enable(uint8_t Counter);
+
+/* Interrupts and flags management functions **********************************/
+FlagStatus WWDG_GetFlagStatus(void);
+void WWDG_ClearFlag(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F2xx_WWDG_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 241 - 0
app/Libraries/src/misc.c

@@ -0,0 +1,241 @@
+/**
+  ******************************************************************************
+  * @file    misc.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides all the miscellaneous firmware functions (add-on
+  *          to CMSIS functions).
+  *          
+  *  @verbatim   
+  *                               
+  *          ===================================================================      
+  *                        How to configure Interrupts using driver 
+  *          ===================================================================      
+  * 
+  *            This section provide functions allowing to configure the NVIC interrupts (IRQ).
+  *            The Cortex-M3 exceptions are managed by CMSIS functions.
+  *
+  *            1. Configure the NVIC Priority Grouping using NVIC_PriorityGroupConfig()
+  *                function according to the following table.
+ 
+  *  The table below gives the allowed values of the pre-emption priority and subpriority according
+  *  to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function
+  *    ==========================================================================================================================
+  *      NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  |       Description
+  *    ==========================================================================================================================
+  *     NVIC_PriorityGroup_0  |                0                  |            0-15             | 0 bits for pre-emption priority
+  *                           |                                   |                             | 4 bits for subpriority
+  *    --------------------------------------------------------------------------------------------------------------------------
+  *     NVIC_PriorityGroup_1  |                0-1                |            0-7              | 1 bits for pre-emption priority
+  *                           |                                   |                             | 3 bits for subpriority
+  *    --------------------------------------------------------------------------------------------------------------------------    
+  *     NVIC_PriorityGroup_2  |                0-3                |            0-3              | 2 bits for pre-emption priority
+  *                           |                                   |                             | 2 bits for subpriority
+  *    --------------------------------------------------------------------------------------------------------------------------    
+  *     NVIC_PriorityGroup_3  |                0-7                |            0-1              | 3 bits for pre-emption priority
+  *                           |                                   |                             | 1 bits for subpriority
+  *    --------------------------------------------------------------------------------------------------------------------------    
+  *     NVIC_PriorityGroup_4  |                0-15               |            0                | 4 bits for pre-emption priority
+  *                           |                                   |                             | 0 bits for subpriority                       
+  *    ==========================================================================================================================     
+  *
+  *            2. Enable and Configure the priority of the selected IRQ Channels using NVIC_Init()  
+  *
+  * @note  When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. 
+  *        The pending IRQ priority will be managed only by the subpriority.
+  *
+  * @note  IRQ priority order (sorted by highest to lowest priority):
+  *         - Lowest pre-emption priority
+  *         - Lowest subpriority
+  *         - Lowest hardware priority (IRQ number)
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "misc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup MISC 
+  * @brief MISC driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define AIRCR_VECTKEY_MASK    ((uint32_t)0x05FA0000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup MISC_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
+  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
+  *   This parameter can be one of the following values:
+  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
+  *                                4 bits for subpriority
+  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
+  *                                3 bits for subpriority
+  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
+  *                                2 bits for subpriority
+  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
+  *                                1 bits for subpriority
+  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
+  *                                0 bits for subpriority
+  * @note   When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. 
+  *         The pending IRQ priority will be managed only by the subpriority. 
+  * @retval None
+  */
+void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
+{
+  /* Check the parameters */
+  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
+  
+  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
+  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
+}
+
+/**
+  * @brief  Initializes the NVIC peripheral according to the specified
+  *         parameters in the NVIC_InitStruct.
+  * @note   To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
+  *         function should be called before. 
+  * @param  NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
+  *         the configuration information for the specified NVIC peripheral.
+  * @retval None
+  */
+void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
+{
+  uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
+  
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
+  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
+  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
+    
+  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
+  {
+    /* Compute the Corresponding IRQ Priority --------------------------------*/    
+    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
+    tmppre = (0x4 - tmppriority);
+    tmpsub = tmpsub >> tmppriority;
+
+    tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
+    tmppriority |=  (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub);
+        
+    tmppriority = tmppriority << 0x04;
+        
+    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
+    
+    /* Enable the Selected IRQ Channels --------------------------------------*/
+    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
+      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
+  }
+  else
+  {
+    /* Disable the Selected IRQ Channels -------------------------------------*/
+    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
+      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
+  }
+}
+
+/**
+  * @brief  Sets the vector table location and Offset.
+  * @param  NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory.
+  *   This parameter can be one of the following values:
+  *     @arg NVIC_VectTab_RAM: Vector Table in internal SRAM.
+  *     @arg NVIC_VectTab_FLASH: Vector Table in internal FLASH.
+  * @param  Offset: Vector Table base offset field. This value must be a multiple of 0x200.
+  * @retval None
+  */
+void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
+{ 
+  /* Check the parameters */
+  assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
+  assert_param(IS_NVIC_OFFSET(Offset));  
+   
+  SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
+}
+
+/**
+  * @brief  Selects the condition for the system to enter low power mode.
+  * @param  LowPowerMode: Specifies the new mode for the system to enter low power mode.
+  *   This parameter can be one of the following values:
+  *     @arg NVIC_LP_SEVONPEND: Low Power SEV on Pend.
+  *     @arg NVIC_LP_SLEEPDEEP: Low Power DEEPSLEEP request.
+  *     @arg NVIC_LP_SLEEPONEXIT: Low Power Sleep on Exit.
+  * @param  NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_NVIC_LP(LowPowerMode));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));  
+  
+  if (NewState != DISABLE)
+  {
+    SCB->SCR |= LowPowerMode;
+  }
+  else
+  {
+    SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode);
+  }
+}
+
+/**
+  * @brief  Configures the SysTick clock source.
+  * @param  SysTick_CLKSource: specifies the SysTick clock source.
+  *   This parameter can be one of the following values:
+  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
+  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
+  * @retval None
+  */
+void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
+{
+  /* Check the parameters */
+  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
+  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
+  {
+    SysTick->CTRL |= SysTick_CLKSource_HCLK;
+  }
+  else
+  {
+    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
+  }
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2709 - 0
app/Libraries/src/stm32f2x7_eth.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1740 - 0
app/Libraries/src/stm32f2xx_adc.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1696 - 0
app/Libraries/src/stm32f2xx_can.c


+ 125 - 0
app/Libraries/src/stm32f2xx_crc.c

@@ -0,0 +1,125 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_crc.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides all the CRC firmware functions.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_crc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup CRC 
+  * @brief CRC driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup CRC_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  Resets the CRC Data register (DR).
+  * @param  None
+  * @retval None
+  */
+void CRC_ResetDR(void)
+{
+  /* Reset CRC generator */
+  CRC->CR = CRC_CR_RESET;
+}
+
+/**
+  * @brief  Computes the 32-bit CRC of a given data word(32-bit).
+  * @param  Data: data word(32-bit) to compute its CRC
+  * @retval 32-bit CRC
+  */
+uint32_t CRC_CalcCRC(uint32_t Data)
+{
+  CRC->DR = Data;
+  
+  return (CRC->DR);
+}
+
+/**
+  * @brief  Computes the 32-bit CRC of a given buffer of data word(32-bit).
+  * @param  pBuffer: pointer to the buffer containing the data to be computed
+  * @param  BufferLength: length of the buffer to be computed					
+  * @retval 32-bit CRC
+  */
+uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength)
+{
+  uint32_t index = 0;
+  
+  for(index = 0; index < BufferLength; index++)
+  {
+    CRC->DR = pBuffer[index];
+  }
+  return (CRC->DR);
+}
+
+/**
+  * @brief  Returns the current CRC value.
+  * @param  None
+  * @retval 32-bit CRC
+  */
+uint32_t CRC_GetCRC(void)
+{
+  return (CRC->DR);
+}
+
+/**
+  * @brief  Stores a 8-bit data in the Independent Data(ID) register.
+  * @param  IDValue: 8-bit value to be stored in the ID register 					
+  * @retval None
+  */
+void CRC_SetIDRegister(uint8_t IDValue)
+{
+  CRC->IDR = IDValue;
+}
+
+/**
+  * @brief  Returns the 8-bit data stored in the Independent Data(ID) register
+  * @param  None
+  * @retval 8-bit value of the ID register 
+  */
+uint8_t CRC_GetIDRegister(void)
+{
+  return (CRC->IDR);
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 848 - 0
app/Libraries/src/stm32f2xx_cryp.c

@@ -0,0 +1,848 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_cryp.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the  Cryptographic processor (CRYP) peripheral:           
+  *           - Initialization and Configuration functions
+  *           - Data treatment functions 
+  *           - Context swapping functions     
+  *           - DMA interface function       
+  *           - Interrupts and flags management       
+  *
+  *  @verbatim
+  *                               
+  *          ===================================================================      
+  *                                 How to use this driver
+  *          =================================================================== 
+  *          1. Enable the CRYP controller clock using 
+  *              RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE); function.
+  *
+  *          2. Initialise the CRYP using CRYP_Init(), CRYP_KeyInit() and if 
+  *             needed CRYP_IVInit(). 
+  *
+  *          3. Flush the IN and OUT FIFOs by using CRYP_FIFOFlush() function.
+  *
+  *          4. Enable the CRYP controller using the CRYP_Cmd() function. 
+  *
+  *          5. If using DMA for Data input and output transfer, 
+  *             Activate the needed DMA Requests using CRYP_DMACmd() function 
+  
+  *          6. If DMA is not used for data transfer, use CRYP_DataIn() and 
+  *             CRYP_DataOut() functions to enter data to IN FIFO and get result
+  *             from OUT FIFO.
+  *
+  *          7. To control CRYP events you can use one of the following 
+  *              two methods:
+  *               - Check on CRYP flags using the CRYP_GetFlagStatus() function.  
+  *               - Use CRYP interrupts through the function CRYP_ITConfig() at 
+  *                 initialization phase and CRYP_GetITStatus() function into 
+  *                 interrupt routines in processing phase.
+  *       
+  *          8. Save and restore Cryptographic processor context using  
+  *             CRYP_SaveContext() and CRYP_RestoreContext() functions.     
+  *
+  *
+  *          ===================================================================  
+  *                Procedure to perform an encryption or a decryption
+  *          ===================================================================  
+  *
+  *      Initialization
+  *      ===============  
+  *     1. Initialize the peripheral using CRYP_Init(), CRYP_KeyInit() and 
+  *        CRYP_IVInit functions:
+  *        - Configure the key size (128-, 192- or 256-bit, in the AES only) 
+  *        - Enter the symmetric key 
+  *        - Configure the data type
+  *        - In case of decryption in AES-ECB or AES-CBC, you must prepare 
+  *          the key: configure the key preparation mode. Then Enable the CRYP 
+  *          peripheral using CRYP_Cmd() function: the BUSY flag is set. 
+  *          Wait until BUSY flag is reset : the key is prepared for decryption
+  *       - Configure the algorithm and chaining (the DES/TDES in ECB/CBC, the 
+  *          AES in ECB/CBC/CTR) 
+  *       - Configure the direction (encryption/decryption).
+  *       - Write the initialization vectors (in CBC or CTR modes only)
+  *
+  *    2. Flush the IN and OUT FIFOs using the CRYP_FIFOFlush() function
+  *
+  *
+  *    Basic Processing mode (polling mode) 
+  *    ====================================  
+  *    1. Enable the cryptographic processor using CRYP_Cmd() function.
+  *
+  *    2. Write the first blocks in the input FIFO (2 to 8 words) using 
+  *       CRYP_DataIn() function.
+  *
+  *    3. Repeat the following sequence until the complete message has been 
+  *       processed:
+  *
+  *       a) Wait for flag CRYP_FLAG_OFNE occurs (using CRYP_GetFlagStatus() 
+  *          function), then read the OUT-FIFO using CRYP_DataOut() function
+  *          (1 block or until the FIFO is empty)
+  *
+  *       b) Wait for flag CRYP_FLAG_IFNF occurs, (using CRYP_GetFlagStatus() 
+  *          function then write the IN FIFO using CRYP_DataIn() function 
+  *          (1 block or until the FIFO is full)
+  *
+  *    4. At the end of the processing, CRYP_FLAG_BUSY flag will be reset and 
+  *        both FIFOs are empty (CRYP_FLAG_IFEM is set and CRYP_FLAG_OFNE is 
+  *        reset). You can disable the peripheral using CRYP_Cmd() function.
+  *
+  *    Interrupts Processing mode 
+  *    ===========================
+  *    In this mode, Processing is done when the data are transferred by the 
+  *    CPU during interrupts.
+  *
+  *    1. Enable the interrupts CRYP_IT_INI and CRYP_IT_OUTI using 
+  *       CRYP_ITConfig() function.
+  *
+  *    2. Enable the cryptographic processor using CRYP_Cmd() function.
+  *
+  *    3. In the CRYP_IT_INI interrupt handler : load the input message into the 
+  *       IN FIFO using CRYP_DataIn() function . You can load 2 or 4 words at a 
+  *       time, or load data until the IN FIFO is full. When the last word of
+  *       the message has been entered into the IN FIFO, disable the CRYP_IT_INI 
+  *       interrupt (using CRYP_ITConfig() function).
+  *
+  *    4. In the CRYP_IT_OUTI interrupt handler : read the output message from 
+  *       the OUT FIFO using CRYP_DataOut() function. You can read 1 block (2 or 
+  *       4 words) at a time or read data until the FIFO is empty.
+  *       When the last word has been read, INIM=0, BUSY=0 and both FIFOs are 
+  *       empty (CRYP_FLAG_IFEM is set and CRYP_FLAG_OFNE is reset). 
+  *       You can disable the CRYP_IT_OUTI interrupt (using CRYP_ITConfig() 
+  *       function) and you can disable the peripheral using CRYP_Cmd() function.
+  *
+  *    DMA Processing mode 
+  *    ====================
+  *    In this mode, Processing is done when the DMA is used to transfer the 
+  *    data from/to the memory.
+  *
+  *    1. Configure the DMA controller to transfer the input data from the 
+  *       memory using DMA_Init() function. 
+  *       The transfer length is the length of the message. 
+  *       As message padding is not managed by the peripheral, the message 
+  *       length must be an entire number of blocks. The data are transferred 
+  *       in burst mode. The burst length is 4 words in the AES and 2 or 4 
+  *       words in the DES/TDES. The DMA should be configured to set an 
+  *       interrupt on transfer completion of the output data to indicate that 
+  *       the processing is finished. 
+  *       Refer to DMA peripheral driver for more details.  
+  *
+  *    2. Enable the cryptographic processor using CRYP_Cmd() function. 
+  *       Enable the DMA requests CRYP_DMAReq_DataIN and CRYP_DMAReq_DataOUT 
+  *       using CRYP_DMACmd() function.
+  *
+  *    3. All the transfers and processing are managed by the DMA and the 
+  *       cryptographic processor. The DMA transfer complete interrupt indicates 
+  *       that the processing is complete. Both FIFOs are normally empty and 
+  *       CRYP_FLAG_BUSY flag is reset.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_cryp.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup CRYP 
+  * @brief CRYP driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define FLAG_MASK     ((uint8_t)0x20)
+#define MAX_TIMEOUT   ((uint16_t)0xFFFF)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup CRYP_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup CRYP_Group1 Initialization and Configuration functions
+ *  @brief    Initialization and Configuration functions 
+ *
+@verbatim    
+ ===============================================================================
+                      Initialization and Configuration functions
+ ===============================================================================  
+  This section provides functions allowing to 
+   - Initialize the cryptographic Processor using CRYP_Init() function 
+      -  Encrypt or Decrypt 
+      -  mode : TDES-ECB, TDES-CBC, 
+                DES-ECB, DES-CBC, 
+                AES-ECB, AES-CBC, AES-CTR, AES-Key 
+      - DataType :  32-bit data, 16-bit data, bit data or bit-string
+      - Key Size (only in AES modes)
+   - Configure the Encrypt or Decrypt Key using CRYP_KeyInit() function 
+   - Configure the Initialization Vectors(IV) for CBC and CTR modes using 
+     CRYP_IVInit() function.  
+   - Flushes the IN and OUT FIFOs : using CRYP_FIFOFlush() function.                         
+   - Enable or disable the CRYP Processor using CRYP_Cmd() function 
+    
+   
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Deinitializes the CRYP peripheral registers to their default reset values
+  * @param  None
+  * @retval None
+  */
+void CRYP_DeInit(void)
+{
+  /* Enable CRYP reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_CRYP, ENABLE);
+
+  /* Release CRYP from reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_CRYP, DISABLE);
+}
+
+/**
+  * @brief  Initializes the CRYP peripheral according to the specified parameters
+  *         in the CRYP_InitStruct.
+  * @param  CRYP_InitStruct: pointer to a CRYP_InitTypeDef structure that contains
+  *         the configuration information for the CRYP peripheral.
+  * @retval None
+  */
+void CRYP_Init(CRYP_InitTypeDef* CRYP_InitStruct)
+{
+  /* Check the parameters */
+  assert_param(IS_CRYP_ALGOMODE(CRYP_InitStruct->CRYP_AlgoMode));
+  assert_param(IS_CRYP_DATATYPE(CRYP_InitStruct->CRYP_DataType));
+  assert_param(IS_CRYP_ALGODIR(CRYP_InitStruct->CRYP_AlgoDir));
+
+  /* Select Algorithm mode*/  
+  CRYP->CR &= ~CRYP_CR_ALGOMODE;
+  CRYP->CR |= CRYP_InitStruct->CRYP_AlgoMode;
+
+  /* Select dataType */ 
+  CRYP->CR &= ~CRYP_CR_DATATYPE;
+  CRYP->CR |= CRYP_InitStruct->CRYP_DataType;
+
+  /* select Key size (used only with AES algorithm) */
+  if ((CRYP_InitStruct->CRYP_AlgoMode == CRYP_AlgoMode_AES_ECB) ||
+      (CRYP_InitStruct->CRYP_AlgoMode == CRYP_AlgoMode_AES_CBC) ||
+      (CRYP_InitStruct->CRYP_AlgoMode == CRYP_AlgoMode_AES_CTR) ||
+      (CRYP_InitStruct->CRYP_AlgoMode == CRYP_AlgoMode_AES_Key))
+  {
+    assert_param(IS_CRYP_KEYSIZE(CRYP_InitStruct->CRYP_KeySize));
+    CRYP->CR &= ~CRYP_CR_KEYSIZE;
+    CRYP->CR |= CRYP_InitStruct->CRYP_KeySize; /* Key size and value must be 
+                                                  configured once the key has 
+                                                  been prepared */
+  }
+
+  /* Select data Direction */ 
+  CRYP->CR &= ~CRYP_CR_ALGODIR;
+  CRYP->CR |= CRYP_InitStruct->CRYP_AlgoDir;
+}
+
+/**
+  * @brief  Fills each CRYP_InitStruct member with its default value.
+  * @param  CRYP_InitStruct: pointer to a CRYP_InitTypeDef structure which will
+  *         be initialized.
+  * @retval None
+  */
+void CRYP_StructInit(CRYP_InitTypeDef* CRYP_InitStruct)
+{
+  /* Initialize the CRYP_AlgoDir member */
+  CRYP_InitStruct->CRYP_AlgoDir = CRYP_AlgoDir_Encrypt;
+
+  /* initialize the CRYP_AlgoMode member */
+  CRYP_InitStruct->CRYP_AlgoMode = CRYP_AlgoMode_TDES_ECB;
+
+  /* initialize the CRYP_DataType member */
+  CRYP_InitStruct->CRYP_DataType = CRYP_DataType_32b;
+  
+  /* Initialize the CRYP_KeySize member */
+  CRYP_InitStruct->CRYP_KeySize = CRYP_KeySize_128b;
+}
+
+/**
+  * @brief  Initializes the CRYP Keys according to the specified parameters in
+  *         the CRYP_KeyInitStruct.
+  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure that
+  *         contains the configuration information for the CRYP Keys.
+  * @retval None
+  */
+void CRYP_KeyInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
+{
+  /* Key Initialisation */
+  CRYP->K0LR = CRYP_KeyInitStruct->CRYP_Key0Left;
+  CRYP->K0RR = CRYP_KeyInitStruct->CRYP_Key0Right;
+  CRYP->K1LR = CRYP_KeyInitStruct->CRYP_Key1Left;
+  CRYP->K1RR = CRYP_KeyInitStruct->CRYP_Key1Right;
+  CRYP->K2LR = CRYP_KeyInitStruct->CRYP_Key2Left;
+  CRYP->K2RR = CRYP_KeyInitStruct->CRYP_Key2Right;
+  CRYP->K3LR = CRYP_KeyInitStruct->CRYP_Key3Left;
+  CRYP->K3RR = CRYP_KeyInitStruct->CRYP_Key3Right;
+}
+
+/**
+  * @brief  Fills each CRYP_KeyInitStruct member with its default value.
+  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure 
+  *         which will be initialized.
+  * @retval None
+  */
+void CRYP_KeyStructInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
+{
+  CRYP_KeyInitStruct->CRYP_Key0Left  = 0;
+  CRYP_KeyInitStruct->CRYP_Key0Right = 0;
+  CRYP_KeyInitStruct->CRYP_Key1Left  = 0;
+  CRYP_KeyInitStruct->CRYP_Key1Right = 0;
+  CRYP_KeyInitStruct->CRYP_Key2Left  = 0;
+  CRYP_KeyInitStruct->CRYP_Key2Right = 0;
+  CRYP_KeyInitStruct->CRYP_Key3Left  = 0;
+  CRYP_KeyInitStruct->CRYP_Key3Right = 0;
+}
+/**
+  * @brief  Initializes the CRYP Initialization Vectors(IV) according to the
+  *         specified parameters in the CRYP_IVInitStruct.
+  * @param  CRYP_IVInitStruct: pointer to a CRYP_IVInitTypeDef structure that contains
+  *         the configuration information for the CRYP Initialization Vectors(IV).
+  * @retval None
+  */
+void CRYP_IVInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct)
+{
+  CRYP->IV0LR = CRYP_IVInitStruct->CRYP_IV0Left;
+  CRYP->IV0RR = CRYP_IVInitStruct->CRYP_IV0Right;
+  CRYP->IV1LR = CRYP_IVInitStruct->CRYP_IV1Left;
+  CRYP->IV1RR = CRYP_IVInitStruct->CRYP_IV1Right;
+}
+
+/**
+  * @brief  Fills each CRYP_IVInitStruct member with its default value.
+  * @param  CRYP_IVInitStruct: pointer to a CRYP_IVInitTypeDef Initialization 
+  *         Vectors(IV) structure which will be initialized.
+  * @retval None
+  */
+void CRYP_IVStructInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct)
+{
+  CRYP_IVInitStruct->CRYP_IV0Left  = 0;
+  CRYP_IVInitStruct->CRYP_IV0Right = 0;
+  CRYP_IVInitStruct->CRYP_IV1Left  = 0;
+  CRYP_IVInitStruct->CRYP_IV1Right = 0;
+}
+
+/**
+  * @brief  Flushes the IN and OUT FIFOs (that is read and write pointers of the 
+  *         FIFOs are reset)
+  * @note   The FIFOs must be flushed only when BUSY flag is reset.  
+  * @param  None
+  * @retval None
+  */
+void CRYP_FIFOFlush(void)
+{
+  /* Reset the read and write pointers of the FIFOs */
+  CRYP->CR |= CRYP_CR_FFLUSH;
+}
+
+/**
+  * @brief  Enables or disables the CRYP peripheral.
+  * @param  NewState: new state of the CRYP peripheral.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void CRYP_Cmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the Cryptographic processor */
+    CRYP->CR |= CRYP_CR_CRYPEN;
+  }
+  else
+  {
+    /* Disable the Cryptographic processor */
+    CRYP->CR &= ~CRYP_CR_CRYPEN;
+  }
+}
+/**
+  * @}
+  */
+  
+/** @defgroup CRYP_Group2 CRYP Data processing functions
+ *  @brief    CRYP Data processing functions
+ *
+@verbatim    
+ ===============================================================================
+                      CRYP Data processing functions
+ ===============================================================================  
+  This section provides functions allowing the encryption and decryption 
+  operations: 
+  - Enter data to be treated in the IN FIFO : using CRYP_DataIn() function.
+  - Get the data result from the OUT FIFO : using CRYP_DataOut() function.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Writes data in the Data Input register (DIN).
+  * @note   After the DIN register has been read once or several times, 
+  *         the FIFO must be flushed (using CRYP_FIFOFlush() function).  
+  * @param  Data: data to write in Data Input register
+  * @retval None
+  */
+void CRYP_DataIn(uint32_t Data)
+{
+  CRYP->DR = Data;
+}
+
+/**
+  * @brief  Returns the last data entered into the output FIFO.
+  * @param  None
+  * @retval Last data entered into the output FIFO.
+  */
+uint32_t CRYP_DataOut(void)
+{
+  return CRYP->DOUT;
+}
+/**
+  * @}
+  */
+  
+/** @defgroup CRYP_Group3 Context swapping functions
+ *  @brief   Context swapping functions
+ *
+@verbatim   
+ ===============================================================================
+                             Context swapping functions
+ ===============================================================================  
+
+  This section provides functions allowing to save and store CRYP Context
+
+  It is possible to interrupt an encryption/ decryption/ key generation process 
+  to perform another processing with a higher priority, and to complete the 
+  interrupted process later on, when the higher-priority task is complete. To do 
+  so, the context of the interrupted task must be saved from the CRYP registers 
+  to memory, and then be restored from memory to the CRYP registers.
+   
+  1. To save the current context, use CRYP_SaveContext() function
+  2. To restore the saved context, use CRYP_RestoreContext() function 
+
+
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Saves the CRYP peripheral Context. 
+  * @note   This function stops DMA transfer before to save the context. After 
+  *         restoring the context, you have to enable the DMA again (if the DMA
+  *         was previously used).
+  * @param  CRYP_ContextSave: pointer to a CRYP_Context structure that contains
+  *         the repository for current context.
+  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure that 
+  *         contains the configuration information for the CRYP Keys.  
+  * @retval None
+  */
+ErrorStatus CRYP_SaveContext(CRYP_Context* CRYP_ContextSave,
+                             CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
+{
+  __IO uint32_t timeout = 0;
+  uint32_t ckeckmask = 0, bitstatus;    
+  ErrorStatus status = ERROR;
+
+  /* Stop DMA transfers on the IN FIFO by clearing the DIEN bit in the CRYP_DMACR */
+  CRYP->DMACR &= ~(uint32_t)CRYP_DMACR_DIEN;
+    
+  /* Wait until both the IN and OUT FIFOs are empty  
+    (IFEM=1 and OFNE=0 in the CRYP_SR register) and the 
+     BUSY bit is cleared. */
+
+  if ((CRYP->CR & (uint32_t)(CRYP_CR_ALGOMODE_TDES_ECB | CRYP_CR_ALGOMODE_TDES_CBC)) != (uint32_t)0 )/* TDES */
+  { 
+    ckeckmask =  CRYP_SR_IFEM | CRYP_SR_BUSY ;
+  }
+  else /* AES or DES */
+  {
+    ckeckmask =  CRYP_SR_IFEM | CRYP_SR_BUSY | CRYP_SR_OFNE;
+  }           
+   
+  do 
+  {
+    bitstatus = CRYP->SR & ckeckmask;
+    timeout++;
+  }
+  while ((timeout != MAX_TIMEOUT) && (bitstatus != CRYP_SR_IFEM));
+     
+  if ((CRYP->SR & ckeckmask) != CRYP_SR_IFEM)
+  {
+    status = ERROR;
+  }
+  else
+  {      
+    /* Stop DMA transfers on the OUT FIFO by 
+       - writing the DOEN bit to 0 in the CRYP_DMACR register 
+       - and clear the CRYPEN bit. */
+
+    CRYP->DMACR &= ~(uint32_t)CRYP_DMACR_DOEN;
+    CRYP->CR &= ~(uint32_t)CRYP_CR_CRYPEN;
+
+    /* Save the current configuration (bits [9:2] in the CRYP_CR register) */
+    CRYP_ContextSave->CR_bits9to2  = CRYP->CR & (CRYP_CR_KEYSIZE  | 
+                                                 CRYP_CR_DATATYPE | 
+                                                 CRYP_CR_ALGOMODE |
+                                                 CRYP_CR_ALGODIR); 
+
+    /* and, if not in ECB mode, the initialization vectors. */
+    CRYP_ContextSave->CRYP_IV0LR = CRYP->IV0LR;
+    CRYP_ContextSave->CRYP_IV0RR = CRYP->IV0RR;
+    CRYP_ContextSave->CRYP_IV1LR = CRYP->IV1LR;
+    CRYP_ContextSave->CRYP_IV1RR = CRYP->IV1RR;
+
+    /* save The key value */
+    CRYP_ContextSave->CRYP_K0LR = CRYP_KeyInitStruct->CRYP_Key0Left; 
+    CRYP_ContextSave->CRYP_K0RR = CRYP_KeyInitStruct->CRYP_Key0Right; 
+    CRYP_ContextSave->CRYP_K1LR = CRYP_KeyInitStruct->CRYP_Key1Left; 
+    CRYP_ContextSave->CRYP_K1RR = CRYP_KeyInitStruct->CRYP_Key1Right; 
+    CRYP_ContextSave->CRYP_K2LR = CRYP_KeyInitStruct->CRYP_Key2Left; 
+    CRYP_ContextSave->CRYP_K2RR = CRYP_KeyInitStruct->CRYP_Key2Right; 
+    CRYP_ContextSave->CRYP_K3LR = CRYP_KeyInitStruct->CRYP_Key3Left; 
+    CRYP_ContextSave->CRYP_K3RR = CRYP_KeyInitStruct->CRYP_Key3Right; 
+
+   /* When needed, save the DMA status (pointers for IN and OUT messages, 
+      number of remaining bytes, etc.) */
+     
+    status = SUCCESS;
+  }
+
+   return status;
+}
+
+/**
+  * @brief  Restores the CRYP peripheral Context.
+  * @note   Since teh DMA transfer is stopped in CRYP_SaveContext() function,
+  *         after restoring the context, you have to enable the DMA again (if the
+  *         DMA was previously used).  
+  * @param  CRYP_ContextRestore: pointer to a CRYP_Context structure that contains
+  *         the repository for saved context.
+  * @note   The data that were saved during context saving must be rewrited into
+  *         the IN FIFO.
+  * @retval None
+  */
+void CRYP_RestoreContext(CRYP_Context* CRYP_ContextRestore)  
+{
+
+  /* Configure the processor with the saved configuration */
+  CRYP->CR = CRYP_ContextRestore->CR_bits9to2;
+
+  /* restore The key value */
+  CRYP->K0LR = CRYP_ContextRestore->CRYP_K0LR; 
+  CRYP->K0RR = CRYP_ContextRestore->CRYP_K0RR;
+  CRYP->K1LR = CRYP_ContextRestore->CRYP_K1LR;
+  CRYP->K1RR = CRYP_ContextRestore->CRYP_K1RR;
+  CRYP->K2LR = CRYP_ContextRestore->CRYP_K2LR;
+  CRYP->K2RR = CRYP_ContextRestore->CRYP_K2RR;
+  CRYP->K3LR = CRYP_ContextRestore->CRYP_K3LR;
+  CRYP->K3RR = CRYP_ContextRestore->CRYP_K3RR;
+
+  /* and the initialization vectors. */
+  CRYP->IV0LR = CRYP_ContextRestore->CRYP_IV0LR;
+  CRYP->IV0RR = CRYP_ContextRestore->CRYP_IV0RR;
+  CRYP->IV1LR = CRYP_ContextRestore->CRYP_IV1LR;
+  CRYP->IV1RR = CRYP_ContextRestore->CRYP_IV1RR;
+
+  /* Enable the cryptographic processor */
+  CRYP->CR |= CRYP_CR_CRYPEN;
+}
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_Group4 CRYP's DMA interface Configuration function
+ *  @brief   CRYP's DMA interface Configuration function 
+ *
+@verbatim   
+ ===============================================================================
+                   CRYP's DMA interface Configuration function
+ ===============================================================================  
+
+  This section provides functions allowing to configure the DMA interface for 
+  CRYP data input and output transfer.
+   
+  When the DMA mode is enabled (using the CRYP_DMACmd() function), data can be 
+  transferred:
+  - From memory to the CRYP IN FIFO using the DMA peripheral by enabling 
+    the CRYP_DMAReq_DataIN request.
+  - From the CRYP OUT FIFO to the memory using the DMA peripheral by enabling 
+    the CRYP_DMAReq_DataOUT request.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the CRYP DMA interface.
+  * @param  CRYP_DMAReq: specifies the CRYP DMA transfer request to be enabled or disabled.
+  *           This parameter can be any combination of the following values:
+  *            @arg CRYP_DMAReq_DataOUT: DMA for outgoing(Tx) data transfer
+  *            @arg CRYP_DMAReq_DataIN: DMA for incoming(Rx) data transfer
+  * @param  NewState: new state of the selected CRYP DMA transfer request.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void CRYP_DMACmd(uint8_t CRYP_DMAReq, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_CRYP_DMAREQ(CRYP_DMAReq));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected CRYP DMA request */
+    CRYP->DMACR |= CRYP_DMAReq;
+  }
+  else
+  {
+    /* Disable the selected CRYP DMA request */
+    CRYP->DMACR &= (uint8_t)~CRYP_DMAReq;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup CRYP_Group5 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                   Interrupts and flags management functions
+ ===============================================================================  
+
+  This section provides functions allowing to configure the CRYP Interrupts and 
+  to get the status and Interrupts pending bits.
+
+  The CRYP provides 2 Interrupts sources and 7 Flags:
+
+  Flags :
+  ------- 
+                          
+     1. CRYP_FLAG_IFEM :  Set when Input FIFO is empty.
+                          This Flag is cleared only by hardware.
+      
+     2. CRYP_FLAG_IFNF :  Set when Input FIFO is not full.
+                          This Flag is cleared only by hardware.
+
+
+     3. CRYP_FLAG_INRIS  : Set when Input FIFO Raw interrupt is pending 
+                           it gives the raw interrupt state prior to masking 
+                           of the input FIFO service interrupt.
+                           This Flag is cleared only by hardware.
+     
+     4. CRYP_FLAG_OFNE   : Set when Output FIFO not empty.
+                           This Flag is cleared only by hardware.
+        
+     5. CRYP_FLAG_OFFU   : Set when Output FIFO is full.
+                           This Flag is cleared only by hardware.
+                           
+     6. CRYP_FLAG_OUTRIS : Set when Output FIFO Raw interrupt is pending 
+                           it gives the raw interrupt state prior to masking 
+                           of the output FIFO service interrupt.
+                           This Flag is cleared only by hardware.
+                               
+     7. CRYP_FLAG_BUSY   : Set when the CRYP core is currently processing a 
+                           block of data or a key preparation (for AES 
+                           decryption).
+                           This Flag is cleared only by hardware.
+                           To clear it, the CRYP core must be disabled and the 
+                           last processing has completed. 
+
+  Interrupts :
+  ------------
+
+   1. CRYP_IT_INI   : The input FIFO service interrupt is asserted when there 
+                      are less than 4 words in the input FIFO.
+                      This interrupt is associated to CRYP_FLAG_INRIS flag.
+
+                @note This interrupt is cleared by performing write operations 
+                      to the input FIFO until it holds 4 or more words. The 
+                      input FIFO service interrupt INMIS is enabled with the 
+                      CRYP enable bit. Consequently, when CRYP is disabled, the 
+                      INMIS signal is low even if the input FIFO is empty.
+
+
+
+   2. CRYP_IT_OUTI  : The output FIFO service interrupt is asserted when there 
+                      is one or more (32-bit word) data items in the output FIFO.
+                      This interrupt is associated to CRYP_FLAG_OUTRIS flag.
+
+                @note This interrupt is cleared by reading data from the output 
+                      FIFO until there is no valid (32-bit) word left (that is, 
+                      the interrupt follows the state of the OFNE (output FIFO 
+                      not empty) flag).
+
+
+  Managing the CRYP controller events :
+  ------------------------------------ 
+  The user should identify which mode will be used in his application to manage 
+  the CRYP controller events: Polling mode or Interrupt mode.
+
+  1.  In the Polling Mode it is advised to use the following functions:
+      - CRYP_GetFlagStatus() : to check if flags events occur. 
+
+  @note  The CRYPT flags do not need to be cleared since they are cleared as 
+         soon as the associated event are reset.   
+
+
+  2.  In the Interrupt Mode it is advised to use the following functions:
+      - CRYP_ITConfig()       : to enable or disable the interrupt source.
+      - CRYP_GetITStatus()    : to check if Interrupt occurs.
+
+  @note  The CRYPT interrupts have no pending bits, the interrupt is cleared as 
+         soon as the associated event is reset. 
+
+@endverbatim
+  * @{
+  */ 
+
+/**
+  * @brief  Enables or disables the specified CRYP interrupts.
+  * @param  CRYP_IT: specifies the CRYP interrupt source to be enabled or disabled.
+  *          This parameter can be any combination of the following values:
+  *            @arg CRYP_IT_INI: Input FIFO interrupt
+  *            @arg CRYP_IT_OUTI: Output FIFO interrupt
+  * @param  NewState: new state of the specified CRYP interrupt.
+  *           This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void CRYP_ITConfig(uint8_t CRYP_IT, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_CRYP_CONFIG_IT(CRYP_IT));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected CRYP interrupt */
+    CRYP->IMSCR |= CRYP_IT;
+  }
+  else
+  {
+    /* Disable the selected CRYP interrupt */
+    CRYP->IMSCR &= (uint8_t)~CRYP_IT;
+  }
+}
+
+/**
+  * @brief  Checks whether the specified CRYP interrupt has occurred or not.
+  * @note   This function checks the status of the masked interrupt (i.e the 
+  *         interrupt should be previously enabled).     
+  * @param  CRYP_IT: specifies the CRYP (masked) interrupt source to check.
+  *           This parameter can be one of the following values:
+  *            @arg CRYP_IT_INI: Input FIFO interrupt
+  *            @arg CRYP_IT_OUTI: Output FIFO interrupt
+  * @retval The new state of CRYP_IT (SET or RESET).
+  */
+ITStatus CRYP_GetITStatus(uint8_t CRYP_IT)
+{
+  ITStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_CRYP_GET_IT(CRYP_IT));
+
+  /* Check the status of the specified CRYP interrupt */
+  if ((CRYP->MISR &  CRYP_IT) != (uint8_t)RESET)
+  {
+    /* CRYP_IT is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* CRYP_IT is reset */
+    bitstatus = RESET;
+  }
+  /* Return the CRYP_IT status */
+  return bitstatus;
+}
+
+/**
+  * @brief  Checks whether the specified CRYP flag is set or not.
+  * @param  CRYP_FLAG: specifies the CRYP flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg CRYP_FLAG_IFEM: Input FIFO Empty flag.
+  *            @arg CRYP_FLAG_IFNF: Input FIFO Not Full flag.
+  *            @arg CRYP_FLAG_OFNE: Output FIFO Not Empty flag.
+  *            @arg CRYP_FLAG_OFFU: Output FIFO Full flag.
+  *            @arg CRYP_FLAG_BUSY: Busy flag.
+  *            @arg CRYP_FLAG_OUTRIS: Output FIFO raw interrupt flag.
+  *            @arg CRYP_FLAG_INRIS: Input FIFO raw interrupt flag.
+  * @retval The new state of CRYP_FLAG (SET or RESET).
+  */
+FlagStatus CRYP_GetFlagStatus(uint8_t CRYP_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  uint32_t tempreg = 0;
+
+  /* Check the parameters */
+  assert_param(IS_CRYP_GET_FLAG(CRYP_FLAG));
+
+  /* check if the FLAG is in RISR register */
+  if ((CRYP_FLAG & FLAG_MASK) != 0x00) 
+  {
+    tempreg = CRYP->RISR;
+  }
+  else  /* The FLAG is in SR register */
+  {
+    tempreg = CRYP->SR;
+  }
+
+
+  /* Check the status of the specified CRYP flag */
+  if ((tempreg & CRYP_FLAG ) != (uint8_t)RESET)
+  {
+    /* CRYP_FLAG is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* CRYP_FLAG is reset */
+    bitstatus = RESET;
+  }
+
+  /* Return the CRYP_FLAG status */
+  return  bitstatus;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 636 - 0
app/Libraries/src/stm32f2xx_cryp_aes.c

@@ -0,0 +1,636 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_cryp_aes.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides high level functions to encrypt and decrypt an 
+  *          input message using AES in ECB/CBC/CTR modes.
+  *          It uses the stm32f2xx_cryp.c/.h drivers to access the STM32F2xx CRYP
+  *          peripheral.
+  *
+  *  @verbatim
+  *
+  *          ===================================================================
+  *                                   How to use this driver
+  *          ===================================================================
+  *          1. Enable The CRYP controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE); function.
+  *
+  *          2. Encrypt and decrypt using AES in ECB Mode using CRYP_AES_ECB()
+  *             function.
+  *
+  *          3. Encrypt and decrypt using AES in CBC Mode using CRYP_AES_CBC()
+  *             function.
+  *
+  *          4. Encrypt and decrypt using AES in CTR Mode using CRYP_AES_CTR()
+  *             function.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_cryp.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup CRYP 
+  * @brief CRYP driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define AESBUSY_TIMEOUT    ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup CRYP_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup CRYP_Group6 High Level AES functions
+ *  @brief   High Level AES functions 
+ *
+@verbatim   
+ ===============================================================================
+                          High Level AES functions
+ ===============================================================================
+
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Encrypt and decrypt using AES in ECB Mode
+  * @param  Mode: encryption or decryption Mode.
+  *          This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  Key: Key used for AES algorithm.
+  * @param  Keysize: length of the Key, must be a 128, 192 or 256.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 16.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_AES_ECB(uint8_t Mode, uint8_t* Key, uint16_t Keysize,
+                         uint8_t* Input, uint32_t Ilength, uint8_t* Output)
+{
+  CRYP_InitTypeDef AES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
+
+  switch(Keysize)
+  {
+    case 128:
+    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 192:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 256:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    default:
+    break;
+  }
+
+  /*------------------ AES Decryption ------------------*/
+  if(Mode == MODE_DECRYPT) /* AES decryption */
+  {
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+
+    /* Crypto Init for Key preparation for decryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b;
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+    /* wait until the Busy flag is RESET */
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != AESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+      /* Crypto Init for decryption process */  
+      AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    }
+  }
+  /*------------------ AES Encryption ------------------*/
+  else /* AES encryption */
+  {
+
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Crypto Init for Encryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+  }
+
+  AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
+  AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&AES_CRYP_InitStructure);
+
+  /* Flush IN/OUT FIFOs */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=16)
+  {
+
+    /* Write the Input block in the IN FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != AESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut(); 
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status; 
+}
+
+/**
+  * @brief  Encrypt and decrypt using AES in CBC Mode
+  * @param  Mode: encryption or decryption Mode.
+  *          This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  InitVectors: Initialisation Vectors used for AES algorithm.
+  * @param  Key: Key used for AES algorithm.
+  * @param  Keysize: length of the Key, must be a 128, 192 or 256.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 16.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_AES_CBC(uint8_t Mode, uint8_t InitVectors[16], uint8_t *Key,
+                         uint16_t Keysize, uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output)
+{
+  CRYP_InitTypeDef AES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
+  CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t ivaddr     = (uint32_t)InitVectors;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
+
+  switch(Keysize)
+  {
+    case 128:
+    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 192:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 256:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    default:
+    break;
+  }
+
+  /* CRYP Initialization Vectors */
+  AES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV1Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV1Right= __REV(*(uint32_t*)(ivaddr));
+
+
+  /*------------------ AES Decryption ------------------*/
+  if(Mode == MODE_DECRYPT) /* AES decryption */
+  {
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+
+    /* Crypto Init for Key preparation for decryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b;
+
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+    /* wait until the Busy flag is RESET */
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != AESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+      /* Crypto Init for decryption process */  
+      AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    }
+  }
+  /*------------------ AES Encryption ------------------*/
+  else /* AES encryption */
+  {
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Crypto Init for Encryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+  }
+  AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
+  AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&AES_CRYP_InitStructure);
+
+  /* CRYP Initialization Vectors */
+  CRYP_IVInit(&AES_CRYP_IVInitStructure);
+
+  /* Flush IN/OUT FIFOs */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=16)
+  {
+
+    /* Write the Input block in the IN FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != AESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status;
+}
+
+/**
+  * @brief  Encrypt and decrypt using AES in CTR Mode
+  * @param  Mode: encryption or decryption Mode.
+  *           This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  InitVectors: Initialisation Vectors used for AES algorithm.
+  * @param  Key: Key used for AES algorithm.
+  * @param  Keysize: length of the Key, must be a 128, 192 or 256.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 16.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_AES_CTR(uint8_t Mode, uint8_t InitVectors[16], uint8_t *Key, 
+                         uint16_t Keysize, uint8_t *Input, uint32_t Ilength,
+                         uint8_t *Output)
+{
+  CRYP_InitTypeDef AES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
+  CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t ivaddr     = (uint32_t)InitVectors;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
+
+  switch(Keysize)
+  {
+    case 128:
+    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 192:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    case 256:
+    AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+    keyaddr+=4;
+    AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+    break;
+    default:
+    break;
+  }
+  /* CRYP Initialization Vectors */
+  AES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV1Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  AES_CRYP_IVInitStructure.CRYP_IV1Right= __REV(*(uint32_t*)(ivaddr));
+
+  /* Key Initialisation */
+  CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+  /*------------------ AES Decryption ------------------*/
+  if(Mode == MODE_DECRYPT) /* AES decryption */
+  {
+    /* Crypto Init for decryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+  }
+  /*------------------ AES Encryption ------------------*/
+  else /* AES encryption */
+  {
+    /* Crypto Init for Encryption process */
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt;
+  }
+  AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR;
+  AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&AES_CRYP_InitStructure);
+
+  /* CRYP Initialization Vectors */
+  CRYP_IVInit(&AES_CRYP_IVInitStructure);
+
+  /* Flush IN/OUT FIFOs */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=16)
+  {
+
+    /* Write the Input block in the IN FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != AESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status;
+}
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+

+ 289 - 0
app/Libraries/src/stm32f2xx_cryp_des.c

@@ -0,0 +1,289 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_cryp_des.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides high level functions to encrypt and decrypt an 
+  *          input message using DES in ECB/CBC modes.
+  *          It uses the stm32f2xx_cryp.c/.h drivers to access the STM32F2xx CRYP
+  *          peripheral.
+  *
+  *  @verbatim
+  *
+  *          ===================================================================
+  *                                   How to use this driver
+  *          ===================================================================
+  *          1. Enable The CRYP controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE); function.
+  *
+  *          2. Encrypt and decrypt using DES in ECB Mode using CRYP_DES_ECB()
+  *             function.
+  *
+  *          3. Encrypt and decrypt using DES in CBC Mode using CRYP_DES_CBC()
+  *             function.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_cryp.h"
+
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup CRYP 
+  * @brief CRYP driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define DESBUSY_TIMEOUT    ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+
+/** @defgroup CRYP_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup CRYP_Group8 High Level DES functions
+ *  @brief   High Level DES functions 
+ *
+@verbatim   
+ ===============================================================================
+                          High Level DES functions
+ ===============================================================================
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Encrypt and decrypt using DES in ECB Mode
+  * @param  Mode: encryption or decryption Mode.
+  *           This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  Key: Key used for DES algorithm.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 8.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_DES_ECB(uint8_t Mode, uint8_t Key[8], uint8_t *Input, 
+                         uint32_t Ilength, uint8_t *Output)
+{
+  CRYP_InitTypeDef DES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure);
+
+  /* Crypto Init for Encryption process */
+  if( Mode == MODE_ENCRYPT ) /* DES encryption */
+  {
+     DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+  }
+  else/* if( Mode == MODE_DECRYPT )*/ /* DES decryption */
+  {      
+     DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+  }
+
+  DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_ECB;
+  DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&DES_CRYP_InitStructure);
+
+  /* Key Initialisation */
+  DES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  DES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+  CRYP_KeyInit(& DES_CRYP_KeyInitStructure);
+
+  /* Flush IN/OUT FIFO */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=8)
+  {
+
+    /* Write the Input block in the Input FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+
+/* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != DESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status; 
+}
+
+/**
+  * @brief  Encrypt and decrypt using DES in CBC Mode
+  * @param  Mode: encryption or decryption Mode.
+  *          This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  Key: Key used for DES algorithm.
+  * @param  InitVectors: Initialisation Vectors used for DES algorithm.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 8.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_DES_CBC(uint8_t Mode, uint8_t Key[8], uint8_t InitVectors[8],
+                         uint8_t *Input, uint32_t Ilength, uint8_t *Output)
+{
+  CRYP_InitTypeDef DES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure;
+  CRYP_IVInitTypeDef DES_CRYP_IVInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t ivaddr     = (uint32_t)InitVectors;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure);
+
+  /* Crypto Init for Encryption process */
+  if(Mode == MODE_ENCRYPT) /* DES encryption */
+  {
+     DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+  }
+  else /*if(Mode == MODE_DECRYPT)*/ /* DES decryption */
+  {
+     DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+  }
+
+  DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_CBC;
+  DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&DES_CRYP_InitStructure);
+
+  /* Key Initialisation */
+  DES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  DES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+  CRYP_KeyInit(& DES_CRYP_KeyInitStructure);
+
+  /* Initialization Vectors */
+  DES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  DES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)(ivaddr));
+  CRYP_IVInit(&DES_CRYP_IVInitStructure);
+
+  /* Flush IN/OUT FIFO */
+  CRYP_FIFOFlush();
+  
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=8)
+  {
+    /* Write the Input block in the Input FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != DESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status; 
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 306 - 0
app/Libraries/src/stm32f2xx_cryp_tdes.c

@@ -0,0 +1,306 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_cryp_tdes.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides high level functions to encrypt and decrypt an 
+  *          input message using TDES in ECB/CBC modes .
+  *          It uses the stm32f2xx_cryp.c/.h drivers to access the STM32F2xx CRYP
+  *          peripheral.
+  *
+  *  @verbatim
+  *
+  *          ===================================================================
+  *                                   How to use this driver
+  *          ===================================================================
+  *          1. Enable The CRYP controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE); function.
+  *
+  *          2. Encrypt and decrypt using TDES in ECB Mode using CRYP_TDES_ECB()
+  *             function.
+  *
+  *          3. Encrypt and decrypt using TDES in CBC Mode using CRYP_TDES_CBC()
+  *             function.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_cryp.h"
+
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup CRYP 
+  * @brief CRYP driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define TDESBUSY_TIMEOUT    ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+
+/** @defgroup CRYP_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup CRYP_Group7 High Level TDES functions
+ *  @brief   High Level TDES functions 
+ *
+@verbatim   
+ ===============================================================================
+                          High Level TDES functions
+ ===============================================================================
+
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Encrypt and decrypt using TDES in ECB Mode
+  * @param  Mode: encryption or decryption Mode.
+  *           This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  Key: Key used for TDES algorithm.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 8.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_TDES_ECB(uint8_t Mode, uint8_t Key[24], uint8_t *Input, 
+                          uint32_t Ilength, uint8_t *Output)
+{
+  CRYP_InitTypeDef TDES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef TDES_CRYP_KeyInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&TDES_CRYP_KeyInitStructure);
+
+  /* Crypto Init for Encryption process */
+  if(Mode == MODE_ENCRYPT) /* TDES encryption */
+  {
+     TDES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt;
+  }
+  else /*if(Mode == MODE_DECRYPT)*/ /* TDES decryption */
+  {
+     TDES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+  }
+
+  TDES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_ECB;
+  TDES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+  CRYP_Init(&TDES_CRYP_InitStructure);
+
+  /* Key Initialisation */
+  TDES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+  CRYP_KeyInit(& TDES_CRYP_KeyInitStructure);
+
+  /* Flush IN/OUT FIFO */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=8)
+  {
+    /* Write the Input block in the Input FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != TDESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+    {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status; 
+}
+
+/**
+  * @brief  Encrypt and decrypt using TDES in CBC Mode
+  * @param  Mode: encryption or decryption Mode.
+  *           This parameter can be one of the following values:
+  *            @arg MODE_ENCRYPT: Encryption
+  *            @arg MODE_DECRYPT: Decryption
+  * @param  Key: Key used for TDES algorithm.
+  * @param  InitVectors: Initialisation Vectors used for TDES algorithm.
+  * @param  Input: pointer to the Input buffer.
+  * @param  Ilength: length of the Input buffer, must be a multiple of 8.
+  * @param  Output: pointer to the returned buffer.
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: Operation done
+  *          - ERROR: Operation failed
+  */
+ErrorStatus CRYP_TDES_CBC(uint8_t Mode, uint8_t Key[24], uint8_t InitVectors[8],
+                          uint8_t *Input, uint32_t Ilength, uint8_t *Output)
+{
+  CRYP_InitTypeDef TDES_CRYP_InitStructure;
+  CRYP_KeyInitTypeDef TDES_CRYP_KeyInitStructure;
+  CRYP_IVInitTypeDef TDES_CRYP_IVInitStructure;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+  uint32_t ivaddr     = (uint32_t)InitVectors;
+  uint32_t i = 0;
+
+  /* Crypto structures initialisation*/
+  CRYP_KeyStructInit(&TDES_CRYP_KeyInitStructure);
+
+  /* Crypto Init for Encryption process */
+  if(Mode == MODE_ENCRYPT) /* TDES encryption */
+  {
+    TDES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt;
+  }
+  else
+  {
+    TDES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+  }
+  TDES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC;
+  TDES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+
+  CRYP_Init(&TDES_CRYP_InitStructure);
+
+  /* Key Initialisation */
+  TDES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)(keyaddr));
+  keyaddr+=4;
+  TDES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)(keyaddr));
+  CRYP_KeyInit(& TDES_CRYP_KeyInitStructure);
+
+  /* Initialization Vectors */
+  TDES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)(ivaddr));
+  ivaddr+=4;
+  TDES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)(ivaddr));
+  CRYP_IVInit(&TDES_CRYP_IVInitStructure);
+
+  /* Flush IN/OUT FIFO */
+  CRYP_FIFOFlush();
+
+  /* Enable Crypto processor */
+  CRYP_Cmd(ENABLE);
+
+  for(i=0; ((i<Ilength) && (status != ERROR)); i+=8)
+  {
+    /* Write the Input block in the Input FIFO */
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+    CRYP_DataIn(*(uint32_t*)(inputaddr));
+    inputaddr+=4;
+
+    /* Wait until the complete message has been processed */
+    counter = 0;
+    do
+    {
+      busystatus = CRYP_GetFlagStatus(CRYP_FLAG_BUSY);
+      counter++;
+    }while ((counter != TDESBUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+   {
+       status = ERROR;
+    }
+    else
+    {
+
+      /* Read the Output block from the Output FIFO */
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+      *(uint32_t*)(outputaddr) = CRYP_DataOut();
+      outputaddr+=4;
+    }
+  }
+
+  /* Disable Crypto */
+  CRYP_Cmd(DISABLE);
+
+  return status; 
+}
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 699 - 0
app/Libraries/src/stm32f2xx_dac.c

@@ -0,0 +1,699 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dac.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+   * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the Digital-to-Analog Converter (DAC) peripheral: 
+  *           - DAC channels configuration: trigger, output buffer, data format
+  *           - DMA management      
+  *           - Interrupts and flags management
+  *
+  *  @verbatim
+  *    
+  *          ===================================================================
+  *                             DAC Peripheral features
+  *          ===================================================================
+  *          
+  *          DAC Channels
+  *          =============  
+  *          The device integrates two 12-bit Digital Analog Converters that can 
+  *          be used independently or simultaneously (dual mode):
+  *            1- DAC channel1 with DAC_OUT1 (PA4) as output
+  *            1- DAC channel2 with DAC_OUT2 (PA5) as output
+  *
+  *          DAC Triggers
+  *          =============
+  *          Digital to Analog conversion can be non-triggered using DAC_Trigger_None
+  *          and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register 
+  *          using DAC_SetChannel1Data() / DAC_SetChannel2Data() functions.
+  *   
+  *         Digital to Analog conversion can be triggered by:
+  *             1- External event: EXTI Line 9 (any GPIOx_Pin9) using DAC_Trigger_Ext_IT9.
+  *                The used pin (GPIOx_Pin9) must be configured in input mode.
+  *
+  *             2- Timers TRGO: TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8 
+  *                (DAC_Trigger_T2_TRGO, DAC_Trigger_T4_TRGO...)
+  *                The timer TRGO event should be selected using TIM_SelectOutputTrigger()
+  *
+  *             3- Software using DAC_Trigger_Software
+  *
+  *          DAC Buffer mode feature
+  *          ========================  
+  *          Each DAC channel integrates an output buffer that can be used to 
+  *          reduce the output impedance, and to drive external loads directly
+  *          without having to add an external operational amplifier.
+  *          To enable, the output buffer use  
+  *              DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+  *          
+  *          Refer to the device datasheet for more details about output 
+  *          impedance value with and without output buffer.
+  *          
+  *          DAC wave generation feature
+  *          =============================      
+  *          Both DAC channels can be used to generate
+  *             1- Noise wave using DAC_WaveGeneration_Noise
+  *             2- Triangle wave using DAC_WaveGeneration_Triangle
+  *        
+  *          Wave generation can be disabled using DAC_WaveGeneration_None
+  *
+  *          DAC data format
+  *          ================   
+  *          The DAC data format can be:
+  *             1- 8-bit right alignment using DAC_Align_8b_R
+  *             2- 12-bit left alignment using DAC_Align_12b_L
+  *             3- 12-bit right alignment using DAC_Align_12b_R
+  *
+  *          DAC data value to voltage correspondence  
+  *          ========================================  
+  *          The analog output voltage on each DAC channel pin is determined
+  *          by the following equation: 
+  *          DAC_OUTx = VREF+ * DOR / 4095
+  *          with  DOR is the Data Output Register
+  *                VEF+ is the input voltage reference (refer to the device datasheet)
+  *          e.g. To set DAC_OUT1 to 0.7V, use
+  *            DAC_SetChannel1Data(DAC_Align_12b_R, 868);
+  *          Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
+  *
+  *          DMA requests 
+  *          =============    
+  *          A DMA1 request can be generated when an external trigger (but not
+  *          a software trigger) occurs if DMA1 requests are enabled using
+  *          DAC_DMACmd()
+  *          DMA1 requests are mapped as following:
+  *             1- DAC channel1 : mapped on DMA1 Stream5 channel7 which must be 
+  *                               already configured
+  *             2- DAC channel2 : mapped on DMA1 Stream6 channel7 which must be 
+  *                               already configured
+  *
+  *          ===================================================================      
+  *                              How to use this driver 
+  *          ===================================================================          
+  *            - DAC APB clock must be enabled to get write access to DAC
+  *              registers using
+  *              RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE)
+  *            - Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
+  *            - Configure the DAC channel using DAC_Init() function
+  *            - Enable the DAC channel using DAC_Cmd() function
+  * 
+  *  @endverbatim
+  *    
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_dac.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup DAC 
+  * @brief DAC driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* CR register Mask */
+#define CR_CLEAR_MASK              ((uint32_t)0x00000FFE)
+
+/* DAC Dual Channels SWTRIG masks */
+#define DUAL_SWTRIG_SET            ((uint32_t)0x00000003)
+#define DUAL_SWTRIG_RESET          ((uint32_t)0xFFFFFFFC)
+
+/* DHR registers offsets */
+#define DHR12R1_OFFSET             ((uint32_t)0x00000008)
+#define DHR12R2_OFFSET             ((uint32_t)0x00000014)
+#define DHR12RD_OFFSET             ((uint32_t)0x00000020)
+
+/* DOR register offset */
+#define DOR_OFFSET                 ((uint32_t)0x0000002C)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DAC_Private_Functions
+  * @{
+  */
+
+/** @defgroup DAC_Group1 DAC channels configuration
+ *  @brief   DAC channels configuration: trigger, output buffer, data format 
+ *
+@verbatim   
+ ===============================================================================
+          DAC channels configuration: trigger, output buffer, data format
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the DAC peripheral registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void DAC_DeInit(void)
+{
+  /* Enable DAC reset state */
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE);
+  /* Release DAC from reset state */
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE);
+}
+
+/**
+  * @brief  Initializes the DAC peripheral according to the specified parameters
+  *         in the DAC_InitStruct.
+  * @param  DAC_Channel: the selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_InitStruct: pointer to a DAC_InitTypeDef structure that contains
+  *         the configuration information for the  specified DAC channel.
+  * @retval None
+  */
+void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)
+{
+  uint32_t tmpreg1 = 0, tmpreg2 = 0;
+
+  /* Check the DAC parameters */
+  assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger));
+  assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration));
+  assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude));
+  assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer));
+
+/*---------------------------- DAC CR Configuration --------------------------*/
+  /* Get the DAC CR value */
+  tmpreg1 = DAC->CR;
+  /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
+  tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel);
+  /* Configure for the selected DAC channel: buffer output, trigger, 
+     wave generation, mask/amplitude for wave generation */
+  /* Set TSELx and TENx bits according to DAC_Trigger value */
+  /* Set WAVEx bits according to DAC_WaveGeneration value */
+  /* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */ 
+  /* Set BOFFx bit according to DAC_OutputBuffer value */   
+  tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration |
+             DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | \
+             DAC_InitStruct->DAC_OutputBuffer);
+  /* Calculate CR register value depending on DAC_Channel */
+  tmpreg1 |= tmpreg2 << DAC_Channel;
+  /* Write to DAC CR */
+  DAC->CR = tmpreg1;
+}
+
+/**
+  * @brief  Fills each DAC_InitStruct member with its default value.
+  * @param  DAC_InitStruct: pointer to a DAC_InitTypeDef structure which will 
+  *         be initialized.
+  * @retval None
+  */
+void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct)
+{
+/*--------------- Reset DAC init structure parameters values -----------------*/
+  /* Initialize the DAC_Trigger member */
+  DAC_InitStruct->DAC_Trigger = DAC_Trigger_None;
+  /* Initialize the DAC_WaveGeneration member */
+  DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None;
+  /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */
+  DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
+  /* Initialize the DAC_OutputBuffer member */
+  DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+}
+
+/**
+  * @brief  Enables or disables the specified DAC channel.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the DAC channel. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @note   When the DAC channel is enabled the trigger source can no more be modified.
+  * @retval None
+  */
+void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC channel */
+    DAC->CR |= (DAC_CR_EN1 << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC channel */
+    DAC->CR &= (~(DAC_CR_EN1 << DAC_Channel));
+  }
+}
+
+/**
+  * @brief  Enables or disables the selected DAC channel software trigger.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the selected DAC channel software trigger.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable software trigger for the selected DAC channel */
+    DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4);
+  }
+  else
+  {
+    /* Disable software trigger for the selected DAC channel */
+    DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4));
+  }
+}
+
+/**
+  * @brief  Enables or disables simultaneously the two DAC channels software triggers.
+  * @param  NewState: new state of the DAC channels software triggers.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable software trigger for both DAC channels */
+    DAC->SWTRIGR |= DUAL_SWTRIG_SET;
+  }
+  else
+  {
+    /* Disable software trigger for both DAC channels */
+    DAC->SWTRIGR &= DUAL_SWTRIG_RESET;
+  }
+}
+
+/**
+  * @brief  Enables or disables the selected DAC channel wave generation.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_Wave: specifies the wave type to enable or disable.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Wave_Noise: noise wave generation
+  *            @arg DAC_Wave_Triangle: triangle wave generation
+  * @param  NewState: new state of the selected DAC channel wave generation.
+  *          This parameter can be: ENABLE or DISABLE.  
+  * @retval None
+  */
+void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_WAVE(DAC_Wave)); 
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected wave generation for the selected DAC channel */
+    DAC->CR |= DAC_Wave << DAC_Channel;
+  }
+  else
+  {
+    /* Disable the selected wave generation for the selected DAC channel */
+    DAC->CR &= ~(DAC_Wave << DAC_Channel);
+  }
+}
+
+/**
+  * @brief  Set the specified data holding register value for DAC channel1.
+  * @param  DAC_Align: Specifies the data alignment for DAC channel1.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data: Data to be loaded in the selected data holding register.
+  * @retval None
+  */
+void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data)
+{  
+  __IO uint32_t tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data));
+  
+  tmp = (uint32_t)DAC_BASE; 
+  tmp += DHR12R1_OFFSET + DAC_Align;
+
+  /* Set the DAC channel1 selected data holding register */
+  *(__IO uint32_t *) tmp = Data;
+}
+
+/**
+  * @brief  Set the specified data holding register value for DAC channel2.
+  * @param  DAC_Align: Specifies the data alignment for DAC channel2.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data: Data to be loaded in the selected data holding register.
+  * @retval None
+  */
+void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data)
+{
+  __IO uint32_t tmp = 0;
+
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data));
+  
+  tmp = (uint32_t)DAC_BASE;
+  tmp += DHR12R2_OFFSET + DAC_Align;
+
+  /* Set the DAC channel2 selected data holding register */
+  *(__IO uint32_t *)tmp = Data;
+}
+
+/**
+  * @brief  Set the specified data holding register value for dual channel DAC.
+  * @param  DAC_Align: Specifies the data alignment for dual channel DAC.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data2: Data for DAC Channel2 to be loaded in the selected data holding register.
+  * @param  Data1: Data for DAC Channel1 to be loaded in the selected data  holding register.
+  * @note   In dual mode, a unique register access is required to write in both
+  *          DAC channels at the same time.
+  * @retval None
+  */
+void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1)
+{
+  uint32_t data = 0, tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data1));
+  assert_param(IS_DAC_DATA(Data2));
+  
+  /* Calculate and set dual DAC data holding register value */
+  if (DAC_Align == DAC_Align_8b_R)
+  {
+    data = ((uint32_t)Data2 << 8) | Data1; 
+  }
+  else
+  {
+    data = ((uint32_t)Data2 << 16) | Data1;
+  }
+  
+  tmp = (uint32_t)DAC_BASE;
+  tmp += DHR12RD_OFFSET + DAC_Align;
+
+  /* Set the dual DAC selected data holding register */
+  *(__IO uint32_t *)tmp = data;
+}
+
+/**
+  * @brief  Returns the last data output value of the selected DAC channel.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @retval The selected DAC channel data output value.
+  */
+uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel)
+{
+  __IO uint32_t tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  
+  tmp = (uint32_t) DAC_BASE ;
+  tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2);
+  
+  /* Returns the DAC channel data output register value */
+  return (uint16_t) (*(__IO uint32_t*) tmp);
+}
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Group2 DMA management functions
+ *  @brief   DMA management functions
+ *
+@verbatim   
+ ===============================================================================
+                          DMA management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the specified DAC channel DMA request.
+  * @note   When enabled DMA1 is generated when an external trigger (EXTI Line9,
+  *         TIM2, TIM4, TIM5, TIM6, TIM7 or TIM8  but not a software trigger) occurs.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the selected DAC channel DMA request.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @note   The DAC channel1 is mapped on DMA1 Stream 5 channel7 which must be
+  *          already configured.
+  * @note   The DAC channel2 is mapped on DMA1 Stream 6 channel7 which must be
+  *          already configured.    
+  * @retval None
+  */
+void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC channel DMA request */
+    DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC channel DMA request */
+    DAC->CR &= (~(DAC_CR_DMAEN1 << DAC_Channel));
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Group3 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                   Interrupts and flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the specified DAC interrupts.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt sources to be enabled or disabled. 
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @param  NewState: new state of the specified DAC interrupts.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */ 
+void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState)  
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  assert_param(IS_DAC_IT(DAC_IT)); 
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC interrupts */
+    DAC->CR |=  (DAC_IT << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC interrupts */
+    DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel));
+  }
+}
+
+/**
+  * @brief  Checks whether the specified DAC flag is set or not.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_FLAG: specifies the flag to check. 
+  *          This parameter can be only of the following value:
+  *            @arg DAC_FLAG_DMAUDR: DMA underrun flag
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @retval The new state of DAC_FLAG (SET or RESET).
+  */
+FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+  /* Check the status of the specified DAC flag */
+  if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET)
+  {
+    /* DAC_FLAG is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* DAC_FLAG is reset */
+    bitstatus = RESET;
+  }
+  /* Return the DAC_FLAG status */
+  return  bitstatus;
+}
+
+/**
+  * @brief  Clears the DAC channel's pending flags.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_FLAG: specifies the flag to clear. 
+  *          This parameter can be of the following value:
+  *            @arg DAC_FLAG_DMAUDR: DMA underrun flag 
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).                           
+  * @retval None
+  */
+void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+  /* Clear the selected DAC flags */
+  DAC->SR = (DAC_FLAG << DAC_Channel);
+}
+
+/**
+  * @brief  Checks whether the specified DAC interrupt has occurred or not.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt source to check. 
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @retval The new state of DAC_IT (SET or RESET).
+  */
+ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t enablestatus = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_IT(DAC_IT));
+
+  /* Get the DAC_IT enable bit status */
+  enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ;
+  
+  /* Check the status of the specified DAC interrupt */
+  if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus)
+  {
+    /* DAC_IT is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* DAC_IT is reset */
+    bitstatus = RESET;
+  }
+  /* Return the DAC_IT status */
+  return  bitstatus;
+}
+
+/**
+  * @brief  Clears the DAC channel's interrupt pending bits.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt pending bit to clear.
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask                         
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).                           
+  * @retval None
+  */
+void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_IT(DAC_IT)); 
+
+  /* Clear the selected DAC interrupt pending bits */
+  DAC->SR = (DAC_IT << DAC_Channel);
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 172 - 0
app/Libraries/src/stm32f2xx_dbgmcu.c

@@ -0,0 +1,172 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dbgmcu.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides all the DBGMCU firmware functions.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_dbgmcu.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup DBGMCU 
+  * @brief DBGMCU driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define IDCODE_DEVID_MASK    ((uint32_t)0x00000FFF)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DBGMCU_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Returns the device revision identifier.
+  * @param  None
+  * @retval Device revision identifier
+  */
+uint32_t DBGMCU_GetREVID(void)
+{
+   return(DBGMCU->IDCODE >> 16);
+}
+
+/**
+  * @brief  Returns the device identifier.
+  * @param  None
+  * @retval Device identifier
+  */
+uint32_t DBGMCU_GetDEVID(void)
+{
+   return(DBGMCU->IDCODE & IDCODE_DEVID_MASK);
+}
+
+/**
+  * @brief  Configures low power mode behavior when the MCU is in Debug mode.
+  * @param  DBGMCU_Periph: specifies the low power mode.
+  *   This parameter can be any combination of the following values:
+  *     @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode              
+  *     @arg DBGMCU_STOP: Keep debugger connection during STOP mode               
+  *     @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode        
+  * @param  NewState: new state of the specified low power mode in Debug mode.
+  *   This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DBGMCU_PERIPH(DBGMCU_Periph));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  if (NewState != DISABLE)
+  {
+    DBGMCU->CR |= DBGMCU_Periph;
+  }
+  else
+  {
+    DBGMCU->CR &= ~DBGMCU_Periph;
+  }
+}
+
+/**
+  * @brief  Configures APB1 peripheral behavior when the MCU is in Debug mode.
+  * @param  DBGMCU_Periph: specifies the APB1 peripheral.
+  *   This parameter can be any combination of the following values:        
+  *     @arg DBGMCU_TIM2_STOP: TIM2 counter stopped when Core is halted          
+  *     @arg DBGMCU_TIM3_STOP: TIM3 counter stopped when Core is halted          
+  *     @arg DBGMCU_TIM4_STOP: TIM4 counter stopped when Core is halted
+  *     @arg DBGMCU_TIM5_STOP: TIM5 counter stopped when Core is halted          
+  *     @arg DBGMCU_TIM6_STOP: TIM6 counter stopped when Core is halted          
+  *     @arg DBGMCU_TIM7_STOP: TIM7 counter stopped when Core is halted
+  *     @arg DBGMCU_TIM12_STOP: TIM12 counter stopped when Core is halted  
+  *     @arg DBGMCU_TIM13_STOP: TIM13 counter stopped when Core is halted  
+  *     @arg DBGMCU_TIM14_STOP: TIM14 counter stopped when Core is halted 
+  *     @arg DBGMCU_RTC_STOP: RTC Wakeup counter stopped when Core is halted.                                                                                
+  *     @arg DBGMCU_WWDG_STOP: Debug WWDG stopped when Core is halted
+  *     @arg DBGMCU_IWDG_STOP: Debug IWDG stopped when Core is halted        
+  *     @arg DBGMCU_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted
+  *     @arg DBGMCU_I2C2_SMBUS_TIMEOUT: I2C2 SMBUS timeout mode stopped when Core is halted
+  *     @arg DBGMCU_I2C3_SMBUS_TIMEOUT: I2C3 SMBUS timeout mode stopped when Core is halted
+  *     @arg DBGMCU_CAN2_STOP: Debug CAN1 stopped when Core is halted           
+  *     @arg DBGMCU_CAN1_STOP: Debug CAN2 stopped when Core is halted        
+  *   This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DBGMCU_APB1PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DBGMCU_APB1PERIPH(DBGMCU_Periph));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    DBGMCU->APB1FZ |= DBGMCU_Periph;
+  }
+  else
+  {
+    DBGMCU->APB1FZ &= ~DBGMCU_Periph;
+  }
+}
+
+/**
+  * @brief  Configures APB2 peripheral behavior when the MCU is in Debug mode.
+  * @param  DBGMCU_Periph: specifies the APB2 peripheral.
+  *   This parameter can be any combination of the following values:       
+  *     @arg DBGMCU_TIM1_STOP: TIM1 counter stopped when Core is halted                
+  *     @arg DBGMCU_TIM8_STOP: TIM8 counter stopped when Core is halted
+  *     @arg DBGMCU_TIM9_STOP: TIM9 counter stopped when Core is halted   
+  *     @arg DBGMCU_TIM10_STOP: TIM10 counter stopped when Core is halted   
+  *     @arg DBGMCU_TIM11_STOP: TIM11 counter stopped when Core is halted                                                                                  
+  * @param  NewState: new state of the specified peripheral in Debug mode.
+  *   This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DBGMCU_APB2PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DBGMCU_APB2PERIPH(DBGMCU_Periph));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    DBGMCU->APB2FZ |= DBGMCU_Periph;
+  }
+  else
+  {
+    DBGMCU->APB2FZ &= ~DBGMCU_Periph;
+  }
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 532 - 0
app/Libraries/src/stm32f2xx_dcmi.c

@@ -0,0 +1,532 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_dcmi.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the DCMI peripheral:           
+  *           - Initialization and Configuration
+  *           - Image capture functions  
+  *           - Interrupts and flags management
+  *
+  *  @verbatim  
+  *  
+  *        
+  *          ===================================================================
+  *                                 How to use this driver
+  *          ===================================================================  
+  *         
+  *         The sequence below describes how to use this driver to capture image
+  *         from a camera module connected to the DCMI Interface.
+  *         This sequence does not take into account the configuration of the  
+  *         camera module, which should be made before to configure and enable
+  *         the DCMI to capture images.
+  *           
+  *          1. Enable the clock for the DCMI and associated GPIOs using the following functions:
+  *                 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
+  *                 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+  *
+  *          2. DCMI pins configuration 
+  *             - Connect the involved DCMI pins to AF13 using the following function 
+  *                 GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_DCMI); 
+  *             - Configure these DCMI pins in alternate function mode by calling the function
+  *                 GPIO_Init();
+  *    
+  *          3. Declare a DCMI_InitTypeDef structure, for example:
+  *                 DCMI_InitTypeDef  DCMI_InitStructure;
+  *             and fill the DCMI_InitStructure variable with the allowed values
+  *             of the structure member.
+  *  
+  *          4. Initialize the DCMI interface by calling the function
+  *                 DCMI_Init(&DCMI_InitStructure); 
+  *  
+  *          5. Configure the DMA2_Stream1 channel1 to transfer Data from DCMI DR
+  *             register to the destination memory buffer.
+  *  
+  *          6. Enable DCMI interface using the function
+  *                 DCMI_Cmd(ENABLE);
+  *                 
+  *         7. Start the image capture using the function
+  *                 DCMI_CaptureCmd(ENABLE);
+  *                 
+  *         8. At this stage the DCMI interface waits for the first start of frame,
+  *            then a DMA request is generated continuously/once (depending on the
+  *            mode used, Continuous/Snapshot) to transfer the received data into
+  *            the destination memory. 
+  *   
+  *  @note  If you need to capture only a rectangular window from the received
+  *         image, you have to use the DCMI_CROPConfig() function to configure 
+  *         the coordinates and size of the window to be captured, then enable 
+  *         the Crop feature using DCMI_CROPCmd(ENABLE);  
+  *         In this case, the Crop configuration should be made before to enable
+  *         and start the DCMI interface. 
+  *        
+  *  @endverbatim   
+  *  
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_dcmi.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup DCMI 
+  * @brief DCMI driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DCMI_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup DCMI_Group1 Initialization and Configuration functions
+ *  @brief   Initialization and Configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                  Initialization and Configuration functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the DCMI registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void DCMI_DeInit(void)
+{
+  DCMI->CR = 0x0;
+  DCMI->IER = 0x0;
+  DCMI->ICR = 0x1F;
+  DCMI->ESCR = 0x0;
+  DCMI->ESUR = 0x0;
+  DCMI->CWSTRTR = 0x0;
+  DCMI->CWSIZER = 0x0;
+}
+
+/**
+  * @brief  Initializes the DCMI according to the specified parameters in the DCMI_InitStruct.
+  * @param  DCMI_InitStruct: pointer to a DCMI_InitTypeDef structure that contains 
+  *         the configuration information for the DCMI.
+  * @retval None
+  */
+void DCMI_Init(DCMI_InitTypeDef* DCMI_InitStruct)
+{
+  uint32_t temp = 0x0;
+  
+  /* Check the parameters */
+  assert_param(IS_DCMI_CAPTURE_MODE(DCMI_InitStruct->DCMI_CaptureMode));
+  assert_param(IS_DCMI_SYNCHRO(DCMI_InitStruct->DCMI_SynchroMode));
+  assert_param(IS_DCMI_PCKPOLARITY(DCMI_InitStruct->DCMI_PCKPolarity));
+  assert_param(IS_DCMI_VSPOLARITY(DCMI_InitStruct->DCMI_VSPolarity));
+  assert_param(IS_DCMI_HSPOLARITY(DCMI_InitStruct->DCMI_HSPolarity));
+  assert_param(IS_DCMI_CAPTURE_RATE(DCMI_InitStruct->DCMI_CaptureRate));
+  assert_param(IS_DCMI_EXTENDED_DATA(DCMI_InitStruct->DCMI_ExtendedDataMode));
+
+  /* The DCMI configuration registers should be programmed correctly before 
+  enabling the CR_ENABLE Bit and the CR_CAPTURE Bit */
+  DCMI->CR &= ~(DCMI_CR_ENABLE | DCMI_CR_CAPTURE);
+   
+  /* Reset the old DCMI configuration */
+  temp = DCMI->CR;
+  
+  temp &= ~((uint32_t)DCMI_CR_CM     | DCMI_CR_ESS   | DCMI_CR_PCKPOL |
+                      DCMI_CR_HSPOL  | DCMI_CR_VSPOL | DCMI_CR_FCRC_0 | 
+                      DCMI_CR_FCRC_1 | DCMI_CR_EDM_0 | DCMI_CR_EDM_1); 
+                  
+  /* Sets the new configuration of the DCMI peripheral */
+  temp |= ((uint32_t)DCMI_InitStruct->DCMI_CaptureMode |
+                     DCMI_InitStruct->DCMI_SynchroMode |
+                     DCMI_InitStruct->DCMI_PCKPolarity |
+                     DCMI_InitStruct->DCMI_VSPolarity |
+                     DCMI_InitStruct->DCMI_HSPolarity |
+                     DCMI_InitStruct->DCMI_CaptureRate |
+                     DCMI_InitStruct->DCMI_ExtendedDataMode);
+
+  DCMI->CR = temp;                              
+}
+
+/**
+  * @brief  Fills each DCMI_InitStruct member with its default value.
+  * @param  DCMI_InitStruct : pointer to a DCMI_InitTypeDef structure which will
+  *         be initialized.
+  * @retval None
+  */
+void DCMI_StructInit(DCMI_InitTypeDef* DCMI_InitStruct)
+{
+  /* Set the default configuration */
+  DCMI_InitStruct->DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
+  DCMI_InitStruct->DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
+  DCMI_InitStruct->DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
+  DCMI_InitStruct->DCMI_VSPolarity = DCMI_VSPolarity_Low;
+  DCMI_InitStruct->DCMI_HSPolarity = DCMI_HSPolarity_Low;
+  DCMI_InitStruct->DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
+  DCMI_InitStruct->DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
+}
+
+/**
+  * @brief  Initializes the DCMI peripheral CROP mode according to the specified
+  *         parameters in the DCMI_CROPInitStruct.
+  * @note   This function should be called before to enable and start the DCMI interface.   
+  * @param  DCMI_CROPInitStruct:  pointer to a DCMI_CROPInitTypeDef structure that 
+  *         contains the configuration information for the DCMI peripheral CROP mode.
+  * @retval None
+  */
+void DCMI_CROPConfig(DCMI_CROPInitTypeDef* DCMI_CROPInitStruct)
+{  
+  /* Sets the CROP window coordinates */
+  DCMI->CWSTRTR = (uint32_t)((uint32_t)DCMI_CROPInitStruct->DCMI_HorizontalOffsetCount |
+                  ((uint32_t)DCMI_CROPInitStruct->DCMI_VerticalStartLine << 16));
+
+  /* Sets the CROP window size */
+  DCMI->CWSIZER = (uint32_t)(DCMI_CROPInitStruct->DCMI_CaptureCount |
+                  ((uint32_t)DCMI_CROPInitStruct->DCMI_VerticalLineCount << 16));
+}
+
+/**
+  * @brief  Enables or disables the DCMI Crop feature.
+  * @note   This function should be called before to enable and start the DCMI interface.
+  * @param  NewState: new state of the DCMI Crop feature. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DCMI_CROPCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+    
+  if (NewState != DISABLE)
+  {
+    /* Enable the DCMI Crop feature */
+    DCMI->CR |= (uint32_t)DCMI_CR_CROP;
+  }
+  else
+  {
+    /* Disable the DCMI Crop feature */
+    DCMI->CR &= ~(uint32_t)DCMI_CR_CROP;
+  }
+}
+
+/**
+  * @brief  Sets the embedded synchronization codes
+  * @param  DCMI_CodesInitTypeDef: pointer to a DCMI_CodesInitTypeDef structure that
+  *         contains the embedded synchronization codes for the DCMI peripheral.
+  * @retval None
+  */
+void DCMI_SetEmbeddedSynchroCodes(DCMI_CodesInitTypeDef* DCMI_CodesInitStruct)
+{
+  DCMI->ESCR = (uint32_t)(DCMI_CodesInitStruct->DCMI_FrameStartCode |
+                          ((uint32_t)DCMI_CodesInitStruct->DCMI_LineStartCode << 8)|
+                          ((uint32_t)DCMI_CodesInitStruct->DCMI_LineEndCode << 16)|
+                          ((uint32_t)DCMI_CodesInitStruct->DCMI_FrameEndCode << 24));
+}
+
+/**
+  * @brief  Enables or disables the DCMI JPEG format.
+  * @note   The Crop and Embedded Synchronization features cannot be used in this mode.  
+  * @param  NewState: new state of the DCMI JPEG format. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DCMI_JPEGCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+ 
+  if (NewState != DISABLE)
+  {
+    /* Enable the DCMI JPEG format */
+    DCMI->CR |= (uint32_t)DCMI_CR_JPEG;
+  }
+  else
+  {
+    /* Disable the DCMI JPEG format */
+    DCMI->CR &= ~(uint32_t)DCMI_CR_JPEG;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup DCMI_Group2 Image capture functions
+ *  @brief   Image capture functions
+ *
+@verbatim   
+ ===============================================================================
+                                 Image capture functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Enables or disables the DCMI interface.
+  * @param  NewState: new state of the DCMI interface. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DCMI_Cmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the DCMI by setting ENABLE bit */
+    DCMI->CR |= (uint32_t)DCMI_CR_ENABLE;
+  }
+  else
+  {
+    /* Disable the DCMI by clearing ENABLE bit */
+    DCMI->CR &= ~(uint32_t)DCMI_CR_ENABLE;
+  }
+}
+
+/**
+  * @brief  Enables or disables the DCMI Capture.
+  * @param  NewState: new state of the DCMI capture. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DCMI_CaptureCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+    
+  if (NewState != DISABLE)
+  {
+    /* Enable the DCMI Capture */
+    DCMI->CR |= (uint32_t)DCMI_CR_CAPTURE;
+  }
+  else
+  {
+    /* Disable the DCMI Capture */
+    DCMI->CR &= ~(uint32_t)DCMI_CR_CAPTURE;
+  }
+}
+
+/**
+  * @brief  Reads the data stored in the DR register.
+  * @param  None 
+  * @retval Data register value
+  */
+uint32_t DCMI_ReadData(void)
+{
+  return DCMI->DR;
+}
+/**
+  * @}
+  */
+
+/** @defgroup DCMI_Group3 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                  Interrupts and flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the DCMI interface interrupts.
+  * @param  DCMI_IT: specifies the DCMI interrupt sources to be enabled or disabled. 
+  *          This parameter can be any combination of the following values:
+  *            @arg DCMI_IT_FRAME: Frame capture complete interrupt mask
+  *            @arg DCMI_IT_OVF: Overflow interrupt mask
+  *            @arg DCMI_IT_ERR: Synchronization error interrupt mask
+  *            @arg DCMI_IT_VSYNC: VSYNC interrupt mask
+  *            @arg DCMI_IT_LINE: Line interrupt mask
+  * @param  NewState: new state of the specified DCMI interrupts.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DCMI_ITConfig(uint16_t DCMI_IT, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DCMI_CONFIG_IT(DCMI_IT));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the Interrupt sources */
+    DCMI->IER |= DCMI_IT;
+  }
+  else
+  {
+    /* Disable the Interrupt sources */
+    DCMI->IER &= (uint16_t)(~DCMI_IT);
+  }  
+}
+
+/**
+  * @brief  Checks whether the  DCMI interface flag is set or not.
+  * @param  DCMI_FLAG: specifies the flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg DCMI_FLAG_FRAMERI: Frame capture complete Raw flag mask
+  *            @arg DCMI_FLAG_OVFRI: Overflow Raw flag mask
+  *            @arg DCMI_FLAG_ERRRI: Synchronization error Raw flag mask
+  *            @arg DCMI_FLAG_VSYNCRI: VSYNC Raw flag mask
+  *            @arg DCMI_FLAG_LINERI: Line Raw flag mask
+  *            @arg DCMI_FLAG_FRAMEMI: Frame capture complete Masked flag mask
+  *            @arg DCMI_FLAG_OVFMI: Overflow Masked flag mask
+  *            @arg DCMI_FLAG_ERRMI: Synchronization error Masked flag mask
+  *            @arg DCMI_FLAG_VSYNCMI: VSYNC Masked flag mask
+  *            @arg DCMI_FLAG_LINEMI: Line Masked flag mask
+  *            @arg DCMI_FLAG_HSYNC: HSYNC flag mask
+  *            @arg DCMI_FLAG_VSYNC: VSYNC flag mask
+  *            @arg DCMI_FLAG_FNE: Fifo not empty flag mask
+  * @retval The new state of DCMI_FLAG (SET or RESET).
+  */
+FlagStatus DCMI_GetFlagStatus(uint16_t DCMI_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  uint32_t dcmireg, tempreg = 0;
+
+  /* Check the parameters */
+  assert_param(IS_DCMI_GET_FLAG(DCMI_FLAG));
+  
+  /* Get the DCMI register index */
+  dcmireg = (((uint16_t)DCMI_FLAG) >> 12);
+  
+  if (dcmireg == 0x00) /* The FLAG is in RISR register */
+  {
+    tempreg= DCMI->RISR;
+  }
+  else if (dcmireg == 0x02) /* The FLAG is in SR register */
+  {
+    tempreg = DCMI->SR;
+  }
+  else /* The FLAG is in MISR register */
+  {
+    tempreg = DCMI->MISR;
+  }
+  
+  if ((tempreg & DCMI_FLAG) != (uint16_t)RESET )
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  /* Return the DCMI_FLAG status */
+  return  bitstatus;
+}
+
+/**
+  * @brief  Clears the DCMI's pending flags.
+  * @param  DCMI_FLAG: specifies the flag to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg DCMI_FLAG_FRAMERI: Frame capture complete Raw flag mask
+  *            @arg DCMI_FLAG_OVFRI: Overflow Raw flag mask
+  *            @arg DCMI_FLAG_ERRRI: Synchronization error Raw flag mask
+  *            @arg DCMI_FLAG_VSYNCRI: VSYNC Raw flag mask
+  *            @arg DCMI_FLAG_LINERI: Line Raw flag mask
+  * @retval None
+  */
+void DCMI_ClearFlag(uint16_t DCMI_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_DCMI_CLEAR_FLAG(DCMI_FLAG));
+  
+  /* Clear the flag by writing in the ICR register 1 in the corresponding 
+  Flag position*/
+  
+  DCMI->ICR = DCMI_FLAG;
+}
+
+/**
+  * @brief  Checks whether the DCMI interrupt has occurred or not.
+  * @param  DCMI_IT: specifies the DCMI interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg DCMI_IT_FRAME: Frame capture complete interrupt mask
+  *            @arg DCMI_IT_OVF: Overflow interrupt mask
+  *            @arg DCMI_IT_ERR: Synchronization error interrupt mask
+  *            @arg DCMI_IT_VSYNC: VSYNC interrupt mask
+  *            @arg DCMI_IT_LINE: Line interrupt mask
+  * @retval The new state of DCMI_IT (SET or RESET).
+  */
+ITStatus DCMI_GetITStatus(uint16_t DCMI_IT)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t itstatus = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DCMI_GET_IT(DCMI_IT));
+  
+  itstatus = DCMI->MISR & DCMI_IT; /* Only masked interrupts are checked */
+  
+  if ((itstatus != (uint16_t)RESET))
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the DCMI's interrupt pending bits.
+  * @param  DCMI_IT: specifies the DCMI interrupt pending bit to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg DCMI_IT_FRAME: Frame capture complete interrupt mask
+  *            @arg DCMI_IT_OVF: Overflow interrupt mask
+  *            @arg DCMI_IT_ERR: Synchronization error interrupt mask
+  *            @arg DCMI_IT_VSYNC: VSYNC interrupt mask
+  *            @arg DCMI_IT_LINE: Line interrupt mask
+  * @retval None
+  */
+void DCMI_ClearITPendingBit(uint16_t DCMI_IT)
+{
+  /* Clear the interrupt pending Bit by writing in the ICR register 1 in the 
+  corresponding pending Bit position*/
+  
+  DCMI->ICR = DCMI_IT;
+}
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1281 - 0
app/Libraries/src/stm32f2xx_dma.c


+ 304 - 0
app/Libraries/src/stm32f2xx_exti.c

@@ -0,0 +1,304 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_exti.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the EXTI peripheral:           
+  *           - Initialization and Configuration
+  *           - Interrupts and flags management
+  *
+  *  @verbatim  
+  *  
+  *          ===================================================================
+  *                                     EXTI features
+  *          ===================================================================
+  *    
+  *          External interrupt/event lines are mapped as following:
+  *            1- All available GPIO pins are connected to the 16 external 
+  *               interrupt/event lines from EXTI0 to EXTI15.
+  *            2- EXTI line 16 is connected to the PVD Output
+  *            3- EXTI line 17 is connected to the RTC Alarm event
+  *            4- EXTI line 18 is connected to the USB OTG FS Wakeup from suspend event                                    
+  *            5- EXTI line 19 is connected to the Ethernet Wakeup event
+  *            6- EXTI line 20 is connected to the USB OTG HS (configured in FS) Wakeup event 
+  *            7- EXTI line 21 is connected to the RTC Tamper and Time Stamp events                                               
+  *            8- EXTI line 22 is connected to the RTC Wakeup event
+  *        
+  *          ===================================================================
+  *                                 How to use this driver
+  *          ===================================================================  
+  *              
+  *          In order to use an I/O pin as an external interrupt source, follow
+  *          steps below:
+  *            1- Configure the I/O in input mode using GPIO_Init()
+  *            2- Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig()
+  *            3- Select the mode(interrupt, event) and configure the trigger 
+  *               selection (Rising, falling or both) using EXTI_Init()
+  *            4- Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init()
+  *   
+  *  @note  SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx
+  *         registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
+  *          
+  *  @endverbatim                  
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_exti.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup EXTI 
+  * @brief EXTI driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+#define EXTI_LINENONE    ((uint32_t)0x00000)  /* No interrupt selected */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup EXTI_Private_Functions
+  * @{
+  */
+
+/** @defgroup EXTI_Group1 Initialization and Configuration functions
+ *  @brief   Initialization and Configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                  Initialization and Configuration functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the EXTI peripheral registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void EXTI_DeInit(void)
+{
+  EXTI->IMR = 0x00000000;
+  EXTI->EMR = 0x00000000;
+  EXTI->RTSR = 0x00000000;
+  EXTI->FTSR = 0x00000000;
+  EXTI->PR = 0x007FFFFF;
+}
+
+/**
+  * @brief  Initializes the EXTI peripheral according to the specified
+  *         parameters in the EXTI_InitStruct.
+  * @param  EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure
+  *         that contains the configuration information for the EXTI peripheral.
+  * @retval None
+  */
+void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
+{
+  uint32_t tmp = 0;
+
+  /* Check the parameters */
+  assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode));
+  assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger));
+  assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line));  
+  assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd));
+
+  tmp = (uint32_t)EXTI_BASE;
+     
+  if (EXTI_InitStruct->EXTI_LineCmd != DISABLE)
+  {
+    /* Clear EXTI line configuration */
+    EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
+    EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;
+    
+    tmp += EXTI_InitStruct->EXTI_Mode;
+
+    *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
+
+    /* Clear Rising Falling edge configuration */
+    EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line;
+    EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line;
+    
+    /* Select the trigger for the selected external interrupts */
+    if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling)
+    {
+      /* Rising Falling edge */
+      EXTI->RTSR |= EXTI_InitStruct->EXTI_Line;
+      EXTI->FTSR |= EXTI_InitStruct->EXTI_Line;
+    }
+    else
+    {
+      tmp = (uint32_t)EXTI_BASE;
+      tmp += EXTI_InitStruct->EXTI_Trigger;
+
+      *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
+    }
+  }
+  else
+  {
+    tmp += EXTI_InitStruct->EXTI_Mode;
+
+    /* Disable the selected external lines */
+    *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line;
+  }
+}
+
+/**
+  * @brief  Fills each EXTI_InitStruct member with its reset value.
+  * @param  EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure which will
+  *         be initialized.
+  * @retval None
+  */
+void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct)
+{
+  EXTI_InitStruct->EXTI_Line = EXTI_LINENONE;
+  EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt;
+  EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling;
+  EXTI_InitStruct->EXTI_LineCmd = DISABLE;
+}
+
+/**
+  * @brief  Generates a Software interrupt on selected EXTI line.
+  * @param  EXTI_Line: specifies the EXTI line on which the software interrupt
+  *         will be generated.
+  *         This parameter can be any combination of EXTI_Linex where x can be (0..22)
+  * @retval None
+  */
+void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line)
+{
+  /* Check the parameters */
+  assert_param(IS_EXTI_LINE(EXTI_Line));
+  
+  EXTI->SWIER |= EXTI_Line;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup EXTI_Group2 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions 
+ *
+@verbatim   
+ ===============================================================================
+                  Interrupts and flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Checks whether the specified EXTI line flag is set or not.
+  * @param  EXTI_Line: specifies the EXTI line flag to check.
+  *          This parameter can be EXTI_Linex where x can be(0..22)
+  * @retval The new state of EXTI_Line (SET or RESET).
+  */
+FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line)
+{
+  FlagStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_GET_EXTI_LINE(EXTI_Line));
+  
+  if ((EXTI->PR & EXTI_Line) != (uint32_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the EXTI's line pending flags.
+  * @param  EXTI_Line: specifies the EXTI lines flags to clear.
+  *          This parameter can be any combination of EXTI_Linex where x can be (0..22)
+  * @retval None
+  */
+void EXTI_ClearFlag(uint32_t EXTI_Line)
+{
+  /* Check the parameters */
+  assert_param(IS_EXTI_LINE(EXTI_Line));
+  
+  EXTI->PR = EXTI_Line;
+}
+
+/**
+  * @brief  Checks whether the specified EXTI line is asserted or not.
+  * @param  EXTI_Line: specifies the EXTI line to check.
+  *          This parameter can be EXTI_Linex where x can be(0..22)
+  * @retval The new state of EXTI_Line (SET or RESET).
+  */
+ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t enablestatus = 0;
+  /* Check the parameters */
+  assert_param(IS_GET_EXTI_LINE(EXTI_Line));
+  
+  enablestatus =  EXTI->IMR & EXTI_Line;
+  if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET))
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the EXTI's line pending bits.
+  * @param  EXTI_Line: specifies the EXTI lines to clear.
+  *          This parameter can be any combination of EXTI_Linex where x can be (0..22)
+  * @retval None
+  */
+void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
+{
+  /* Check the parameters */
+  assert_param(IS_EXTI_LINE(EXTI_Line));
+  
+  EXTI->PR = EXTI_Line;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1052 - 0
app/Libraries/src/stm32f2xx_flash.c


+ 979 - 0
app/Libraries/src/stm32f2xx_fsmc.c

@@ -0,0 +1,979 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_fsmc.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+ * @brief    This file provides firmware functions to manage the following 
+  *          functionalities of the FSMC peripheral:           
+  *           - Interface with SRAM, PSRAM, NOR and OneNAND memories
+  *           - Interface with NAND memories
+  *           - Interface with 16-bit PC Card compatible memories  
+  *           - Interrupts and flags management   
+  *           
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_fsmc.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup FSMC 
+  * @brief FSMC driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* --------------------- FSMC registers bit mask ---------------------------- */
+/* FSMC BCRx Mask */
+#define BCR_MBKEN_SET          ((uint32_t)0x00000001)
+#define BCR_MBKEN_RESET        ((uint32_t)0x000FFFFE)
+#define BCR_FACCEN_SET         ((uint32_t)0x00000040)
+
+/* FSMC PCRx Mask */
+#define PCR_PBKEN_SET          ((uint32_t)0x00000004)
+#define PCR_PBKEN_RESET        ((uint32_t)0x000FFFFB)
+#define PCR_ECCEN_SET          ((uint32_t)0x00000040)
+#define PCR_ECCEN_RESET        ((uint32_t)0x000FFFBF)
+#define PCR_MEMORYTYPE_NAND    ((uint32_t)0x00000008)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup FSMC_Private_Functions
+  * @{
+  */
+
+/** @defgroup FSMC_Group1 NOR/SRAM Controller functions
+ *  @brief   NOR/SRAM Controller functions 
+ *
+@verbatim   
+ ===============================================================================
+                    NOR/SRAM Controller functions
+ ===============================================================================  
+
+ The following sequence should be followed to configure the FSMC to interface with
+ SRAM, PSRAM, NOR or OneNAND memory connected to the NOR/SRAM Bank:
+ 
+   1. Enable the clock for the FSMC and associated GPIOs using the following functions:
+          RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
+          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+
+   2. FSMC pins configuration 
+       - Connect the involved FSMC pins to AF12 using the following function 
+          GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_FSMC); 
+       - Configure these FSMC pins in alternate function mode by calling the function
+          GPIO_Init();    
+       
+   3. Declare a FSMC_NORSRAMInitTypeDef structure, for example:
+          FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
+      and fill the FSMC_NORSRAMInitStructure variable with the allowed values of
+      the structure member.
+      
+   4. Initialize the NOR/SRAM Controller by calling the function
+          FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
+
+   5. Then enable the NOR/SRAM Bank, for example:
+          FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);  
+
+   6. At this stage you can read/write from/to the memory connected to the NOR/SRAM Bank. 
+   
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the FSMC NOR/SRAM Banks registers to their default 
+  *   reset values.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1  
+  *            @arg FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2 
+  *            @arg FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3 
+  *            @arg FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 
+  * @retval None
+  */
+void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank)
+{
+  /* Check the parameter */
+  assert_param(IS_FSMC_NORSRAM_BANK(FSMC_Bank));
+  
+  /* FSMC_Bank1_NORSRAM1 */
+  if(FSMC_Bank == FSMC_Bank1_NORSRAM1)
+  {
+    FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030DB;    
+  }
+  /* FSMC_Bank1_NORSRAM2,  FSMC_Bank1_NORSRAM3 or FSMC_Bank1_NORSRAM4 */
+  else
+  {   
+    FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030D2; 
+  }
+  FSMC_Bank1->BTCR[FSMC_Bank + 1] = 0x0FFFFFFF;
+  FSMC_Bank1E->BWTR[FSMC_Bank] = 0x0FFFFFFF;  
+}
+
+/**
+  * @brief  Initializes the FSMC NOR/SRAM Banks according to the specified
+  *         parameters in the FSMC_NORSRAMInitStruct.
+  * @param  FSMC_NORSRAMInitStruct : pointer to a FSMC_NORSRAMInitTypeDef structure
+  *         that contains the configuration information for the FSMC NOR/SRAM 
+  *         specified Banks.                       
+  * @retval None
+  */
+void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct)
+{ 
+  /* Check the parameters */
+  assert_param(IS_FSMC_NORSRAM_BANK(FSMC_NORSRAMInitStruct->FSMC_Bank));
+  assert_param(IS_FSMC_MUX(FSMC_NORSRAMInitStruct->FSMC_DataAddressMux));
+  assert_param(IS_FSMC_MEMORY(FSMC_NORSRAMInitStruct->FSMC_MemoryType));
+  assert_param(IS_FSMC_MEMORY_WIDTH(FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth));
+  assert_param(IS_FSMC_BURSTMODE(FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode));
+  assert_param(IS_FSMC_ASYNWAIT(FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait));
+  assert_param(IS_FSMC_WAIT_POLARITY(FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity));
+  assert_param(IS_FSMC_WRAP_MODE(FSMC_NORSRAMInitStruct->FSMC_WrapMode));
+  assert_param(IS_FSMC_WAIT_SIGNAL_ACTIVE(FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive));
+  assert_param(IS_FSMC_WRITE_OPERATION(FSMC_NORSRAMInitStruct->FSMC_WriteOperation));
+  assert_param(IS_FSMC_WAITE_SIGNAL(FSMC_NORSRAMInitStruct->FSMC_WaitSignal));
+  assert_param(IS_FSMC_EXTENDED_MODE(FSMC_NORSRAMInitStruct->FSMC_ExtendedMode));
+  assert_param(IS_FSMC_WRITE_BURST(FSMC_NORSRAMInitStruct->FSMC_WriteBurst));  
+  assert_param(IS_FSMC_ADDRESS_SETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime));
+  assert_param(IS_FSMC_ADDRESS_HOLD_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime));
+  assert_param(IS_FSMC_DATASETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime));
+  assert_param(IS_FSMC_TURNAROUND_TIME(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration));
+  assert_param(IS_FSMC_CLK_DIV(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision));
+  assert_param(IS_FSMC_DATA_LATENCY(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency));
+  assert_param(IS_FSMC_ACCESS_MODE(FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode)); 
+  
+  /* Bank1 NOR/SRAM control register configuration */ 
+  FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] = 
+            (uint32_t)FSMC_NORSRAMInitStruct->FSMC_DataAddressMux |
+            FSMC_NORSRAMInitStruct->FSMC_MemoryType |
+            FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth |
+            FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode |
+            FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait |
+            FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity |
+            FSMC_NORSRAMInitStruct->FSMC_WrapMode |
+            FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive |
+            FSMC_NORSRAMInitStruct->FSMC_WriteOperation |
+            FSMC_NORSRAMInitStruct->FSMC_WaitSignal |
+            FSMC_NORSRAMInitStruct->FSMC_ExtendedMode |
+            FSMC_NORSRAMInitStruct->FSMC_WriteBurst;
+  if(FSMC_NORSRAMInitStruct->FSMC_MemoryType == FSMC_MemoryType_NOR)
+  {
+    FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] |= (uint32_t)BCR_FACCEN_SET;
+  }
+  /* Bank1 NOR/SRAM timing register configuration */
+  FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank+1] = 
+            (uint32_t)FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime |
+            (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime << 4) |
+            (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime << 8) |
+            (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration << 16) |
+            (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision << 20) |
+            (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency << 24) |
+             FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode;
+            
+    
+  /* Bank1 NOR/SRAM timing register for write configuration, if extended mode is used */
+  if(FSMC_NORSRAMInitStruct->FSMC_ExtendedMode == FSMC_ExtendedMode_Enable)
+  {
+    assert_param(IS_FSMC_ADDRESS_SETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime));
+    assert_param(IS_FSMC_ADDRESS_HOLD_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime));
+    assert_param(IS_FSMC_DATASETUP_TIME(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime));
+    assert_param(IS_FSMC_CLK_DIV(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision));
+    assert_param(IS_FSMC_DATA_LATENCY(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency));
+    assert_param(IS_FSMC_ACCESS_MODE(FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode));
+    FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = 
+              (uint32_t)FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime |
+              (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime << 4 )|
+              (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime << 8) |
+              (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision << 20) |
+              (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency << 24) |
+               FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode;
+  }
+  else
+  {
+    FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = 0x0FFFFFFF;
+  }
+}
+
+/**
+  * @brief  Fills each FSMC_NORSRAMInitStruct member with its default value.
+  * @param  FSMC_NORSRAMInitStruct: pointer to a FSMC_NORSRAMInitTypeDef structure 
+  *         which will be initialized.
+  * @retval None
+  */
+void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct)
+{  
+  /* Reset NOR/SRAM Init structure parameters values */
+  FSMC_NORSRAMInitStruct->FSMC_Bank = FSMC_Bank1_NORSRAM1;
+  FSMC_NORSRAMInitStruct->FSMC_DataAddressMux = FSMC_DataAddressMux_Enable;
+  FSMC_NORSRAMInitStruct->FSMC_MemoryType = FSMC_MemoryType_SRAM;
+  FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
+  FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
+  FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
+  FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
+  FSMC_NORSRAMInitStruct->FSMC_WrapMode = FSMC_WrapMode_Disable;
+  FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
+  FSMC_NORSRAMInitStruct->FSMC_WriteOperation = FSMC_WriteOperation_Enable;
+  FSMC_NORSRAMInitStruct->FSMC_WaitSignal = FSMC_WaitSignal_Enable;
+  FSMC_NORSRAMInitStruct->FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
+  FSMC_NORSRAMInitStruct->FSMC_WriteBurst = FSMC_WriteBurst_Disable;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime = 0xFF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A; 
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime = 0xFF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency = 0xF;
+  FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A;
+}
+
+/**
+  * @brief  Enables or disables the specified NOR/SRAM Memory Bank.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1  
+  *            @arg FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2 
+  *            @arg FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3 
+  *            @arg FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 
+  * @param  NewState: new state of the FSMC_Bank. This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState)
+{
+  assert_param(IS_FSMC_NORSRAM_BANK(FSMC_Bank));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected NOR/SRAM Bank by setting the PBKEN bit in the BCRx register */
+    FSMC_Bank1->BTCR[FSMC_Bank] |= BCR_MBKEN_SET;
+  }
+  else
+  {
+    /* Disable the selected NOR/SRAM Bank by clearing the PBKEN bit in the BCRx register */
+    FSMC_Bank1->BTCR[FSMC_Bank] &= BCR_MBKEN_RESET;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Group2 NAND Controller functions
+ *  @brief   NAND Controller functions 
+ *
+@verbatim   
+ ===============================================================================
+                    NAND Controller functions
+ ===============================================================================  
+
+ The following sequence should be followed to configure the FSMC to interface with
+ 8-bit or 16-bit NAND memory connected to the NAND Bank:
+ 
+   1. Enable the clock for the FSMC and associated GPIOs using the following functions:
+          RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
+          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+
+   2. FSMC pins configuration 
+       - Connect the involved FSMC pins to AF12 using the following function 
+          GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_FSMC); 
+       - Configure these FSMC pins in alternate function mode by calling the function
+          GPIO_Init();    
+       
+   3. Declare a FSMC_NANDInitTypeDef structure, for example:
+          FSMC_NANDInitTypeDef  FSMC_NANDInitStructure;
+      and fill the FSMC_NANDInitStructure variable with the allowed values of
+      the structure member.
+      
+   4. Initialize the NAND Controller by calling the function
+          FSMC_NANDInit(&FSMC_NANDInitStructure); 
+
+   5. Then enable the NAND Bank, for example:
+          FSMC_NANDCmd(FSMC_Bank3_NAND, ENABLE);  
+
+   6. At this stage you can read/write from/to the memory connected to the NAND Bank. 
+   
+@note To enable the Error Correction Code (ECC), you have to use the function
+          FSMC_NANDECCCmd(FSMC_Bank3_NAND, ENABLE);  
+      and to get the current ECC value you have to use the function
+          ECCval = FSMC_GetECC(FSMC_Bank3_NAND); 
+
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Deinitializes the FSMC NAND Banks registers to their default reset values.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND 
+  * @retval None
+  */
+void FSMC_NANDDeInit(uint32_t FSMC_Bank)
+{
+  /* Check the parameter */
+  assert_param(IS_FSMC_NAND_BANK(FSMC_Bank));
+  
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    /* Set the FSMC_Bank2 registers to their reset values */
+    FSMC_Bank2->PCR2 = 0x00000018;
+    FSMC_Bank2->SR2 = 0x00000040;
+    FSMC_Bank2->PMEM2 = 0xFCFCFCFC;
+    FSMC_Bank2->PATT2 = 0xFCFCFCFC;  
+  }
+  /* FSMC_Bank3_NAND */  
+  else
+  {
+    /* Set the FSMC_Bank3 registers to their reset values */
+    FSMC_Bank3->PCR3 = 0x00000018;
+    FSMC_Bank3->SR3 = 0x00000040;
+    FSMC_Bank3->PMEM3 = 0xFCFCFCFC;
+    FSMC_Bank3->PATT3 = 0xFCFCFCFC; 
+  }  
+}
+
+/**
+  * @brief  Initializes the FSMC NAND Banks according to the specified parameters
+  *         in the FSMC_NANDInitStruct.
+  * @param  FSMC_NANDInitStruct : pointer to a FSMC_NANDInitTypeDef structure that
+  *         contains the configuration information for the FSMC NAND specified Banks.                       
+  * @retval None
+  */
+void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct)
+{
+  uint32_t tmppcr = 0x00000000, tmppmem = 0x00000000, tmppatt = 0x00000000; 
+    
+  /* Check the parameters */
+  assert_param( IS_FSMC_NAND_BANK(FSMC_NANDInitStruct->FSMC_Bank));
+  assert_param( IS_FSMC_WAIT_FEATURE(FSMC_NANDInitStruct->FSMC_Waitfeature));
+  assert_param( IS_FSMC_MEMORY_WIDTH(FSMC_NANDInitStruct->FSMC_MemoryDataWidth));
+  assert_param( IS_FSMC_ECC_STATE(FSMC_NANDInitStruct->FSMC_ECC));
+  assert_param( IS_FSMC_ECCPAGE_SIZE(FSMC_NANDInitStruct->FSMC_ECCPageSize));
+  assert_param( IS_FSMC_TCLR_TIME(FSMC_NANDInitStruct->FSMC_TCLRSetupTime));
+  assert_param( IS_FSMC_TAR_TIME(FSMC_NANDInitStruct->FSMC_TARSetupTime));
+  assert_param(IS_FSMC_SETUP_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime));
+  assert_param(IS_FSMC_WAIT_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime));
+  assert_param(IS_FSMC_HOLD_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime));
+  assert_param(IS_FSMC_HIZ_TIME(FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime));
+  assert_param(IS_FSMC_SETUP_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime));
+  assert_param(IS_FSMC_WAIT_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime));
+  assert_param(IS_FSMC_HOLD_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime));
+  assert_param(IS_FSMC_HIZ_TIME(FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime));
+  
+  /* Set the tmppcr value according to FSMC_NANDInitStruct parameters */
+  tmppcr = (uint32_t)FSMC_NANDInitStruct->FSMC_Waitfeature |
+            PCR_MEMORYTYPE_NAND |
+            FSMC_NANDInitStruct->FSMC_MemoryDataWidth |
+            FSMC_NANDInitStruct->FSMC_ECC |
+            FSMC_NANDInitStruct->FSMC_ECCPageSize |
+            (FSMC_NANDInitStruct->FSMC_TCLRSetupTime << 9 )|
+            (FSMC_NANDInitStruct->FSMC_TARSetupTime << 13);
+            
+  /* Set tmppmem value according to FSMC_CommonSpaceTimingStructure parameters */
+  tmppmem = (uint32_t)FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime |
+            (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) |
+            (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)|
+            (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); 
+            
+  /* Set tmppatt value according to FSMC_AttributeSpaceTimingStructure parameters */
+  tmppatt = (uint32_t)FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime |
+            (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) |
+            (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)|
+            (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24);
+  
+  if(FSMC_NANDInitStruct->FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    /* FSMC_Bank2_NAND registers configuration */
+    FSMC_Bank2->PCR2 = tmppcr;
+    FSMC_Bank2->PMEM2 = tmppmem;
+    FSMC_Bank2->PATT2 = tmppatt;
+  }
+  else
+  {
+    /* FSMC_Bank3_NAND registers configuration */
+    FSMC_Bank3->PCR3 = tmppcr;
+    FSMC_Bank3->PMEM3 = tmppmem;
+    FSMC_Bank3->PATT3 = tmppatt;
+  }
+}
+
+
+/**
+  * @brief  Fills each FSMC_NANDInitStruct member with its default value.
+  * @param  FSMC_NANDInitStruct: pointer to a FSMC_NANDInitTypeDef structure which
+  *         will be initialized.
+  * @retval None
+  */
+void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct)
+{ 
+  /* Reset NAND Init structure parameters values */
+  FSMC_NANDInitStruct->FSMC_Bank = FSMC_Bank2_NAND;
+  FSMC_NANDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable;
+  FSMC_NANDInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
+  FSMC_NANDInitStruct->FSMC_ECC = FSMC_ECC_Disable;
+  FSMC_NANDInitStruct->FSMC_ECCPageSize = FSMC_ECCPageSize_256Bytes;
+  FSMC_NANDInitStruct->FSMC_TCLRSetupTime = 0x0;
+  FSMC_NANDInitStruct->FSMC_TARSetupTime = 0x0;
+  FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC;
+  FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC;	  
+}
+
+/**
+  * @brief  Enables or disables the specified NAND Memory Bank.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  * @param  NewState: new state of the FSMC_Bank. This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState)
+{
+  assert_param(IS_FSMC_NAND_BANK(FSMC_Bank));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected NAND Bank by setting the PBKEN bit in the PCRx register */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      FSMC_Bank2->PCR2 |= PCR_PBKEN_SET;
+    }
+    else
+    {
+      FSMC_Bank3->PCR3 |= PCR_PBKEN_SET;
+    }
+  }
+  else
+  {
+    /* Disable the selected NAND Bank by clearing the PBKEN bit in the PCRx register */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      FSMC_Bank2->PCR2 &= PCR_PBKEN_RESET;
+    }
+    else
+    {
+      FSMC_Bank3->PCR3 &= PCR_PBKEN_RESET;
+    }
+  }
+}
+/**
+  * @brief  Enables or disables the FSMC NAND ECC feature.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  * @param  NewState: new state of the FSMC NAND ECC feature.  
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState)
+{
+  assert_param(IS_FSMC_NAND_BANK(FSMC_Bank));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected NAND Bank ECC function by setting the ECCEN bit in the PCRx register */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      FSMC_Bank2->PCR2 |= PCR_ECCEN_SET;
+    }
+    else
+    {
+      FSMC_Bank3->PCR3 |= PCR_ECCEN_SET;
+    }
+  }
+  else
+  {
+    /* Disable the selected NAND Bank ECC function by clearing the ECCEN bit in the PCRx register */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      FSMC_Bank2->PCR2 &= PCR_ECCEN_RESET;
+    }
+    else
+    {
+      FSMC_Bank3->PCR3 &= PCR_ECCEN_RESET;
+    }
+  }
+}
+
+/**
+  * @brief  Returns the error correction code register value.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  * @retval The Error Correction Code (ECC) value.
+  */
+uint32_t FSMC_GetECC(uint32_t FSMC_Bank)
+{
+  uint32_t eccval = 0x00000000;
+  
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    /* Get the ECCR2 register value */
+    eccval = FSMC_Bank2->ECCR2;
+  }
+  else
+  {
+    /* Get the ECCR3 register value */
+    eccval = FSMC_Bank3->ECCR3;
+  }
+  /* Return the error correction code value */
+  return(eccval);
+}
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Group3 PCCARD Controller functions
+ *  @brief   PCCARD Controller functions 
+ *
+@verbatim   
+ ===============================================================================
+                    PCCARD Controller functions
+ ===============================================================================  
+
+ The following sequence should be followed to configure the FSMC to interface with
+ 16-bit PC Card compatible memory connected to the PCCARD Bank:
+ 
+   1. Enable the clock for the FSMC and associated GPIOs using the following functions:
+          RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
+          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+
+   2. FSMC pins configuration 
+       - Connect the involved FSMC pins to AF12 using the following function 
+          GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_FSMC); 
+       - Configure these FSMC pins in alternate function mode by calling the function
+          GPIO_Init();    
+       
+   3. Declare a FSMC_PCCARDInitTypeDef structure, for example:
+          FSMC_PCCARDInitTypeDef  FSMC_PCCARDInitStructure;
+      and fill the FSMC_PCCARDInitStructure variable with the allowed values of
+      the structure member.
+      
+   4. Initialize the PCCARD Controller by calling the function
+          FSMC_PCCARDInit(&FSMC_PCCARDInitStructure); 
+
+   5. Then enable the PCCARD Bank:
+          FSMC_PCCARDCmd(ENABLE);  
+
+   6. At this stage you can read/write from/to the memory connected to the PCCARD Bank. 
+ 
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the FSMC PCCARD Bank registers to their default reset values.
+  * @param  None                       
+  * @retval None
+  */
+void FSMC_PCCARDDeInit(void)
+{
+  /* Set the FSMC_Bank4 registers to their reset values */
+  FSMC_Bank4->PCR4 = 0x00000018; 
+  FSMC_Bank4->SR4 = 0x00000000;	
+  FSMC_Bank4->PMEM4 = 0xFCFCFCFC;
+  FSMC_Bank4->PATT4 = 0xFCFCFCFC;
+  FSMC_Bank4->PIO4 = 0xFCFCFCFC;
+}
+
+/**
+  * @brief  Initializes the FSMC PCCARD Bank according to the specified parameters
+  *         in the FSMC_PCCARDInitStruct.
+  * @param  FSMC_PCCARDInitStruct : pointer to a FSMC_PCCARDInitTypeDef structure
+  *         that contains the configuration information for the FSMC PCCARD Bank.                       
+  * @retval None
+  */
+void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct)
+{
+  /* Check the parameters */
+  assert_param(IS_FSMC_WAIT_FEATURE(FSMC_PCCARDInitStruct->FSMC_Waitfeature));
+  assert_param(IS_FSMC_TCLR_TIME(FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime));
+  assert_param(IS_FSMC_TAR_TIME(FSMC_PCCARDInitStruct->FSMC_TARSetupTime));
+ 
+  assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime));
+  assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime));
+  assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime));
+  assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime));
+  
+  assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime));
+  assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime));
+  assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime));
+  assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime));
+  assert_param(IS_FSMC_SETUP_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime));
+  assert_param(IS_FSMC_WAIT_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime));
+  assert_param(IS_FSMC_HOLD_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime));
+  assert_param(IS_FSMC_HIZ_TIME(FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime));
+  
+  /* Set the PCR4 register value according to FSMC_PCCARDInitStruct parameters */
+  FSMC_Bank4->PCR4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_Waitfeature |
+                     FSMC_MemoryDataWidth_16b |  
+                     (FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime << 9) |
+                     (FSMC_PCCARDInitStruct->FSMC_TARSetupTime << 13);
+            
+  /* Set PMEM4 register value according to FSMC_CommonSpaceTimingStructure parameters */
+  FSMC_Bank4->PMEM4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime |
+                      (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) |
+                      (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)|
+                      (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); 
+            
+  /* Set PATT4 register value according to FSMC_AttributeSpaceTimingStructure parameters */
+  FSMC_Bank4->PATT4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime |
+                      (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) |
+                      (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)|
+                      (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24);	
+            
+  /* Set PIO4 register value according to FSMC_IOSpaceTimingStructure parameters */
+  FSMC_Bank4->PIO4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime |
+                     (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime << 8) |
+                     (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime << 16)|
+                     (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime << 24);             
+}
+
+/**
+  * @brief  Fills each FSMC_PCCARDInitStruct member with its default value.
+  * @param  FSMC_PCCARDInitStruct: pointer to a FSMC_PCCARDInitTypeDef structure
+  *         which will be initialized.
+  * @retval None
+  */
+void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct)
+{
+  /* Reset PCCARD Init structure parameters values */
+  FSMC_PCCARDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable;
+  FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime = 0x0;
+  FSMC_PCCARDInitStruct->FSMC_TARSetupTime = 0x0;
+  FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC;	
+  FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC;
+  FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC;
+}
+
+/**
+  * @brief  Enables or disables the PCCARD Memory Bank.
+  * @param  NewState: new state of the PCCARD Memory Bank.  
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void FSMC_PCCARDCmd(FunctionalState NewState)
+{
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the PCCARD Bank by setting the PBKEN bit in the PCR4 register */
+    FSMC_Bank4->PCR4 |= PCR_PBKEN_SET;
+  }
+  else
+  {
+    /* Disable the PCCARD Bank by clearing the PBKEN bit in the PCR4 register */
+    FSMC_Bank4->PCR4 &= PCR_PBKEN_RESET;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup FSMC_Group4  Interrupts and flags management functions
+ *  @brief    Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                     Interrupts and flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the specified FSMC interrupts.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  *            @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD
+  * @param  FSMC_IT: specifies the FSMC interrupt sources to be enabled or disabled.
+  *          This parameter can be any combination of the following values:
+  *            @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. 
+  *            @arg FSMC_IT_Level: Level edge detection interrupt.
+  *            @arg FSMC_IT_FallingEdge: Falling edge detection interrupt.
+  * @param  NewState: new state of the specified FSMC interrupts.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState)
+{
+  assert_param(IS_FSMC_IT_BANK(FSMC_Bank));
+  assert_param(IS_FSMC_IT(FSMC_IT));	
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected FSMC_Bank2 interrupts */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      FSMC_Bank2->SR2 |= FSMC_IT;
+    }
+    /* Enable the selected FSMC_Bank3 interrupts */
+    else if (FSMC_Bank == FSMC_Bank3_NAND)
+    {
+      FSMC_Bank3->SR3 |= FSMC_IT;
+    }
+    /* Enable the selected FSMC_Bank4 interrupts */
+    else
+    {
+      FSMC_Bank4->SR4 |= FSMC_IT;    
+    }
+  }
+  else
+  {
+    /* Disable the selected FSMC_Bank2 interrupts */
+    if(FSMC_Bank == FSMC_Bank2_NAND)
+    {
+      
+      FSMC_Bank2->SR2 &= (uint32_t)~FSMC_IT;
+    }
+    /* Disable the selected FSMC_Bank3 interrupts */
+    else if (FSMC_Bank == FSMC_Bank3_NAND)
+    {
+      FSMC_Bank3->SR3 &= (uint32_t)~FSMC_IT;
+    }
+    /* Disable the selected FSMC_Bank4 interrupts */
+    else
+    {
+      FSMC_Bank4->SR4 &= (uint32_t)~FSMC_IT;    
+    }
+  }
+}
+
+/**
+  * @brief  Checks whether the specified FSMC flag is set or not.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  *            @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD
+  * @param  FSMC_FLAG: specifies the flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_FLAG_RisingEdge: Rising edge detection Flag.
+  *            @arg FSMC_FLAG_Level: Level detection Flag.
+  *            @arg FSMC_FLAG_FallingEdge: Falling edge detection Flag.
+  *            @arg FSMC_FLAG_FEMPT: Fifo empty Flag. 
+  * @retval The new state of FSMC_FLAG (SET or RESET).
+  */
+FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  uint32_t tmpsr = 0x00000000;
+  
+  /* Check the parameters */
+  assert_param(IS_FSMC_GETFLAG_BANK(FSMC_Bank));
+  assert_param(IS_FSMC_GET_FLAG(FSMC_FLAG));
+  
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    tmpsr = FSMC_Bank2->SR2;
+  }  
+  else if(FSMC_Bank == FSMC_Bank3_NAND)
+  {
+    tmpsr = FSMC_Bank3->SR3;
+  }
+  /* FSMC_Bank4_PCCARD*/
+  else
+  {
+    tmpsr = FSMC_Bank4->SR4;
+  } 
+  
+  /* Get the flag status */
+  if ((tmpsr & FSMC_FLAG) != (uint16_t)RESET )
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  /* Return the flag status */
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the FSMC's pending flags.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  *            @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD
+  * @param  FSMC_FLAG: specifies the flag to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg FSMC_FLAG_RisingEdge: Rising edge detection Flag.
+  *            @arg FSMC_FLAG_Level: Level detection Flag.
+  *            @arg FSMC_FLAG_FallingEdge: Falling edge detection Flag.
+  * @retval None
+  */
+void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG)
+{
+ /* Check the parameters */
+  assert_param(IS_FSMC_GETFLAG_BANK(FSMC_Bank));
+  assert_param(IS_FSMC_CLEAR_FLAG(FSMC_FLAG)) ;
+    
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    FSMC_Bank2->SR2 &= ~FSMC_FLAG; 
+  }  
+  else if(FSMC_Bank == FSMC_Bank3_NAND)
+  {
+    FSMC_Bank3->SR3 &= ~FSMC_FLAG;
+  }
+  /* FSMC_Bank4_PCCARD*/
+  else
+  {
+    FSMC_Bank4->SR4 &= ~FSMC_FLAG;
+  }
+}
+
+/**
+  * @brief  Checks whether the specified FSMC interrupt has occurred or not.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  *            @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD
+  * @param  FSMC_IT: specifies the FSMC interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. 
+  *            @arg FSMC_IT_Level: Level edge detection interrupt.
+  *            @arg FSMC_IT_FallingEdge: Falling edge detection interrupt. 
+  * @retval The new state of FSMC_IT (SET or RESET).
+  */
+ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t tmpsr = 0x0, itstatus = 0x0, itenable = 0x0; 
+  
+  /* Check the parameters */
+  assert_param(IS_FSMC_IT_BANK(FSMC_Bank));
+  assert_param(IS_FSMC_GET_IT(FSMC_IT));
+  
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    tmpsr = FSMC_Bank2->SR2;
+  }  
+  else if(FSMC_Bank == FSMC_Bank3_NAND)
+  {
+    tmpsr = FSMC_Bank3->SR3;
+  }
+  /* FSMC_Bank4_PCCARD*/
+  else
+  {
+    tmpsr = FSMC_Bank4->SR4;
+  } 
+  
+  itstatus = tmpsr & FSMC_IT;
+  
+  itenable = tmpsr & (FSMC_IT >> 3);
+  if ((itstatus != (uint32_t)RESET)  && (itenable != (uint32_t)RESET))
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus; 
+}
+
+/**
+  * @brief  Clears the FSMC's interrupt pending bits.
+  * @param  FSMC_Bank: specifies the FSMC Bank to be used
+  *          This parameter can be one of the following values:
+  *            @arg FSMC_Bank2_NAND: FSMC Bank2 NAND 
+  *            @arg FSMC_Bank3_NAND: FSMC Bank3 NAND
+  *            @arg FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD
+  * @param  FSMC_IT: specifies the interrupt pending bit to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg FSMC_IT_RisingEdge: Rising edge detection interrupt. 
+  *            @arg FSMC_IT_Level: Level edge detection interrupt.
+  *            @arg FSMC_IT_FallingEdge: Falling edge detection interrupt.
+  * @retval None
+  */
+void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT)
+{
+  /* Check the parameters */
+  assert_param(IS_FSMC_IT_BANK(FSMC_Bank));
+  assert_param(IS_FSMC_IT(FSMC_IT));
+    
+  if(FSMC_Bank == FSMC_Bank2_NAND)
+  {
+    FSMC_Bank2->SR2 &= ~(FSMC_IT >> 3); 
+  }  
+  else if(FSMC_Bank == FSMC_Bank3_NAND)
+  {
+    FSMC_Bank3->SR3 &= ~(FSMC_IT >> 3);
+  }
+  /* FSMC_Bank4_PCCARD*/
+  else
+  {
+    FSMC_Bank4->SR4 &= ~(FSMC_IT >> 3);
+  }
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 558 - 0
app/Libraries/src/stm32f2xx_gpio.c

@@ -0,0 +1,558 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_gpio.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the GPIO peripheral:           
+  *           - Initialization and Configuration
+  *           - GPIO Read and Write
+  *           - GPIO Alternate functions configuration
+  * 
+  *  @verbatim
+  *
+  *          ===================================================================
+  *                                 How to use this driver
+  *          ===================================================================       
+  *           1. Enable the GPIO AHB clock using the following function
+  *                RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+  *             
+  *           2. Configure the GPIO pin(s) using GPIO_Init()
+  *              Four possible configuration are available for each pin:
+  *                - Input: Floating, Pull-up, Pull-down.
+  *                - Output: Push-Pull (Pull-up, Pull-down or no Pull)
+  *                          Open Drain (Pull-up, Pull-down or no Pull).
+  *                  In output mode, the speed is configurable: 2 MHz, 25 MHz,
+  *                  50 MHz or 100 MHz.
+  *                - Alternate Function: Push-Pull (Pull-up, Pull-down or no Pull)
+  *                                      Open Drain (Pull-up, Pull-down or no Pull).
+  *                - Analog: required mode when a pin is to be used as ADC channel
+  *                          or DAC output.
+  * 
+  *          3- Peripherals alternate function:
+  *              - For ADC and DAC, configure the desired pin in analog mode using 
+  *                  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AN;
+  *              - For other peripherals (TIM, USART...):
+  *                 - Connect the pin to the desired peripherals' Alternate 
+  *                   Function (AF) using GPIO_PinAFConfig() function
+  *                 - Configure the desired pin in alternate function mode using
+  *                   GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
+  *                 - Select the type, pull-up/pull-down and output speed via 
+  *                   GPIO_PuPd, GPIO_OType and GPIO_Speed members
+  *                 - Call GPIO_Init() function
+  *        
+  *          4. To get the level of a pin configured in input mode use GPIO_ReadInputDataBit()
+  *          
+  *          5. To set/reset the level of a pin configured in output mode use
+  *             GPIO_SetBits()/GPIO_ResetBits()
+  *               
+  *          6. During and just after reset, the alternate functions are not 
+  *             active and the GPIO pins are configured in input floating mode
+  *             (except JTAG pins).
+  *
+  *          7. The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as 
+  *             general-purpose (PC14 and PC15, respectively) when the LSE
+  *             oscillator is off. The LSE has priority over the GPIO function.
+  *
+  *          8. The HSE oscillator pins OSC_IN/OSC_OUT can be used as 
+  *             general-purpose PH0 and PH1, respectively, when the HSE 
+  *             oscillator is off. The HSE has priority over the GPIO function.
+  *             
+  *  @endverbatim        
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_gpio.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup GPIO 
+  * @brief GPIO driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup GPIO_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup GPIO_Group1 Initialization and Configuration
+ *  @brief   Initialization and Configuration
+ *
+@verbatim   
+ ===============================================================================
+                        Initialization and Configuration
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the GPIOx peripheral registers to their default reset values.
+  * @note   By default, The GPIO pins are configured in input floating mode (except JTAG pins).
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @retval None
+  */
+void GPIO_DeInit(GPIO_TypeDef* GPIOx)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+
+  if (GPIOx == GPIOA)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);
+  }
+  else if (GPIOx == GPIOB)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, DISABLE);
+  }
+  else if (GPIOx == GPIOC)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, DISABLE);
+  }
+  else if (GPIOx == GPIOD)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, DISABLE);
+  }
+  else if (GPIOx == GPIOE)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, DISABLE);
+  }
+  else if (GPIOx == GPIOF)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, DISABLE);
+  }
+  else if (GPIOx == GPIOG)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, DISABLE);
+  }
+  else if (GPIOx == GPIOH)
+  {
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, ENABLE);
+    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, DISABLE);
+  }
+  else
+  {
+    if (GPIOx == GPIOI)
+    {
+      RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, ENABLE);
+      RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, DISABLE);
+    }
+  }
+}
+
+/**
+  * @brief  Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that contains
+  *         the configuration information for the specified GPIO peripheral.
+  * @retval None
+  */
+void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
+{
+  uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
+
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
+  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
+  assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));
+
+  /* -------------------------Configure the port pins---------------- */
+  /*-- GPIO Mode Configuration --*/
+  for (pinpos = 0x00; pinpos < 0x10; pinpos++)
+  {
+    pos = ((uint32_t)0x01) << pinpos;
+    /* Get the port pins position */
+    currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
+
+    if (currentpin == pos)
+    {
+      GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2));
+      GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));
+
+      if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
+      {
+        /* Check Speed mode parameters */
+        assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
+
+        /* Speed mode configuration */
+        GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));
+        GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));
+
+        /* Check Output mode parameters */
+        assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));
+
+        /* Output mode configuration*/
+        GPIOx->OTYPER  &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;
+        GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));
+      }
+
+      /* Pull-up Pull down resistor configuration*/
+      GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));
+      GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));
+    }
+  }
+}
+
+/**
+  * @brief  Fills each GPIO_InitStruct member with its default value.
+  * @param  GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will be initialized.
+  * @retval None
+  */
+void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
+{
+  /* Reset GPIO init structure parameters values */
+  GPIO_InitStruct->GPIO_Pin  = GPIO_Pin_All;
+  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;
+  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
+  GPIO_InitStruct->GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
+}
+
+/**
+  * @brief  Locks GPIO Pins configuration registers.
+  * @note   The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
+  *         GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
+  * @note   The configuration of the locked GPIO pins can no longer be modified
+  *         until the next reset.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bit to be locked.
+  *          This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
+  * @retval None
+  */
+void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  __IO uint32_t tmp = 0x00010000;
+
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+  tmp |= GPIO_Pin;
+  /* Set LCKK bit */
+  GPIOx->LCKR = tmp;
+  /* Reset LCKK bit */
+  GPIOx->LCKR =  GPIO_Pin;
+  /* Set LCKK bit */
+  GPIOx->LCKR = tmp;
+  /* Read LCKK bit*/
+  tmp = GPIOx->LCKR;
+  /* Read LCKK bit*/
+  tmp = GPIOx->LCKR;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup GPIO_Group2 GPIO Read and Write
+ *  @brief   GPIO Read and Write
+ *
+@verbatim   
+ ===============================================================================
+                              GPIO Read and Write
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Reads the specified input port pin.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bit to read.
+  *         This parameter can be GPIO_Pin_x where x can be (0..15).
+  * @retval The input port pin value.
+  */
+uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  uint8_t bitstatus = 0x00;
+
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
+
+  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
+  {
+    bitstatus = (uint8_t)Bit_SET;
+  }
+  else
+  {
+    bitstatus = (uint8_t)Bit_RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Reads the specified GPIO input data port.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @retval GPIO input data port value.
+  */
+uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+
+  return ((uint16_t)GPIOx->IDR);
+}
+
+/**
+  * @brief  Reads the specified output data port bit.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bit to read.
+  *          This parameter can be GPIO_Pin_x where x can be (0..15).
+  * @retval The output port pin value.
+  */
+uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  uint8_t bitstatus = 0x00;
+
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
+
+  if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
+  {
+    bitstatus = (uint8_t)Bit_SET;
+  }
+  else
+  {
+    bitstatus = (uint8_t)Bit_RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Reads the specified GPIO output data port.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @retval GPIO output data port value.
+  */
+uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+
+  return ((uint16_t)GPIOx->ODR);
+}
+
+/**
+  * @brief  Sets the selected data port bits.
+  * @note   This functions uses GPIOx_BSRR register to allow atomic read/modify 
+  *         accesses. In this way, there is no risk of an IRQ occurring between
+  *         the read and the modify access.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bits to be written.
+  *          This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
+  * @retval None
+  */
+void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+  GPIOx->BSRR = GPIO_Pin;
+}
+
+/**
+  * @brief  Clears the selected data port bits.
+  * @note   This functions uses GPIOx_BSRR register to allow atomic read/modify 
+  *         accesses. In this way, there is no risk of an IRQ occurring between
+  *         the read and the modify access.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bits to be written.
+  *          This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
+  * @retval None
+  */
+void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+  GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
+}
+
+/**
+  * @brief  Sets or clears the selected data port bit.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: specifies the port bit to be written.
+  *          This parameter can be one of GPIO_Pin_x where x can be (0..15).
+  * @param  BitVal: specifies the value to be written to the selected bit.
+  *          This parameter can be one of the BitAction enum values:
+  *            @arg Bit_RESET: to clear the port pin
+  *            @arg Bit_SET: to set the port pin
+  * @retval None
+  */
+void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
+  assert_param(IS_GPIO_BIT_ACTION(BitVal));
+
+  if (BitVal != Bit_RESET)
+  {
+    GPIOx->BSRR = GPIO_Pin;
+  }
+  else
+  {
+    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
+  }
+}
+
+/**
+  * @brief  Writes data to the specified GPIO data port.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  PortVal: specifies the value to be written to the port output data register.
+  * @retval None
+  */
+void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+
+  GPIOx->ODR = PortVal;
+}
+
+/**
+  * @brief  Toggles the specified GPIO pins..
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_Pin: Specifies the pins to be toggled.
+  * @retval None
+  */
+void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+
+  GPIOx->ODR ^= GPIO_Pin;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup GPIO_Group3 GPIO Alternate functions configuration function
+ *  @brief   GPIO Alternate functions configuration function
+ *
+@verbatim   
+ ===============================================================================
+               GPIO Alternate functions configuration function
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Changes the mapping of the specified pin.
+  * @param  GPIOx: where x can be (A..I) to select the GPIO peripheral.
+  * @param  GPIO_PinSource: specifies the pin for the Alternate function.
+  *         This parameter can be GPIO_PinSourcex where x can be (0..15).
+  * @param  GPIO_AFSelection: selects the pin to used as Alternate function.
+  *          This parameter can be one of the following values:
+  *            @arg GPIO_AF_RTC_50Hz: Connect RTC_50Hz pin to AF0 (default after reset) 
+  *            @arg GPIO_AF_MCO: Connect MCO pin (MCO1 and MCO2) to AF0 (default after reset) 
+  *            @arg GPIO_AF_TAMPER: Connect TAMPER pins (TAMPER_1 and TAMPER_2) to AF0 (default after reset) 
+  *            @arg GPIO_AF_SWJ: Connect SWJ pins (SWD and JTAG)to AF0 (default after reset) 
+  *            @arg GPIO_AF_TRACE: Connect TRACE pins to AF0 (default after reset)
+  *            @arg GPIO_AF_TIM1: Connect TIM1 pins to AF1
+  *            @arg GPIO_AF_TIM2: Connect TIM2 pins to AF1
+  *            @arg GPIO_AF_TIM3: Connect TIM3 pins to AF2
+  *            @arg GPIO_AF_TIM4: Connect TIM4 pins to AF2
+  *            @arg GPIO_AF_TIM5: Connect TIM5 pins to AF2
+  *            @arg GPIO_AF_TIM8: Connect TIM8 pins to AF3
+  *            @arg GPIO_AF_TIM9: Connect TIM9 pins to AF3
+  *            @arg GPIO_AF_TIM10: Connect TIM10 pins to AF3
+  *            @arg GPIO_AF_TIM11: Connect TIM11 pins to AF3
+  *            @arg GPIO_AF_I2C1: Connect I2C1 pins to AF4
+  *            @arg GPIO_AF_I2C2: Connect I2C2 pins to AF4
+  *            @arg GPIO_AF_I2C3: Connect I2C3 pins to AF4
+  *            @arg GPIO_AF_SPI1: Connect SPI1 pins to AF5
+  *            @arg GPIO_AF_SPI2: Connect SPI2/I2S2 pins to AF5
+  *            @arg GPIO_AF_SPI3: Connect SPI3/I2S3 pins to AF6
+  *            @arg GPIO_AF_USART1: Connect USART1 pins to AF7
+  *            @arg GPIO_AF_USART2: Connect USART2 pins to AF7
+  *            @arg GPIO_AF_USART3: Connect USART3 pins to AF7
+  *            @arg GPIO_AF_UART4: Connect UART4 pins to AF8
+  *            @arg GPIO_AF_UART5: Connect UART5 pins to AF8
+  *            @arg GPIO_AF_USART6: Connect USART6 pins to AF8
+  *            @arg GPIO_AF_CAN1: Connect CAN1 pins to AF9
+  *            @arg GPIO_AF_CAN2: Connect CAN2 pins to AF9
+  *            @arg GPIO_AF_TIM12: Connect TIM12 pins to AF9
+  *            @arg GPIO_AF_TIM13: Connect TIM13 pins to AF9
+  *            @arg GPIO_AF_TIM14: Connect TIM14 pins to AF9
+  *            @arg GPIO_AF_OTG_FS: Connect OTG_FS pins to AF10
+  *            @arg GPIO_AF_OTG_HS: Connect OTG_HS pins to AF10
+  *            @arg GPIO_AF_ETH: Connect ETHERNET pins to AF11
+  *            @arg GPIO_AF_FSMC: Connect FSMC pins to AF12
+  *            @arg GPIO_AF_OTG_HS_FS: Connect OTG HS (configured in FS) pins to AF12
+  *            @arg GPIO_AF_SDIO: Connect SDIO pins to AF12
+  *            @arg GPIO_AF_DCMI: Connect DCMI pins to AF13
+  *            @arg GPIO_AF_EVENTOUT: Connect EVENTOUT pins to AF15
+  * @retval None
+  */
+void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
+{
+  uint32_t temp = 0x00;
+  uint32_t temp_2 = 0x00;
+  
+  /* Check the parameters */
+  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
+  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
+  assert_param(IS_GPIO_AF(GPIO_AF));
+  
+  temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;
+  GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;
+  temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp;
+  GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2;
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 698 - 0
app/Libraries/src/stm32f2xx_hash.c

@@ -0,0 +1,698 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_hash.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the HASH / HMAC Processor (HASH) peripheral:           
+  *           - Initialization and Configuration functions
+  *           - Message Digest generation functions
+  *           - context swapping functions   
+  *           - DMA interface function       
+  *           - Interrupts and flags management       
+  *         
+  *  @verbatim
+  *                               
+  *          ===================================================================      
+  *                                   How to use this driver
+  *          ===================================================================
+  *          HASH operation : 
+  *          ----------------                   
+  *         1. Enable the HASH controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE) function.
+  *           
+  *         2. Initialise the HASH using HASH_Init() function. 
+  *               
+  *         3 . Reset the HASH processor core, so that the HASH will be ready 
+  *             to compute he message digest of a new message by using 
+  *             HASH_Reset() function.
+  *
+  *         4. Enable the HASH controller using the HASH_Cmd() function. 
+  *                
+  *         5. if using DMA for Data input transfer, Activate the DMA Request 
+  *            using HASH_DMACmd() function 
+  *                    
+  *         6. if DMA is not used for data transfer, use HASH_DataIn() function 
+  *            to enter data to IN FIFO.
+  *             
+  *          
+  *         7. Configure the Number of valid bits in last word of the message 
+  *            using HASH_SetLastWordValidBitsNbr() function.
+  *             
+  *         8. if the message length is not an exact multiple of 512 bits, 
+  *            then the function HASH_StartDigest() must be called to 
+  *            launch the computation of the final digest.     
+  *             
+  *         9. Once computed, the digest can be read using HASH_GetDigest() 
+  *            function.         
+  *                   
+  *        10. To control HASH events you can use one of the following 
+  *              two methods:
+  *               a- Check on HASH flags using the HASH_GetFlagStatus() function.  
+  *               b- Use HASH interrupts through the function HASH_ITConfig() at 
+  *                  initialization phase and HASH_GetITStatus() function into 
+  *                  interrupt routines in hashing phase.
+  *          After checking on a flag you should clear it using HASH_ClearFlag()
+  *          function. And after checking on an interrupt event you should 
+  *          clear it using HASH_ClearITPendingBit() function.     
+  *                     
+  *        11. Save and restore hash processor context using 
+  *            HASH_SaveContext() and HASH_RestoreContext() functions.     
+  *              
+  *
+  *            
+  *          HMAC operation : 
+  *          ----------------  
+  *          The HMAC algorithm is used for message authentication, by 
+  *          irreversibly binding the message being processed to a key chosen 
+  *          by the user. 
+  *          For HMAC specifications, refer to "HMAC: keyed-hashing for message 
+  *          authentication, H. Krawczyk, M. Bellare, R. Canetti, February 1997"
+  *          
+  *          Basically, the HMAC algorithm consists of two nested hash operations:
+  *          HMAC(message) = Hash[((key | pad) XOR 0x5C) | Hash(((key | pad) XOR 0x36) | message)]
+  *          where:
+  *          - "pad" is a sequence of zeroes needed to extend the key to the 
+  *                  length of the underlying hash function data block (that is 
+  *                  512 bits for both the SHA-1 and MD5 hash algorithms)
+  *          - "|"   represents the concatenation operator 
+  *          
+  *         
+  *         To compute the HMAC, four different phases are required:
+  *                    
+  *         1.  Initialise the HASH using HASH_Init() function to do HMAC 
+  *             operation. 
+  *                
+  *         2.  The key (to be used for the inner hash function) is then given 
+  *             to the core. This operation follows the same mechanism as the 
+  *             one used to send the message in the hash operation (that is, 
+  *             by HASH_DataIn() function and, finally, 
+  *             HASH_StartDigest() function.
+  *          
+  *         3.  Once the last word has been entered and computation has started, 
+  *             the hash processor elaborates the key. It is then ready to 
+  *             accept the message text using the same mechanism as the one 
+  *             used to send the message in the hash operation.
+  *       
+  *         4.  After the first hash round, the hash processor returns "ready" 
+  *             to indicate that it is ready to receive the key to be used for 
+  *             the outer hash function (normally, this key is the same as the 
+  *             one used for the inner hash function). When the last word of 
+  *             the key is entered and computation starts, the HMAC result is 
+  *             made available using HASH_GetDigest() function.
+  *               
+  *              
+  *  @endverbatim
+  *         
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_hash.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup HASH 
+  * @brief HASH driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/ 
+
+/** @defgroup HASH_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup HASH_Group1 Initialization and Configuration functions
+ *  @brief    Initialization and Configuration functions 
+ *
+@verbatim    
+ ===============================================================================
+                      Initialization and Configuration functions
+ ===============================================================================  
+  This section provides functions allowing to 
+   - Initialize the HASH peripheral
+   - Configure the HASH Processor 
+      - MD5/SHA1, 
+      - HASH/HMAC, 
+      - datatype 
+      - HMAC Key (if mode = HMAC)
+   - Reset the HASH Processor 
+   
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Deinitializes the HASH peripheral registers to their default reset values
+  * @param  None
+  * @retval None
+  */
+void HASH_DeInit(void)
+{
+  /* Enable HASH reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_HASH, ENABLE);
+  /* Release HASH from reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_HASH, DISABLE);
+}
+
+/**
+  * @brief  Initializes the HASH peripheral according to the specified parameters
+  *         in the HASH_InitStruct structure.
+  * @note   the hash processor is reset when calling this function so that the
+  *         HASH will be ready to compute the message digest of a new message.
+  *         There is no need to call HASH_Reset() function.           
+  * @param  HASH_InitStruct: pointer to a HASH_InitTypeDef structure that contains
+  *         the configuration information for the HASH peripheral.
+  * @note   The field HASH_HMACKeyType in HASH_InitTypeDef must be filled only 
+  *          if the algorithm mode is HMAC.       
+  * @retval None
+  */
+void HASH_Init(HASH_InitTypeDef* HASH_InitStruct)
+{
+  /* Check the parameters */
+  assert_param(IS_HASH_ALGOSELECTION(HASH_InitStruct->HASH_AlgoSelection));
+  assert_param(IS_HASH_DATATYPE(HASH_InitStruct->HASH_DataType));
+  assert_param(IS_HASH_ALGOMODE(HASH_InitStruct->HASH_AlgoMode));
+  
+  /* Configure the Algorithm used, algorithm mode and the datatype */
+  HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE);
+  HASH->CR |= (HASH_InitStruct->HASH_AlgoSelection | \
+               HASH_InitStruct->HASH_DataType | \
+               HASH_InitStruct->HASH_AlgoMode);
+  
+  /* if algorithm mode is HMAC, set the Key */  
+  if(HASH_InitStruct->HASH_AlgoMode == HASH_AlgoMode_HMAC) 
+  {
+    assert_param(IS_HASH_HMAC_KEYTYPE(HASH_InitStruct->HASH_HMACKeyType));
+    HASH->CR &= ~HASH_CR_LKEY;
+    HASH->CR |= HASH_InitStruct->HASH_HMACKeyType;
+  }
+
+  /* Reset the HASH processor core, so that the HASH will be ready to compute 
+     the message digest of a new message */
+  HASH->CR |= HASH_CR_INIT;  
+}
+
+/**
+  * @brief  Fills each HASH_InitStruct member with its default value.
+  * @param  HASH_InitStruct : pointer to a HASH_InitTypeDef structure which will
+  *          be initialized.  
+  *  @note  The default values set are : Processor mode is HASH, Algorithm selected is SHA1,
+  *          Data type selected is 32b and HMAC Key Type is short key.  
+  * @retval None
+  */
+void HASH_StructInit(HASH_InitTypeDef* HASH_InitStruct)
+{
+  /* Initialize the HASH_AlgoSelection member */
+  HASH_InitStruct->HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+
+  /* Initialize the HASH_AlgoMode member */
+  HASH_InitStruct->HASH_AlgoMode = HASH_AlgoMode_HASH;
+
+  /* Initialize the HASH_DataType member */
+  HASH_InitStruct->HASH_DataType = HASH_DataType_32b;
+
+  /* Initialize the HASH_HMACKeyType member */
+  HASH_InitStruct->HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+}
+
+/**
+  * @brief  Resets the HASH processor core, so that the HASH will be ready
+  *         to compute the message digest of a new message.
+  * @note   Calling this function will clear the HASH_SR_DCIS (Digest calculation 
+  *         completion interrupt status) bit corresponding to HASH_IT_DCI 
+  *         interrupt and HASH_FLAG_DCIS flag. 
+  * @param  None
+  * @retval None
+  */
+void HASH_Reset(void)
+{
+  /* Reset the HASH processor core */
+  HASH->CR |= HASH_CR_INIT;
+}
+/**
+  * @}
+  */
+ 
+/** @defgroup HASH_Group2 Message Digest generation functions
+ *  @brief    Message Digest generation functions
+ *
+@verbatim    
+ ===============================================================================
+                      Message Digest generation functions
+ ===============================================================================  
+  This section provides functions allowing the generation of message digest: 
+  - Push data in the IN FIFO : using HASH_DataIn()
+  - Get the number of words set in IN FIFO, use HASH_GetInFIFOWordsNbr()  
+  - set the last word valid bits number using HASH_SetLastWordValidBitsNbr() 
+  - start digest calculation : using HASH_StartDigest()
+  - Get the Digest message : using HASH_GetDigest()
+ 
+@endverbatim
+  * @{
+  */
+
+
+/**
+  * @brief  Configure the Number of valid bits in last word of the message
+  * @param  ValidNumber: Number of valid bits in last word of the message.
+  *           This parameter must be a number between 0 and 0x1F.
+  *             - 0x00: All 32 bits of the last data written are valid
+  *             - 0x01: Only bit [0] of the last data written is valid
+  *             - 0x02: Only bits[1:0] of the last data written are valid
+  *             - 0x03: Only bits[2:0] of the last data written are valid
+  *             - ...
+  *             - 0x1F: Only bits[30:0] of the last data written are valid    
+  * @note   The Number of valid bits must be set before to start the message 
+  *         digest competition (in Hash and HMAC) and key treatment(in HMAC).    
+  * @retval None
+  */
+void HASH_SetLastWordValidBitsNbr(uint16_t ValidNumber)
+{
+  /* Check the parameters */
+  assert_param(IS_HASH_VALIDBITSNUMBER(ValidNumber));
+  
+  /* Configure the Number of valid bits in last word of the message */
+  HASH->STR &= ~(HASH_STR_NBW);
+  HASH->STR |= ValidNumber;
+}
+
+/**
+  * @brief  Writes data in the Data Input FIFO
+  * @param  Data: new data of the message to be processed.
+  * @retval None
+  */
+void HASH_DataIn(uint32_t Data)
+{
+  /* Write in the DIN register a new data */
+  HASH->DIN = Data;
+}
+
+/**
+  * @brief  Returns the number of words already pushed into the IN FIFO.
+  * @param  None
+  * @retval The value of words already pushed into the IN FIFO.
+  */
+uint8_t HASH_GetInFIFOWordsNbr(void)
+{
+  /* Return the value of NBW bits */
+  return ((HASH->CR & HASH_CR_NBW) >> 8);
+}
+
+/**
+  * @brief  Provides the message digest result.
+  * @note   In MD5 mode, Data[4] filed of HASH_MsgDigest structure is not used
+  *         and is read as zero.  
+  * @param  HASH_MessageDigest: pointer to a HASH_MsgDigest structure which will 
+  *         hold the message digest result 
+  * @retval None
+  */
+void HASH_GetDigest(HASH_MsgDigest* HASH_MessageDigest)
+{
+  /* Get the data field */
+  HASH_MessageDigest->Data[0] = HASH->HR[0];
+  HASH_MessageDigest->Data[1] = HASH->HR[1];
+  HASH_MessageDigest->Data[2] = HASH->HR[2];
+  HASH_MessageDigest->Data[3] = HASH->HR[3];
+  HASH_MessageDigest->Data[4] = HASH->HR[4];
+}
+
+/**
+  * @brief  Starts the message padding and calculation of the final message     
+  * @param  None
+  * @retval None
+  */
+void HASH_StartDigest(void)
+{
+  /* Start the Digest calculation */
+  HASH->STR |= HASH_STR_DCAL;
+}
+/**
+  * @}
+  */
+
+/** @defgroup HASH_Group3 Context swapping functions
+ *  @brief   Context swapping functions
+ *
+@verbatim   
+ ===============================================================================
+                             Context swapping functions
+ ===============================================================================  
+
+  This section provides functions allowing to save and store HASH Context
+  
+  It is possible to interrupt a HASH/HMAC process to perform another processing 
+  with a higher priority, and to complete the interrupted process later on, when 
+  the higher priority task is complete. To do so, the context of the interrupted 
+  task must be saved from the HASH registers to memory, and then be restored 
+  from memory to the HASH registers.
+  
+  1. To save the current context, use HASH_SaveContext() function
+  2. To restore the saved context, use HASH_RestoreContext() function 
+  
+
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Save the Hash peripheral Context. 
+  * @note   The context can be saved only when no block is currently being 
+  *         processed. So user must wait for DINIS = 1 (the last block has been 
+  *         processed and the input FIFO is empty) or NBW != 0 (the FIFO is not 
+  *         full and no processing is ongoing).   
+  * @param  HASH_ContextSave: pointer to a HASH_Context structure that contains
+  *         the repository for current context.
+  * @retval None
+  */
+void HASH_SaveContext(HASH_Context* HASH_ContextSave)
+{
+  uint8_t i = 0;
+  
+  /* save context registers */
+  HASH_ContextSave->HASH_IMR = HASH->IMR;  
+  HASH_ContextSave->HASH_STR = HASH->STR;      
+  HASH_ContextSave->HASH_CR  = HASH->CR;     
+  for(i=0; i<=50;i++)
+  {
+     HASH_ContextSave->HASH_CSR[i] = HASH->CSR[i];
+  }   
+}
+
+/**
+  * @brief  Restore the Hash peripheral Context.  
+  * @note   After calling this function, user can restart the processing from the
+  *         point where it has been interrupted.  
+  * @param  HASH_ContextRestore: pointer to a HASH_Context structure that contains
+  *         the repository for saved context.
+  * @retval None
+  */
+void HASH_RestoreContext(HASH_Context* HASH_ContextRestore)  
+{
+  uint8_t i = 0;
+  
+  /* restore context registers */
+  HASH->IMR = HASH_ContextRestore->HASH_IMR;   
+  HASH->STR = HASH_ContextRestore->HASH_STR;     
+  HASH->CR = HASH_ContextRestore->HASH_CR;
+  
+  /* Initialize the hash processor */
+  HASH->CR |= HASH_CR_INIT; 
+  
+   /* continue restoring context registers */     
+  for(i=0; i<=50;i++)
+  {
+     HASH->CSR[i] = HASH_ContextRestore->HASH_CSR[i];
+  }   
+}
+/**
+  * @}
+  */
+
+/** @defgroup HASH_Group4 HASH's DMA interface Configuration function
+ *  @brief   HASH's DMA interface Configuration function 
+ *
+@verbatim   
+ ===============================================================================
+                   HASH's DMA interface Configuration function
+ ===============================================================================  
+
+  This section provides functions allowing to configure the DMA interface for 
+  HASH/ HMAC data input transfer.
+   
+  When the DMA mode is enabled (using the HASH_DMACmd() function), data can be 
+  sent to the IN FIFO using the DMA peripheral.
+
+
+
+@endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Enables or disables the HASH DMA interface.
+  * @note   The DMA is disabled by hardware after the end of transfer.
+  * @param  NewState: new state of the selected HASH DMA transfer request.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void HASH_DMACmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the HASH DMA request */
+    HASH->CR |= HASH_CR_DMAE;
+  }
+  else
+  {
+    /* Disable the HASH DMA request */
+    HASH->CR &= ~HASH_CR_DMAE;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup HASH_Group5 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                   Interrupts and flags management functions
+ ===============================================================================  
+
+  This section provides functions allowing to configure the HASH Interrupts and 
+  to get the status and clear flags and Interrupts pending bits.
+  
+  The HASH provides 2 Interrupts sources and 5 Flags:
+  
+  Flags :
+  ---------- 
+     1. HASH_FLAG_DINIS : set when 16 locations are free in the Data IN FIFO 
+                          which means that a  new block (512 bit) can be entered 
+                          into the input buffer.
+                          
+     2. HASH_FLAG_DCIS :  set when Digest calculation is complete
+      
+     3. HASH_FLAG_DMAS :  set when HASH's DMA interface is enabled (DMAE=1) or 
+                          a transfer is ongoing.
+                          This Flag is cleared only by hardware.
+                           
+     4. HASH_FLAG_BUSY :  set when The hash core is processing a block of data
+                          This Flag is cleared only by hardware. 
+                           
+     5. HASH_FLAG_DINNE : set when Data IN FIFO is not empty which means that 
+                          the Data IN FIFO contains at least one word of data.
+                          This Flag is cleared only by hardware.
+     
+  Interrupts :
+  ------------
+    
+   1. HASH_IT_DINI  : if enabled, this interrupt source is pending when 16 
+                      locations are free in the Data IN FIFO  which means that 
+                      a new block (512 bit) can be entered into the input buffer.
+                      This interrupt source is cleared using 
+                      HASH_ClearITPendingBit(HASH_IT_DINI) function.
+   
+   2. HASH_IT_DCI   : if enabled, this interrupt source is pending when Digest 
+                      calculation is complete.
+                      This interrupt source is cleared using 
+                      HASH_ClearITPendingBit(HASH_IT_DCI) function.
+
+  Managing the HASH controller events :
+  ------------------------------------ 
+  The user should identify which mode will be used in his application to manage 
+  the HASH controller events: Polling mode or Interrupt mode.
+  
+  1.  In the Polling Mode it is advised to use the following functions:
+      - HASH_GetFlagStatus() : to check if flags events occur. 
+      - HASH_ClearFlag()     : to clear the flags events.
+    
+  2.  In the Interrupt Mode it is advised to use the following functions:
+      - HASH_ITConfig()       : to enable or disable the interrupt source.
+      - HASH_GetITStatus()    : to check if Interrupt occurs.
+      - HASH_ClearITPendingBit() : to clear the Interrupt pending Bit 
+                                (corresponding Flag). 
+
+@endverbatim
+  * @{
+  */ 
+  
+/**
+  * @brief  Enables or disables the specified HASH interrupts.
+  * @param  HASH_IT: specifies the HASH interrupt source to be enabled or disabled.
+  *          This parameter can be any combination of the following values:
+  *            @arg HASH_IT_DINI: Data Input interrupt
+  *            @arg HASH_IT_DCI: Digest Calculation Completion Interrupt
+  * @param  NewState: new state of the specified HASH interrupt.
+  *           This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void HASH_ITConfig(uint8_t HASH_IT, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_HASH_IT(HASH_IT));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected HASH interrupt */
+    HASH->IMR |= HASH_IT;
+  }
+  else
+  {
+    /* Disable the selected HASH interrupt */
+    HASH->IMR &= (uint8_t) ~HASH_IT;
+  }
+}
+
+/**
+  * @brief  Checks whether the specified HASH flag is set or not.
+  * @param  HASH_FLAG: specifies the HASH flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg HASH_FLAG_DINIS: Data input interrupt status flag
+  *            @arg HASH_FLAG_DCIS: Digest calculation completion interrupt status flag
+  *            @arg HASH_FLAG_BUSY: Busy flag
+  *            @arg HASH_FLAG_DMAS: DMAS Status flag
+  *            @arg HASH_FLAG_DINNE: Data Input register (DIN) not empty status flag
+  * @retval The new state of HASH_FLAG (SET or RESET)
+  */
+FlagStatus HASH_GetFlagStatus(uint16_t HASH_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  uint32_t tempreg = 0;
+
+  /* Check the parameters */
+  assert_param(IS_HASH_GET_FLAG(HASH_FLAG));
+
+  /* check if the FLAG is in CR register */
+  if ((HASH_FLAG & HASH_FLAG_DINNE) != (uint16_t)RESET ) 
+  {
+    tempreg = HASH->CR;
+  }
+  else /* The FLAG is in SR register */
+  {
+    tempreg = HASH->SR;
+  }
+
+  /* Check the status of the specified HASH flag */
+  if ((tempreg & HASH_FLAG) != (uint16_t)RESET)
+  {
+    /* HASH is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* HASH_FLAG is reset */
+    bitstatus = RESET;
+  }
+
+  /* Return the HASH_FLAG status */
+  return  bitstatus;
+}
+/**
+  * @brief  Clears the HASH flags.
+  * @param  HASH_FLAG: specifies the flag to clear. 
+  *          This parameter can be any combination of the following values:
+  *            @arg HASH_FLAG_DINIS: Data Input Flag
+  *            @arg HASH_FLAG_DCIS: Digest Calculation Completion Flag                       
+  * @retval None
+  */
+void HASH_ClearFlag(uint16_t HASH_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_HASH_CLEAR_FLAG(HASH_FLAG));
+  
+  /* Clear the selected HASH flags */
+  HASH->SR = ~(uint32_t)HASH_FLAG;
+}
+/**
+  * @brief  Checks whether the specified HASH interrupt has occurred or not.
+  * @param  HASH_IT: specifies the HASH interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg HASH_IT_DINI: Data Input interrupt
+  *            @arg HASH_IT_DCI: Digest Calculation Completion Interrupt
+  * @retval The new state of HASH_IT (SET or RESET).
+  */
+ITStatus HASH_GetITStatus(uint8_t HASH_IT)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t tmpreg = 0;
+
+  /* Check the parameters */
+  assert_param(IS_HASH_GET_IT(HASH_IT));  
+
+
+  /* Check the status of the specified HASH interrupt */
+  tmpreg =  HASH->SR;
+
+  if (((HASH->IMR & tmpreg) & HASH_IT) != RESET)
+  {
+    /* HASH_IT is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* HASH_IT is reset */
+    bitstatus = RESET;
+  }
+  /* Return the HASH_IT status */
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the HASH interrupt pending bit(s).
+  * @param  HASH_IT: specifies the HASH interrupt pending bit(s) to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg HASH_IT_DINI: Data Input interrupt
+  *            @arg HASH_IT_DCI: Digest Calculation Completion Interrupt
+  * @retval None
+  */
+void HASH_ClearITPendingBit(uint8_t HASH_IT)
+{
+  /* Check the parameters */
+  assert_param(IS_HASH_IT(HASH_IT));
+
+  /* Clear the selected HASH interrupt pending bit */
+  HASH->SR = (uint8_t)~HASH_IT;
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

+ 312 - 0
app/Libraries/src/stm32f2xx_hash_md5.c

@@ -0,0 +1,312 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_hash_md5.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides high level functions to compute the HASH MD5 and
+  *          HMAC MD5 Digest of an input message.
+  *          It uses the stm32f2xx_hash.c/.h drivers to access the STM32F2xx HASH
+  *          peripheral.
+  *
+  *  @verbatim
+  *    
+  *          ===================================================================
+  *                                   How to use this driver
+  *          ===================================================================
+  *          1. Enable The HASH controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); function.
+  *
+  *          2. Calculate the HASH MD5 Digest using HASH_MD5() function.
+  *
+  *          3. Calculate the HMAC MD5 Digest using HMAC_MD5() function.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_hash.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup HASH 
+  * @brief HASH driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define MD5BUSY_TIMEOUT    ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup HASH_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup HASH_Group7 High Level MD5 functions
+ *  @brief   High Level MD5 Hash and HMAC functions 
+ *
+@verbatim   
+ ===============================================================================
+                          High Level MD5 Hash and HMAC functions
+ ===============================================================================
+
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Compute the HASH MD5 digest.
+  * @param  Input: pointer to the Input buffer to be treated.
+  * @param  Ilen: length of the Input buffer.
+  * @param  Output: the returned digest
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: digest computation done
+  *          - ERROR: digest computation failed
+  */
+ErrorStatus HASH_MD5(uint8_t *Input, uint32_t Ilen, uint8_t Output[16])
+{
+  HASH_InitTypeDef MD5_HASH_InitStructure;
+  HASH_MsgDigest MD5_MessageDigest;
+  __IO uint16_t nbvalidbitsdata = 0;
+  uint32_t i = 0;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+
+
+  /* Number of valid bits in last word of the Input data */
+  nbvalidbitsdata = 8 * (Ilen % 4);
+
+  /* HASH peripheral initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
+  MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
+  MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  HASH_Init(&MD5_HASH_InitStructure);
+
+  /* Configure the number of valid bits in last word of the data */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+  /* Write the Input block in the IN FIFO */
+  for(i=0; i<Ilen; i+=4)
+  {
+    HASH_DataIn(*(uint32_t*)inputaddr);
+    inputaddr+=4;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  do
+  {
+    busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+    counter++;
+  }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
+
+  if (busystatus != RESET)
+  {
+     status = ERROR;
+  }
+  else
+  {
+    /* Read the message digest */
+    HASH_GetDigest(&MD5_MessageDigest);
+    *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[0]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[1]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[2]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[3]);
+  }
+  return status; 
+}
+
+/**
+  * @brief  Compute the HMAC MD5 digest.
+  * @param  Key: pointer to the Key used for HMAC.
+  * @param  Keylen: length of the Key used for HMAC.
+  * @param  Input: pointer to the Input buffer to be treated.
+  * @param  Ilen: length of the Input buffer.
+  * @param  Output: the returned digest  
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: digest computation done
+  *          - ERROR: digest computation failed
+  */
+ErrorStatus HMAC_MD5(uint8_t *Key, uint32_t Keylen, uint8_t *Input, 
+                     uint32_t Ilen, uint8_t Output[16])
+{
+  HASH_InitTypeDef MD5_HASH_InitStructure;
+  HASH_MsgDigest MD5_MessageDigest;
+  __IO uint16_t nbvalidbitsdata = 0;
+  __IO uint16_t nbvalidbitskey = 0;
+  uint32_t i = 0;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+
+  /* Number of valid bits in last word of the Input data */
+  nbvalidbitsdata = 8 * (Ilen % 4);
+
+  /* Number of valid bits in last word of the Key */
+  nbvalidbitskey = 8 * (Keylen % 4);
+   
+  /* HASH peripheral initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
+  MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
+  MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  if(Keylen > 64)
+  {
+    /* HMAC long Key */
+    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
+  }
+  else
+  {
+    /* HMAC short Key */
+    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+  }
+  HASH_Init(&MD5_HASH_InitStructure);
+
+  /* Configure the number of valid bits in last word of the Key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i=0; i<Keylen; i+=4)
+  {
+    HASH_DataIn(*(uint32_t*)keyaddr);
+    keyaddr+=4;
+  }
+  
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  do
+  {
+    busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+    counter++;
+  }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
+
+  if (busystatus != RESET)
+  {
+     status = ERROR;
+  }
+  else
+  {
+    /* Configure the number of valid bits in last word of the Input data */
+    HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+    /* Write the Input block in the IN FIFO */
+    for(i=0; i<Ilen; i+=4)
+    {
+      HASH_DataIn(*(uint32_t*)inputaddr);
+      inputaddr+=4;
+    }
+
+    /* Start the HASH processor */
+    HASH_StartDigest();
+
+    /* wait until the Busy flag is RESET */
+    counter =0;
+    do
+    {
+       busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+       counter++;
+    }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+    {
+      status = ERROR;
+    }
+    else
+    {  
+      /* Configure the number of valid bits in last word of the Key */
+      HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+      /* Write the Key */
+      keyaddr = (uint32_t)Key;
+      for(i=0; i<Keylen; i+=4)
+      {
+        HASH_DataIn(*(uint32_t*)keyaddr);
+        keyaddr+=4;
+      }
+  
+       /* Start the HASH processor */
+       HASH_StartDigest();
+
+       /* wait until the Busy flag is RESET */
+       counter =0;
+       do
+       {
+          busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+          counter++;
+      }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
+
+      if (busystatus != RESET)
+      {
+         status = ERROR;
+      }
+      else
+      {
+         /* Read the message digest */
+         HASH_GetDigest(&MD5_MessageDigest);
+         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[0]);
+         outputaddr+=4;
+         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[1]);
+         outputaddr+=4;
+         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[2]);
+         outputaddr+=4;
+         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[3]);
+      }
+    }
+  }
+  return status;  
+}
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+

+ 315 - 0
app/Libraries/src/stm32f2xx_hash_sha1.c

@@ -0,0 +1,315 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_hash_sha1.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides high level functions to compute the HASH SHA1 and
+  *          HMAC SHA1 Digest of an input message.
+  *          It uses the stm32f2xx_hash.c/.h drivers to access the STM32F2xx HASH
+  *          peripheral.
+  *
+  *  @verbatim
+  * 
+  *          ===================================================================
+  *                                   How to use this driver
+  *          ===================================================================
+  *          1. Enable The HASH controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); function.
+  *
+  *          2. Calculate the HASH SHA1 Digest using HASH_SHA1() function.
+  *
+  *          3. Calculate the HMAC SHA1 Digest using HMAC_SHA1() function.
+  *
+  *  @endverbatim
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_hash.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup HASH 
+  * @brief HASH driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define SHA1BUSY_TIMEOUT    ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup HASH_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup HASH_Group6 High Level SHA1 functions
+ *  @brief   High Level SHA1 Hash and HMAC functions 
+ *
+@verbatim   
+ ===============================================================================
+                          High Level SHA1 Hash and HMAC functions
+ ===============================================================================
+
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Compute the HASH SHA1 digest.
+  * @param  Input: pointer to the Input buffer to be treated.
+  * @param  Ilen: length of the Input buffer.
+  * @param  Output: the returned digest
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: digest computation done
+  *          - ERROR: digest computation failed
+  */
+ErrorStatus HASH_SHA1(uint8_t *Input, uint32_t Ilen, uint8_t Output[20])
+{
+  HASH_InitTypeDef SHA1_HASH_InitStructure;
+  HASH_MsgDigest SHA1_MessageDigest;
+  __IO uint16_t nbvalidbitsdata = 0;
+  uint32_t i = 0;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+
+  /* Number of valid bits in last word of the Input data */
+  nbvalidbitsdata = 8 * (Ilen % 4);
+
+  /* HASH peripheral initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+  SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
+  SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  HASH_Init(&SHA1_HASH_InitStructure);
+
+  /* Configure the number of valid bits in last word of the data */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+  /* Write the Input block in the IN FIFO */
+  for(i=0; i<Ilen; i+=4)
+  {
+    HASH_DataIn(*(uint32_t*)inputaddr);
+    inputaddr+=4;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  do
+  {
+    busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+    counter++;
+  }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+  if (busystatus != RESET)
+  {
+     status = ERROR;
+  }
+  else
+  {
+    /* Read the message digest */
+    HASH_GetDigest(&SHA1_MessageDigest);
+    *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[0]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[1]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[2]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[3]);
+    outputaddr+=4;
+    *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[4]);
+  }
+  return status;
+}
+
+/**
+  * @brief  Compute the HMAC SHA1 digest.
+  * @param  Key: pointer to the Key used for HMAC.
+  * @param  Keylen: length of the Key used for HMAC.  
+  * @param  Input: pointer to the Input buffer to be treated.
+  * @param  Ilen: length of the Input buffer.
+  * @param  Output: the returned digest
+  * @retval An ErrorStatus enumeration value:
+  *          - SUCCESS: digest computation done
+  *          - ERROR: digest computation failed
+  */
+ErrorStatus HMAC_SHA1(uint8_t *Key, uint32_t Keylen, uint8_t *Input,
+                      uint32_t Ilen, uint8_t Output[20])
+{
+  HASH_InitTypeDef SHA1_HASH_InitStructure;
+  HASH_MsgDigest SHA1_MessageDigest;
+  __IO uint16_t nbvalidbitsdata = 0;
+  __IO uint16_t nbvalidbitskey = 0;
+  uint32_t i = 0;
+  __IO uint32_t counter = 0;
+  uint32_t busystatus = 0;
+  ErrorStatus status = SUCCESS;
+  uint32_t keyaddr    = (uint32_t)Key;
+  uint32_t inputaddr  = (uint32_t)Input;
+  uint32_t outputaddr = (uint32_t)Output;
+
+  /* Number of valid bits in last word of the Input data */
+  nbvalidbitsdata = 8 * (Ilen % 4);
+
+  /* Number of valid bits in last word of the Key */
+  nbvalidbitskey = 8 * (Keylen % 4);
+
+  /* HASH peripheral initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+  SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
+  SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  if(Keylen > 64)
+  {
+    /* HMAC long Key */
+    SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
+  }
+  else
+  {
+    /* HMAC short Key */
+    SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+  }
+  HASH_Init(&SHA1_HASH_InitStructure);
+
+  /* Configure the number of valid bits in last word of the Key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i=0; i<Keylen; i+=4)
+  {
+    HASH_DataIn(*(uint32_t*)keyaddr);
+    keyaddr+=4;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  do
+  {
+    busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+    counter++;
+  }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+  if (busystatus != RESET)
+  {
+     status = ERROR;
+  }
+  else
+  {
+    /* Configure the number of valid bits in last word of the Input data */
+    HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+    /* Write the Input block in the IN FIFO */
+    for(i=0; i<Ilen; i+=4)
+    {
+      HASH_DataIn(*(uint32_t*)inputaddr);
+      inputaddr+=4;
+    }
+
+    /* Start the HASH processor */
+    HASH_StartDigest();
+
+
+    /* wait until the Busy flag is RESET */
+    counter =0;
+    do
+    {
+      busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+      counter++;
+    }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+    if (busystatus != RESET)
+    {
+      status = ERROR;
+    }
+    else
+    {  
+      /* Configure the number of valid bits in last word of the Key */
+      HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+      /* Write the Key */
+      keyaddr = (uint32_t)Key;
+      for(i=0; i<Keylen; i+=4)
+      {
+        HASH_DataIn(*(uint32_t*)keyaddr);
+        keyaddr+=4;
+      }
+
+      /* Start the HASH processor */
+      HASH_StartDigest();
+
+      /* wait until the Busy flag is RESET */
+      counter =0;
+      do
+      {
+        busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+        counter++;
+      }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+      if (busystatus != RESET)
+      {
+        status = ERROR;
+      }
+      else
+      {
+        /* Read the message digest */
+        HASH_GetDigest(&SHA1_MessageDigest);
+        *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[0]);
+        outputaddr+=4;
+        *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[1]);
+        outputaddr+=4;
+        *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[2]);
+        outputaddr+=4;
+        *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[3]);
+        outputaddr+=4;
+        *(uint32_t*)(outputaddr)  = __REV(SHA1_MessageDigest.Data[4]);
+      }
+    }  
+  }
+  return status;  
+}
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1402 - 0
app/Libraries/src/stm32f2xx_i2c.c


+ 261 - 0
app/Libraries/src/stm32f2xx_iwdg.c

@@ -0,0 +1,261 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_iwdg.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the Independent watchdog (IWDG) peripheral:           
+  *           - Prescaler and Counter configuration
+  *           - IWDG activation
+  *           - Flag management
+  *
+  *  @verbatim  
+  *  
+  *          ===================================================================
+  *                                     IWDG features
+  *          ===================================================================
+  *    
+  *          The IWDG can be started by either software or hardware (configurable
+  *          through option byte).
+  *            
+  *          The IWDG is clocked by its own dedicated low-speed clock (LSI) and
+  *          thus stays active even if the main clock fails.
+  *          Once the IWDG is started, the LSI is forced ON and cannot be disabled
+  *          (LSI cannot be disabled too), and the counter starts counting down from 
+  *          the reset value of 0xFFF. When it reaches the end of count value (0x000)
+  *          a system reset is generated.
+  *          The IWDG counter should be reloaded at regular intervals to prevent
+  *          an MCU reset.
+  *                           
+  *          The IWDG is implemented in the VDD voltage domain that is still functional
+  *          in STOP and STANDBY mode (IWDG reset can wake-up from STANDBY).          
+  *            
+  *          IWDGRST flag in RCC_CSR register can be used to inform when a IWDG
+  *          reset occurs.
+  *            
+  *          Min-max timeout value @32KHz (LSI): ~125us / ~32.7s
+  *          The IWDG timeout may vary due to LSI frequency dispersion. STM32F2xx
+  *          devices provide the capability to measure the LSI frequency (LSI clock
+  *          connected internally to TIM5 CH4 input capture). The measured value
+  *          can be used to have an IWDG timeout with an acceptable accuracy. 
+  *          For more information, please refer to the STM32F2xx Reference manual
+  *          
+  *                            
+  *          ===================================================================
+  *                                 How to use this driver
+  *          ===================================================================
+  *          1. Enable write access to IWDG_PR and IWDG_RLR registers using
+  *             IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable) function
+  *               
+  *          2. Configure the IWDG prescaler using IWDG_SetPrescaler() function
+  *            
+  *          3. Configure the IWDG counter value using IWDG_SetReload() function.
+  *             This value will be loaded in the IWDG counter each time the counter
+  *             is reloaded, then the IWDG will start counting down from this value.
+  *            
+  *          4. Start the IWDG using IWDG_Enable() function, when the IWDG is used
+  *             in software mode (no need to enable the LSI, it will be enabled
+  *             by hardware)
+  *             
+  *          5. Then the application program must reload the IWDG counter at regular
+  *             intervals during normal operation to prevent an MCU reset, using
+  *             IWDG_ReloadCounter() function.      
+  *          
+  *  @endverbatim
+  *    
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_iwdg.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup IWDG 
+  * @brief IWDG driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* KR register bit mask */
+#define KR_KEY_RELOAD    ((uint16_t)0xAAAA)
+#define KR_KEY_ENABLE    ((uint16_t)0xCCCC)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup IWDG_Private_Functions
+  * @{
+  */
+
+/** @defgroup IWDG_Group1 Prescaler and Counter configuration functions
+ *  @brief   Prescaler and Counter configuration functions
+ *
+@verbatim   
+ ===============================================================================
+                  Prescaler and Counter configuration functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables write access to IWDG_PR and IWDG_RLR registers.
+  * @param  IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers.
+  *          This parameter can be one of the following values:
+  *            @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers
+  *            @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers
+  * @retval None
+  */
+void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
+{
+  /* Check the parameters */
+  assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));
+  IWDG->KR = IWDG_WriteAccess;
+}
+
+/**
+  * @brief  Sets IWDG Prescaler value.
+  * @param  IWDG_Prescaler: specifies the IWDG Prescaler value.
+  *          This parameter can be one of the following values:
+  *            @arg IWDG_Prescaler_4: IWDG prescaler set to 4
+  *            @arg IWDG_Prescaler_8: IWDG prescaler set to 8
+  *            @arg IWDG_Prescaler_16: IWDG prescaler set to 16
+  *            @arg IWDG_Prescaler_32: IWDG prescaler set to 32
+  *            @arg IWDG_Prescaler_64: IWDG prescaler set to 64
+  *            @arg IWDG_Prescaler_128: IWDG prescaler set to 128
+  *            @arg IWDG_Prescaler_256: IWDG prescaler set to 256
+  * @retval None
+  */
+void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
+{
+  /* Check the parameters */
+  assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));
+  IWDG->PR = IWDG_Prescaler;
+}
+
+/**
+  * @brief  Sets IWDG Reload value.
+  * @param  Reload: specifies the IWDG Reload value.
+  *          This parameter must be a number between 0 and 0x0FFF.
+  * @retval None
+  */
+void IWDG_SetReload(uint16_t Reload)
+{
+  /* Check the parameters */
+  assert_param(IS_IWDG_RELOAD(Reload));
+  IWDG->RLR = Reload;
+}
+
+/**
+  * @brief  Reloads IWDG counter with value defined in the reload register
+  *         (write access to IWDG_PR and IWDG_RLR registers disabled).
+  * @param  None
+  * @retval None
+  */
+void IWDG_ReloadCounter(void)
+{
+  IWDG->KR = KR_KEY_RELOAD;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup IWDG_Group2 IWDG activation function
+ *  @brief   IWDG activation function 
+ *
+@verbatim   
+ ===============================================================================
+                          IWDG activation function
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled).
+  * @param  None
+  * @retval None
+  */
+void IWDG_Enable(void)
+{
+  IWDG->KR = KR_KEY_ENABLE;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup IWDG_Group3 Flag management function 
+ *  @brief  Flag management function  
+ *
+@verbatim   
+ ===============================================================================
+                            Flag management function 
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Checks whether the specified IWDG flag is set or not.
+  * @param  IWDG_FLAG: specifies the flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg IWDG_FLAG_PVU: Prescaler Value Update on going
+  *            @arg IWDG_FLAG_RVU: Reload Value Update on going
+  * @retval The new state of IWDG_FLAG (SET or RESET).
+  */
+FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_IWDG_FLAG(IWDG_FLAG));
+  if ((IWDG->SR & IWDG_FLAG) != (uint32_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  /* Return the flag status */
+  return bitstatus;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 612 - 0
app/Libraries/src/stm32f2xx_pwr.c

@@ -0,0 +1,612 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_pwr.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the Power Controller (PWR) peripheral:           
+  *           - Backup Domain Access
+  *           - PVD configuration
+  *           - WakeUp pin configuration
+  *           - Backup Regulator configuration
+  *           - FLASH Power Down configuration
+  *           - Low Power modes configuration
+  *           - Flags management
+  *               
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_pwr.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup PWR 
+  * @brief PWR driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* --------- PWR registers bit address in the alias region ---------- */
+#define PWR_OFFSET               (PWR_BASE - PERIPH_BASE)
+
+/* --- CR Register ---*/
+
+/* Alias word address of DBP bit */
+#define CR_OFFSET                (PWR_OFFSET + 0x00)
+#define DBP_BitNumber            0x08
+#define CR_DBP_BB                (PERIPH_BB_BASE + (CR_OFFSET * 32) + (DBP_BitNumber * 4))
+
+/* Alias word address of PVDE bit */
+#define PVDE_BitNumber           0x04
+#define CR_PVDE_BB               (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PVDE_BitNumber * 4))
+
+/* Alias word address of FPDS bit */
+#define FPDS_BitNumber           0x09
+#define CR_FPDS_BB               (PERIPH_BB_BASE + (CR_OFFSET * 32) + (FPDS_BitNumber * 4))
+
+/* --- CSR Register ---*/
+
+/* Alias word address of EWUP bit */
+#define CSR_OFFSET               (PWR_OFFSET + 0x04)
+#define EWUP_BitNumber           0x08
+#define CSR_EWUP_BB              (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (EWUP_BitNumber * 4))
+
+/* Alias word address of BRE bit */
+#define BRE_BitNumber            0x09
+#define CSR_BRE_BB              (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (BRE_BitNumber * 4))
+
+/* ------------------ PWR registers bit mask ------------------------ */
+
+/* CR register bit mask */
+#define CR_DS_MASK               ((uint32_t)0xFFFFFFFC)
+#define CR_PLS_MASK              ((uint32_t)0xFFFFFF1F)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup PWR_Private_Functions
+  * @{
+  */
+
+/** @defgroup PWR_Group1 Backup Domain Access function 
+ *  @brief   Backup Domain Access function  
+ *
+@verbatim   
+ ===============================================================================
+                            Backup Domain Access function 
+ ===============================================================================  
+
+  After reset, the backup domain (RTC registers, RTC backup data 
+  registers and backup SRAM) is protected against possible unwanted 
+  write accesses. 
+  To enable access to the RTC Domain and RTC registers, proceed as follows:
+    - Enable the Power Controller (PWR) APB1 interface clock using the
+      RCC_APB1PeriphClockCmd() function.
+    - Enable access to RTC domain using the PWR_BackupAccessCmd() function.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the PWR peripheral registers to their default reset values.     
+  * @param  None
+  * @retval None
+  */
+void PWR_DeInit(void)
+{
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE);
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE);
+}
+
+/**
+  * @brief  Enables or disables access to the backup domain (RTC registers, RTC 
+  *         backup data registers and backup SRAM).
+  * @note   If the HSE divided by 2, 3, ..31 is used as the RTC clock, the 
+  *         Backup Domain Access should be kept enabled.
+  * @param  NewState: new state of the access to the backup domain.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void PWR_BackupAccessCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  *(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group2 PVD configuration functions
+ *  @brief   PVD configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                           PVD configuration functions
+ ===============================================================================  
+
+ - The PVD is used to monitor the VDD power supply by comparing it to a threshold
+   selected by the PVD Level (PLS[2:0] bits in the PWR_CR).
+ - A PVDO flag is available to indicate if VDD/VDDA is higher or lower than the 
+   PVD threshold. This event is internally connected to the EXTI line16
+   and can generate an interrupt if enabled through the EXTI registers.
+ - The PVD is stopped in Standby mode.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Configures the voltage threshold detected by the Power Voltage Detector(PVD).
+  * @param  PWR_PVDLevel: specifies the PVD detection level
+  *          This parameter can be one of the following values:
+  *            @arg PWR_PVDLevel_0
+  *            @arg PWR_PVDLevel_1
+  *            @arg PWR_PVDLevel_2
+  *            @arg PWR_PVDLevel_3
+  *            @arg PWR_PVDLevel_4
+  *            @arg PWR_PVDLevel_5
+  *            @arg PWR_PVDLevel_6
+  *            @arg PWR_PVDLevel_7
+  * @note   Refer to the electrical characteristics of your device datasheet for
+  *         more details about the voltage threshold corresponding to each 
+  *         detection level. 
+  * @retval None
+  */
+void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel)
+{
+  uint32_t tmpreg = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel));
+  
+  tmpreg = PWR->CR;
+  
+  /* Clear PLS[7:5] bits */
+  tmpreg &= CR_PLS_MASK;
+  
+  /* Set PLS[7:5] bits according to PWR_PVDLevel value */
+  tmpreg |= PWR_PVDLevel;
+  
+  /* Store the new value */
+  PWR->CR = tmpreg;
+}
+
+/**
+  * @brief  Enables or disables the Power Voltage Detector(PVD).
+  * @param  NewState: new state of the PVD.
+  *         This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void PWR_PVDCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  
+  *(__IO uint32_t *) CR_PVDE_BB = (uint32_t)NewState;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group3 WakeUp pin configuration functions
+ *  @brief   WakeUp pin configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                    WakeUp pin configuration functions
+ ===============================================================================  
+
+ - WakeUp pin is used to wakeup the system from Standby mode. This pin is 
+   forced in input pull down configuration and is active on rising edges.
+ - There is only one WakeUp pin: WakeUp Pin 1 on PA.00.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the WakeUp Pin functionality.
+  * @param  NewState: new state of the WakeUp Pin functionality.
+  *         This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void PWR_WakeUpPinCmd(FunctionalState NewState)
+{
+  /* Check the parameters */  
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  *(__IO uint32_t *) CSR_EWUP_BB = (uint32_t)NewState;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group4 Backup Regulator configuration functions
+ *  @brief   Backup Regulator configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                    Backup Regulator configuration functions
+ ===============================================================================  
+
+ - The backup domain includes 4 Kbytes of backup SRAM accessible only from the 
+   CPU, and address in 32-bit, 16-bit or 8-bit mode. Its content is retained 
+   even in Standby or VBAT mode when the low power backup regulator is enabled. 
+   It can be considered as an internal EEPROM when VBAT is always present.
+   You can use the PWR_BackupRegulatorCmd() function to enable the low power
+   backup regulator and use the PWR_GetFlagStatus(PWR_FLAG_BRR) to check if it is
+   ready or not. 
+
+ - When the backup domain is supplied by VDD (analog switch connected to VDD) 
+   the backup SRAM is powered from VDD which replaces the VBAT power supply to 
+   save battery life.
+
+ - The backup SRAM is not mass erased by an tamper event. It is read protected 
+   to prevent confidential data, such as cryptographic private key, from being 
+   accessed. The backup SRAM can be erased only through the Flash interface when
+   a protection level change from level 1 to level 0 is requested. 
+   Refer to the description of Read protection (RDP) in the Flash programming manual.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the Backup Regulator.
+  * @param  NewState: new state of the Backup Regulator.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void PWR_BackupRegulatorCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  *(__IO uint32_t *) CSR_BRE_BB = (uint32_t)NewState;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group5 FLASH Power Down configuration functions
+ *  @brief   FLASH Power Down configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                     FLASH Power Down configuration functions
+ ===============================================================================  
+
+ - By setting the FPDS bit in the PWR_CR register by using the PWR_FlashPowerDownCmd()
+   function, the Flash memory also enters power down mode when the device enters 
+   Stop mode. When the Flash memory is in power down mode, an additional startup 
+   delay is incurred when waking up from Stop mode.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the Flash Power Down in STOP mode.
+  * @param  NewState: new state of the Flash power mode.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void PWR_FlashPowerDownCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  *(__IO uint32_t *) CR_FPDS_BB = (uint32_t)NewState;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group6 Low Power modes configuration functions
+ *  @brief   Low Power modes configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+                    Low Power modes configuration functions
+ ===============================================================================  
+
+  The devices feature 3 low-power modes:
+   - Sleep mode: Cortex-M3 core stopped, peripherals kept running.
+   - Stop mode: all clocks are stopped, regulator running, regulator in low power mode
+   - Standby mode: 1.2V domain powered off.
+   
+   Sleep mode
+   ===========
+    - Entry:
+      - The Sleep mode is entered by using the __WFI() or __WFE() functions.
+    - Exit:
+      - Any peripheral interrupt acknowledged by the nested vectored interrupt 
+        controller (NVIC) can wake up the device from Sleep mode.
+
+   Stop mode
+   ==========
+   In Stop mode, all clocks in the 1.2V domain are stopped, the PLL, the HSI,
+   and the HSE RC oscillators are disabled. Internal SRAM and register contents 
+   are preserved.
+   The voltage regulator can be configured either in normal or low-power mode.
+   To minimize the consumption In Stop mode, FLASH can be powered off before 
+   entering the Stop mode. It can be switched on again by software after exiting 
+   the Stop mode using the PWR_FlashPowerDownCmd() function. 
+   
+    - Entry:
+      - The Stop mode is entered using the PWR_EnterSTOPMode(PWR_Regulator_LowPower,) 
+        function with regulator in LowPower or with Regulator ON.
+    - Exit:
+      - Any EXTI Line (Internal or External) configured in Interrupt/Event mode.
+      
+   Standby mode
+   ============
+   The Standby mode allows to achieve the lowest power consumption. It is based 
+   on the Cortex-M3 deepsleep mode, with the voltage regulator disabled. 
+   The 1.2V domain is consequently powered off. The PLL, the HSI oscillator and 
+   the HSE oscillator are also switched off. SRAM and register contents are lost 
+   except for the RTC registers, RTC backup registers, backup SRAM and Standby 
+   circuitry.
+   
+   The voltage regulator is OFF.
+      
+    - Entry:
+      - The Standby mode is entered using the PWR_EnterSTANDBYMode() function.
+    - Exit:
+      - WKUP pin rising edge, RTC alarm (Alarm A and Alarm B), RTC wakeup,
+        tamper event, time-stamp event, external reset in NRST pin, IWDG reset.              
+
+   Auto-wakeup (AWU) from low-power mode
+   =====================================
+   The MCU can be woken up from low-power mode by an RTC Alarm event, an RTC 
+   Wakeup event, a tamper event, a time-stamp event, or a comparator event, 
+   without depending on an external interrupt (Auto-wakeup mode).
+
+   - RTC auto-wakeup (AWU) from the Stop mode
+     ----------------------------------------
+     
+     - To wake up from the Stop mode with an RTC alarm event, it is necessary to:
+       - Configure the EXTI Line 17 to be sensitive to rising edges (Interrupt 
+         or Event modes) using the EXTI_Init() function.
+       - Enable the RTC Alarm Interrupt using the RTC_ITConfig() function
+       - Configure the RTC to generate the RTC alarm using the RTC_SetAlarm() 
+         and RTC_AlarmCmd() functions.
+     - To wake up from the Stop mode with an RTC Tamper or time stamp event, it 
+       is necessary to:
+       - Configure the EXTI Line 21 to be sensitive to rising edges (Interrupt 
+         or Event modes) using the EXTI_Init() function.
+       - Enable the RTC Tamper or time stamp Interrupt using the RTC_ITConfig() 
+         function
+       - Configure the RTC to detect the tamper or time stamp event using the
+         RTC_TimeStampConfig(), RTC_TamperTriggerConfig() and RTC_TamperCmd()
+         functions.
+     - To wake up from the Stop mode with an RTC WakeUp event, it is necessary to:
+       - Configure the EXTI Line 22 to be sensitive to rising edges (Interrupt 
+         or Event modes) using the EXTI_Init() function.
+       - Enable the RTC WakeUp Interrupt using the RTC_ITConfig() function
+       - Configure the RTC to generate the RTC WakeUp event using the RTC_WakeUpClockConfig(), 
+         RTC_SetWakeUpCounter() and RTC_WakeUpCmd() functions.
+
+   - RTC auto-wakeup (AWU) from the Standby mode
+     -------------------------------------------
+     - To wake up from the Standby mode with an RTC alarm event, it is necessary to:
+       - Enable the RTC Alarm Interrupt using the RTC_ITConfig() function
+       - Configure the RTC to generate the RTC alarm using the RTC_SetAlarm() 
+         and RTC_AlarmCmd() functions.
+     - To wake up from the Standby mode with an RTC Tamper or time stamp event, it 
+       is necessary to:
+       - Enable the RTC Tamper or time stamp Interrupt using the RTC_ITConfig() 
+         function
+       - Configure the RTC to detect the tamper or time stamp event using the
+         RTC_TimeStampConfig(), RTC_TamperTriggerConfig() and RTC_TamperCmd()
+         functions.
+     - To wake up from the Standby mode with an RTC WakeUp event, it is necessary to:
+       - Enable the RTC WakeUp Interrupt using the RTC_ITConfig() function
+       - Configure the RTC to generate the RTC WakeUp event using the RTC_WakeUpClockConfig(), 
+         RTC_SetWakeUpCounter() and RTC_WakeUpCmd() functions.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enters STOP mode.
+  *   
+  * @note   In Stop mode, all I/O pins keep the same state as in Run mode.
+  * @note   When exiting Stop mode by issuing an interrupt or a wakeup event, 
+  *         the HSI RC oscillator is selected as system clock.
+  * @note   When the voltage regulator operates in low power mode, an additional 
+  *         startup delay is incurred when waking up from Stop mode. 
+  *         By keeping the internal regulator ON during Stop mode, the consumption 
+  *         is higher although the startup time is reduced.           
+  *     
+  * @param  PWR_Regulator: specifies the regulator state in STOP mode.
+  *          This parameter can be one of the following values:
+  *            @arg PWR_Regulator_ON: STOP mode with regulator ON
+  *            @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode
+  * @param  PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
+  *          This parameter can be one of the following values:
+  *            @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction
+  *            @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction
+  * @retval None
+  */
+void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
+{
+  uint32_t tmpreg = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_PWR_REGULATOR(PWR_Regulator));
+  assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
+  
+  /* Select the regulator state in STOP mode ---------------------------------*/
+  tmpreg = PWR->CR;
+  /* Clear PDDS and LPDSR bits */
+  tmpreg &= CR_DS_MASK;
+  
+  /* Set LPDSR bit according to PWR_Regulator value */
+  tmpreg |= PWR_Regulator;
+  
+  /* Store the new value */
+  PWR->CR = tmpreg;
+  
+  /* Set SLEEPDEEP bit of Cortex System Control Register */
+  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+  
+  /* Select STOP mode entry --------------------------------------------------*/
+  if(PWR_STOPEntry == PWR_STOPEntry_WFI)
+  {   
+    /* Request Wait For Interrupt */
+    __WFI();
+  }
+  else
+  {
+    /* Request Wait For Event */
+    __WFE();
+  }
+  /* Reset SLEEPDEEP bit of Cortex System Control Register */
+  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);  
+}
+
+/**
+  * @brief  Enters STANDBY mode.
+  * @note   In Standby mode, all I/O pins are high impedance except for:
+  *          - Reset pad (still available) 
+  *          - RTC_AF1 pin (PC13) if configured for tamper, time-stamp, RTC 
+  *            Alarm out, or RTC clock calibration out.
+  *          - RTC_AF2 pin (PI8) if configured for tamper or time-stamp.  
+  *          - WKUP pin 1 (PA0) if enabled.       
+  * @param  None
+  * @retval None
+  */
+void PWR_EnterSTANDBYMode(void)
+{
+  /* Clear Wakeup flag */
+  PWR->CR |= PWR_CR_CWUF;
+  
+  /* Select STANDBY mode */
+  PWR->CR |= PWR_CR_PDDS;
+  
+  /* Set SLEEPDEEP bit of Cortex System Control Register */
+  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+  
+/* This option is used to ensure that store operations are completed */
+#if defined ( __CC_ARM   )
+  __force_stores();
+#endif
+  /* Request Wait For Interrupt */
+  __WFI();
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PWR_Group7 Flags management functions
+ *  @brief   Flags management functions 
+ *
+@verbatim   
+ ===============================================================================
+                           Flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Checks whether the specified PWR flag is set or not.
+  * @param  PWR_FLAG: specifies the flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg PWR_FLAG_WU: Wake Up flag. This flag indicates that a wakeup event 
+  *                  was received from the WKUP pin or from the RTC alarm (Alarm A 
+  *                  or Alarm B), RTC Tamper event, RTC TimeStamp event or RTC Wakeup.
+  *                  An additional wakeup event is detected if the WKUP pin is enabled 
+  *                  (by setting the EWUP bit) when the WKUP pin level is already high.  
+  *            @arg PWR_FLAG_SB: StandBy flag. This flag indicates that the system was
+  *                  resumed from StandBy mode.    
+  *            @arg PWR_FLAG_PVDO: PVD Output. This flag is valid only if PVD is enabled 
+  *                  by the PWR_PVDCmd() function. The PVD is stopped by Standby mode 
+  *                  For this reason, this bit is equal to 0 after Standby or reset
+  *                  until the PVDE bit is set.
+  *            @arg PWR_FLAG_BRR: Backup regulator ready flag. This bit is not reset 
+  *                  when the device wakes up from Standby mode or by a system reset 
+  *                  or power reset.  
+  * @retval The new state of PWR_FLAG (SET or RESET).
+  */
+FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  
+  /* Check the parameters */
+  assert_param(IS_PWR_GET_FLAG(PWR_FLAG));
+  
+  if ((PWR->CSR & PWR_FLAG) != (uint32_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  /* Return the flag status */
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears the PWR's pending flags.
+  * @param  PWR_FLAG: specifies the flag to clear.
+  *          This parameter can be one of the following values:
+  *            @arg PWR_FLAG_WU: Wake Up flag
+  *            @arg PWR_FLAG_SB: StandBy flag
+  * @retval None
+  */
+void PWR_ClearFlag(uint32_t PWR_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG));
+         
+  PWR->CR |=  PWR_FLAG << 2;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1811 - 0
app/Libraries/src/stm32f2xx_rcc.c


+ 397 - 0
app/Libraries/src/stm32f2xx_rng.c

@@ -0,0 +1,397 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_rng.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+    * @brief This file provides firmware functions to manage the following 
+  *          functionalities of the Random Number Generator (RNG) peripheral:           
+  *           - Initialization and Configuration 
+  *           - Get 32 bit Random number      
+  *           - Interrupts and flags management       
+  *         
+  *  @verbatim
+  *                               
+  *          ===================================================================      
+  *                                   How to use this driver
+  *          ===================================================================          
+  *          1. Enable The RNG controller clock using 
+  *            RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE) function.
+  *              
+  *          2. Activate the RNG peripheral using RNG_Cmd() function.
+  *          
+  *          3. Wait until the 32 bit Random number Generator contains a valid 
+  *            random data (using polling/interrupt mode). For more details, 
+  *            refer to "Interrupts and flags management functions" module 
+  *            description.
+  *           
+  *          4. Get the 32 bit Random number using RNG_GetRandomNumber() function
+  *          
+  *          5. To get another 32 bit Random number, go to step 3.       
+  *
+  *         
+  *              
+  *  @endverbatim
+  *         
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_rng.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup RNG 
+  * @brief RNG driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup RNG_Private_Functions
+  * @{
+  */ 
+
+/** @defgroup RNG_Group1 Initialization and Configuration functions
+ *  @brief    Initialization and Configuration functions 
+ *
+@verbatim    
+ ===============================================================================
+                      Initialization and Configuration functions
+ ===============================================================================  
+  This section provides functions allowing to 
+   - Initialize the RNG peripheral
+   - Enable or disable the RNG peripheral
+   
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the RNG peripheral registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void RNG_DeInit(void)
+{
+  /* Enable RNG reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_RNG, ENABLE);
+
+  /* Release RNG from reset state */
+  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_RNG, DISABLE);
+}
+
+/**
+  * @brief  Enables or disables the RNG peripheral.
+  * @param  NewState: new state of the RNG peripheral.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void RNG_Cmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the RNG */
+    RNG->CR |= RNG_CR_RNGEN;
+  }
+  else
+  {
+    /* Disable the RNG */
+    RNG->CR &= ~RNG_CR_RNGEN;
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup RNG_Group2 Get 32 bit Random number function
+ *  @brief    Get 32 bit Random number function 
+ *
+
+@verbatim    
+ ===============================================================================
+                      Get 32 bit Random number function
+ ===============================================================================  
+  This section provides a function allowing to get the 32 bit Random number  
+  
+  @note  Before to call this function you have to wait till DRDY flag is set,
+         using RNG_GetFlagStatus(RNG_FLAG_DRDY) function. 
+   
+@endverbatim
+  * @{
+  */
+
+
+/**
+  * @brief  Returns a 32-bit random number.
+  *   
+  * @note   Before to call this function you have to wait till DRDY (data ready)
+  *         flag is set, using RNG_GetFlagStatus(RNG_FLAG_DRDY) function.
+  * @note   Each time the the Random number data is read (using RNG_GetRandomNumber()
+  *         function), the RNG_FLAG_DRDY flag is automatically cleared.
+  * @note   In the case of a seed error, the generation of random numbers is 
+  *         interrupted for as long as the SECS bit is '1'. If a number is 
+  *         available in the RNG_DR register, it must not be used because it may 
+  *         not have enough entropy. In this case, it is recommended to clear the 
+  *         SEIS bit(using RNG_ClearFlag(RNG_FLAG_SECS) function), then disable 
+  *         and enable the RNG peripheral (using RNG_Cmd() function) to 
+  *         reinitialize and restart the RNG.
+  * @note   In the case of a clock error, the RNG is no more able to generate 
+  *         random numbers because the PLL48CLK clock is not correct. User have 
+  *         to check that the clock controller is correctly configured to provide
+  *         the RNG clock and clear the CEIS bit (using RNG_ClearFlag(RNG_FLAG_CECS) 
+  *         function) . The clock error has no impact on the previously generated 
+  *         random numbers, and the RNG_DR register contents can be used.
+  *         
+  * @param  None
+  * @retval 32-bit random number.
+  */
+uint32_t RNG_GetRandomNumber(void)
+{
+  /* Return the 32 bit random number from the DR register */
+  return RNG->DR;
+}
+
+
+/**
+  * @}
+  */
+
+/** @defgroup RNG_Group3 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+                   Interrupts and flags management functions
+ ===============================================================================  
+
+  This section provides functions allowing to configure the RNG Interrupts and 
+  to get the status and clear flags and Interrupts pending bits.
+  
+  The RNG provides 3 Interrupts sources and 3 Flags:
+  
+  Flags :
+  ---------- 
+     1. RNG_FLAG_DRDY :  In the case of the RNG_DR register contains valid 
+                         random data. it is cleared by reading the valid data 
+                         (using RNG_GetRandomNumber() function).
+
+     2. RNG_FLAG_CECS : In the case of a seed error detection. 
+      
+     3. RNG_FLAG_SECS : In the case of a clock error detection.
+              
+
+  Interrupts :
+  ------------
+   if enabled, an RNG interrupt is pending :
+    
+   1.  In the case of the RNG_DR register contains valid random data. 
+       This interrupt source is cleared once the RNG_DR register has been read 
+       (using RNG_GetRandomNumber() function) until a new valid value is 
+       computed. 
+   
+   or 
+   2. In the case of a seed error : One of the following faulty sequences has 
+      been detected:
+      - More than 64 consecutive bits at the same value (0 or 1)
+      - More than 32 consecutive alternance of 0 and 1 (0101010101...01)
+      This interrupt source is cleared using RNG_ClearITPendingBit(RNG_IT_SEI)
+      function.
+   
+   or
+   3. In the case of a clock error : the PLL48CLK (RNG peripheral clock source) 
+      was not correctly detected (fPLL48CLK< fHCLK/16).
+      This interrupt source is cleared using RNG_ClearITPendingBit(RNG_IT_CEI)
+      function.
+      @note In this case, User have to check that the clock controller is 
+            correctly configured to provide the RNG clock. 
+
+  Managing the RNG controller events :
+  ------------------------------------ 
+  The user should identify which mode will be used in his application to manage 
+  the RNG controller events: Polling mode or Interrupt mode.
+  
+  1.  In the Polling Mode it is advised to use the following functions:
+      - RNG_GetFlagStatus() : to check if flags events occur. 
+      - RNG_ClearFlag()     : to clear the flags events.
+  
+  @note RNG_FLAG_DRDY can not be cleared by RNG_ClearFlag(). it is cleared only 
+        by reading the Random number data.      
+  
+  2.  In the Interrupt Mode it is advised to use the following functions:
+      - RNG_ITConfig()       : to enable or disable the interrupt source.
+      - RNG_GetITStatus()    : to check if Interrupt occurs.
+      - RNG_ClearITPendingBit() : to clear the Interrupt pending Bit 
+                                (corresponding Flag). 
+  
+
+@endverbatim
+  * @{
+  */ 
+
+/**
+  * @brief  Enables or disables the RNG interrupt.
+  * @note   The RNG provides 3 interrupt sources,
+  *           - Computed data is ready event (DRDY), and           
+  *           - Seed error Interrupt (SEI) and 
+  *           - Clock error Interrupt (CEI), 
+  *         all these interrupts sources are enabled by setting the IE bit in 
+  *         CR register. However, each interrupt have its specific status bit
+  *         (see RNG_GetITStatus() function) and clear bit except the DRDY event
+  *         (see RNG_ClearITPendingBit() function).
+  * @param  NewState: new state of the RNG interrupt.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void RNG_ITConfig(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the RNG interrupt */
+    RNG->CR |= RNG_CR_IE;
+  }
+  else
+  {
+    /* Disable the RNG interrupt */
+    RNG->CR &= ~RNG_CR_IE;
+  }
+}
+
+/**
+  * @brief  Checks whether the specified RNG flag is set or not.
+  * @param  RNG_FLAG: specifies the RNG flag to check.
+  *          This parameter can be one of the following values:
+  *            @arg RNG_FLAG_DRDY: Data Ready flag.
+  *            @arg RNG_FLAG_CECS: Clock Error Current flag.
+  *            @arg RNG_FLAG_SECS: Seed Error Current flag.
+  * @retval The new state of RNG_FLAG (SET or RESET).
+  */
+FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_RNG_GET_FLAG(RNG_FLAG));
+
+  /* Check the status of the specified RNG flag */
+  if ((RNG->SR & RNG_FLAG) != (uint8_t)RESET)
+  {
+    /* RNG_FLAG is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* RNG_FLAG is reset */
+    bitstatus = RESET;
+  }
+  /* Return the RNG_FLAG status */
+  return  bitstatus;
+}
+
+
+/**
+  * @brief  Clears the RNG flags.
+  * @param  RNG_FLAG: specifies the flag to clear. 
+  *          This parameter can be any combination of the following values:
+  *            @arg RNG_FLAG_CECS: Clock Error Current flag.
+  *            @arg RNG_FLAG_SECS: Seed Error Current flag.
+  * @note   RNG_FLAG_DRDY can not be cleared by RNG_ClearFlag() function. 
+  *         This flag is cleared only by reading the Random number data (using 
+  *         RNG_GetRandomNumber() function).                           
+  * @retval None
+  */
+void RNG_ClearFlag(uint8_t RNG_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_RNG_CLEAR_FLAG(RNG_FLAG));
+  /* Clear the selected RNG flags */
+  RNG->SR = ~(uint32_t)(((uint32_t)RNG_FLAG) << 4);
+}
+
+/**
+  * @brief  Checks whether the specified RNG interrupt has occurred or not.
+  * @param  RNG_IT: specifies the RNG interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg RNG_IT_CEI: Clock Error Interrupt.
+  *            @arg RNG_IT_SEI: Seed Error Interrupt.                   
+  * @retval The new state of RNG_IT (SET or RESET).
+  */
+ITStatus RNG_GetITStatus(uint8_t RNG_IT)
+{
+  ITStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_RNG_GET_IT(RNG_IT));
+
+  /* Check the status of the specified RNG interrupt */
+  if ((RNG->SR & RNG_IT) != (uint8_t)RESET)
+  {
+    /* RNG_IT is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* RNG_IT is reset */
+    bitstatus = RESET;
+  }
+  /* Return the RNG_IT status */
+  return bitstatus;
+}
+
+
+/**
+  * @brief  Clears the RNG interrupt pending bit(s).
+  * @param  RNG_IT: specifies the RNG interrupt pending bit(s) to clear.
+  *          This parameter can be any combination of the following values:
+  *            @arg RNG_IT_CEI: Clock Error Interrupt.
+  *            @arg RNG_IT_SEI: Seed Error Interrupt.
+  * @retval None
+  */
+void RNG_ClearITPendingBit(uint8_t RNG_IT)
+{
+  /* Check the parameters */
+  assert_param(IS_RNG_IT(RNG_IT));
+
+  /* Clear the selected RNG interrupt pending bit */
+  RNG->SR = (uint8_t)~RNG_IT;
+}
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+
+/**
+  * @}
+  */ 
+
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2236 - 0
app/Libraries/src/stm32f2xx_rtc.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1002 - 0
app/Libraries/src/stm32f2xx_sdio.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1175 - 0
app/Libraries/src/stm32f2xx_spi.c


+ 202 - 0
app/Libraries/src/stm32f2xx_syscfg.c

@@ -0,0 +1,202 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_syscfg.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the SYSCFG peripheral.
+  *
+  *  @verbatim
+  *  
+  *          ===================================================================
+  *                                 How to use this driver
+  *          ===================================================================
+  *                  
+  *          This driver provides functions for:
+  *          
+  *          1. Remapping the memory accessible in the code area using SYSCFG_MemoryRemapConfig()
+  *              
+  *          2. Manage the EXTI lines connection to the GPIOs using SYSCFG_EXTILineConfig()
+  *            
+  *          3. Select the ETHERNET media interface (RMII/RII) using SYSCFG_ETH_MediaInterfaceConfig()
+  *
+  *  @note  SYSCFG APB clock must be enabled to get write access to SYSCFG registers,
+  *         using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
+  *                 
+  *  @endverbatim
+  *      
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_syscfg.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup SYSCFG 
+  * @brief SYSCFG driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* ------------ RCC registers bit address in the alias region ----------- */
+#define SYSCFG_OFFSET             (SYSCFG_BASE - PERIPH_BASE)
+/* ---  PMC Register ---*/ 
+/* Alias word address of MII_RMII_SEL bit */ 
+#define PMC_OFFSET                (SYSCFG_OFFSET + 0x04) 
+#define MII_RMII_SEL_BitNumber    ((uint8_t)0x17) 
+#define PMC_MII_RMII_SEL_BB       (PERIPH_BB_BASE + (PMC_OFFSET * 32) + (MII_RMII_SEL_BitNumber * 4)) 
+
+/* ---  CMPCR Register ---*/ 
+/* Alias word address of CMP_PD bit */ 
+#define CMPCR_OFFSET              (SYSCFG_OFFSET + 0x20) 
+#define CMP_PD_BitNumber          ((uint8_t)0x00) 
+#define CMPCR_CMP_PD_BB           (PERIPH_BB_BASE + (CMPCR_OFFSET * 32) + (CMP_PD_BitNumber * 4)) 
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup SYSCFG_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Deinitializes the Alternate Functions (remap and EXTI configuration)
+  *   registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void SYSCFG_DeInit(void)
+{
+   RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
+   RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, DISABLE);
+}
+
+/**
+  * @brief  Changes the mapping of the specified pin.
+  * @param  SYSCFG_Memory: selects the memory remapping.
+  *         This parameter can be one of the following values:
+  *            @arg SYSCFG_MemoryRemap_Flash:       Main Flash memory mapped at 0x00000000  
+  *            @arg SYSCFG_MemoryRemap_SystemFlash: System Flash memory mapped at 0x00000000
+  *            @arg SYSCFG_MemoryRemap_FSMC:        FSMC (Bank1 (NOR/PSRAM 1 and 2) mapped at 0x00000000
+  *            @arg SYSCFG_MemoryRemap_SRAM:        Embedded SRAM (112kB) mapped at 0x00000000
+  *  
+  * @note   In remap mode, the FSMC addressing is fixed to the remap address area only
+  *        (Bank1 NOR/PSRAM 1 and NOR/PSRAM 2) and FSMC control registers are not
+  *         accessible. The FSMC remap function must be disabled to allows addressing
+  *         other memory devices through the FSMC and/or to access FSMC control
+  *         registers. 
+  *        
+  * @retval None
+  */
+void SYSCFG_MemoryRemapConfig(uint8_t SYSCFG_MemoryRemap)
+{
+  /* Check the parameters */
+  assert_param(IS_SYSCFG_MEMORY_REMAP_CONFING(SYSCFG_MemoryRemap));
+
+  SYSCFG->MEMRMP = SYSCFG_MemoryRemap;
+}
+
+/**
+  * @brief  Selects the GPIO pin used as EXTI Line.
+  * @param  EXTI_PortSourceGPIOx : selects the GPIO port to be used as source for
+  *          EXTI lines where x can be (A..I).
+  * @param  EXTI_PinSourcex: specifies the EXTI line to be configured.
+  *           This parameter can be EXTI_PinSourcex where x can be (0..15, except
+  *           for EXTI_PortSourceGPIOI x can be (0..11).
+  * @retval None
+  */
+void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)
+{
+  uint32_t tmp = 0x00;
+
+  /* Check the parameters */
+  assert_param(IS_EXTI_PORT_SOURCE(EXTI_PortSourceGPIOx));
+  assert_param(IS_EXTI_PIN_SOURCE(EXTI_PinSourcex));
+
+  tmp = ((uint32_t)0x0F) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03));
+  SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] &= ~tmp;
+  SYSCFG->EXTICR[EXTI_PinSourcex >> 0x02] |= (((uint32_t)EXTI_PortSourceGPIOx) << (0x04 * (EXTI_PinSourcex & (uint8_t)0x03)));
+}
+
+/**
+  * @brief  Selects the ETHERNET media interface 
+  * @param  SYSCFG_ETH_MediaInterface: specifies the Media Interface mode. 
+  *          This parameter can be one of the following values: 
+  *            @arg SYSCFG_ETH_MediaInterface_MII: MII mode selected
+  *            @arg SYSCFG_ETH_MediaInterface_RMII: RMII mode selected 
+  * @retval None 
+  */
+void SYSCFG_ETH_MediaInterfaceConfig(uint32_t SYSCFG_ETH_MediaInterface) 
+{ 
+  assert_param(IS_SYSCFG_ETH_MEDIA_INTERFACE(SYSCFG_ETH_MediaInterface)); 
+  /* Configure MII_RMII selection bit */ 
+  *(__IO uint32_t *) PMC_MII_RMII_SEL_BB = SYSCFG_ETH_MediaInterface; 
+}
+
+/**
+  * @brief  Enables or disables the I/O Compensation Cell.
+  * @note   The I/O compensation cell can be used only when the device supply
+  *         voltage ranges from 2.4 to 3.6 V.  
+  * @param  NewState: new state of the I/O Compensation Cell.
+  *          This parameter can be one of the following values:
+  *            @arg ENABLE: I/O compensation cell enabled  
+  *            @arg DISABLE: I/O compensation cell power-down mode  
+  * @retval None
+  */
+void SYSCFG_CompensationCellCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  *(__IO uint32_t *) CMPCR_CMP_PD_BB = (uint32_t)NewState;
+}
+
+/**
+  * @brief  Checks whether the I/O Compensation Cell ready flag is set or not.
+  * @param  None
+  * @retval The new state of the I/O Compensation Cell ready flag (SET or RESET)
+  */
+FlagStatus SYSCFG_GetCompensationCellStatus(void)
+{
+  FlagStatus bitstatus = RESET;
+    
+  if ((SYSCFG->CMPCR & SYSCFG_CMPCR_READY ) != (uint32_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3350 - 0
app/Libraries/src/stm32f2xx_tim.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1461 - 0
app/Libraries/src/stm32f2xx_usart.c


+ 301 - 0
app/Libraries/src/stm32f2xx_wwdg.c

@@ -0,0 +1,301 @@
+/**
+  ******************************************************************************
+  * @file    stm32f2xx_wwdg.c
+  * @author  MCD Application Team
+  * @version V1.1.3
+  * @date    31-December-2021 
+  * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the Window watchdog (WWDG) peripheral:           
+  *           - Prescaler, Refresh window and Counter configuration
+  *           - WWDG activation
+  *           - Interrupts and flags management
+  *             
+  *  @verbatim
+  *    
+  *          ===================================================================
+  *                                     WWDG features
+  *          ===================================================================
+  *                                        
+  *          Once enabled the WWDG generates a system reset on expiry of a programmed
+  *          time period, unless the program refreshes the counter (downcounter) 
+  *          before to reach 0x3F value (i.e. a reset is generated when the counter
+  *          value rolls over from 0x40 to 0x3F). 
+  *          An MCU reset is also generated if the counter value is refreshed
+  *          before the counter has reached the refresh window value. This 
+  *          implies that the counter must be refreshed in a limited window.
+  *            
+  *          Once enabled the WWDG cannot be disabled except by a system reset.                          
+  *          
+  *          WWDGRST flag in RCC_CSR register can be used to inform when a WWDG
+  *          reset occurs.
+  *            
+  *          The WWDG counter input clock is derived from the APB clock divided 
+  *          by a programmable prescaler.
+  *              
+  *          WWDG counter clock = PCLK1 / Prescaler
+  *          WWDG timeout = (WWDG counter clock) * (counter value)
+  *                      
+  *          Min-max timeout value @30 MHz(PCLK1): ~136.5 us / ~69.9 ms
+  *                            
+  *          ===================================================================
+  *                                 How to use this driver
+  *          =================================================================== 
+  *          1. Enable WWDG clock using RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE) function
+  *            
+  *          2. Configure the WWDG prescaler using WWDG_SetPrescaler() function
+  *                           
+  *          3. Configure the WWDG refresh window using WWDG_SetWindowValue() function
+  *            
+  *          4. Set the WWDG counter value and start it using WWDG_Enable() function.
+  *             When the WWDG is enabled the counter value should be configured to 
+  *             a value greater than 0x40 to prevent generating an immediate reset.     
+  *            
+  *          5. Optionally you can enable the Early wakeup interrupt which is 
+  *             generated when the counter reach 0x40.
+  *             Once enabled this interrupt cannot be disabled except by a system reset.
+  *                 
+  *          6. Then the application program must refresh the WWDG counter at regular
+  *             intervals during normal operation to prevent an MCU reset, using
+  *             WWDG_SetCounter() function. This operation must occur only when
+  *             the counter value is lower than the refresh window value, 
+  *             programmed using WWDG_SetWindowValue().         
+  *
+  *  @endverbatim  
+  *                             
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2012 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f2xx_wwdg.h"
+#include "stm32f2xx_rcc.h"
+
+/** @addtogroup STM32F2xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup WWDG 
+  * @brief WWDG driver modules
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* ----------- WWDG registers bit address in the alias region ----------- */
+#define WWDG_OFFSET       (WWDG_BASE - PERIPH_BASE)
+/* Alias word address of EWI bit */
+#define CFR_OFFSET        (WWDG_OFFSET + 0x04)
+#define EWI_BitNumber     0x09
+#define CFR_EWI_BB        (PERIPH_BB_BASE + (CFR_OFFSET * 32) + (EWI_BitNumber * 4))
+
+/* --------------------- WWDG registers bit mask ------------------------ */
+/* CFR register bit mask */
+#define CFR_WDGTB_MASK    ((uint32_t)0xFFFFFE7F)
+#define CFR_W_MASK        ((uint32_t)0xFFFFFF80)
+#define BIT_MASK          ((uint8_t)0x7F)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup WWDG_Private_Functions
+  * @{
+  */
+
+/** @defgroup WWDG_Group1 Prescaler, Refresh window and Counter configuration functions
+ *  @brief   Prescaler, Refresh window and Counter configuration functions 
+ *
+@verbatim   
+ ===============================================================================
+          Prescaler, Refresh window and Counter configuration functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the WWDG peripheral registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void WWDG_DeInit(void)
+{
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, ENABLE);
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, DISABLE);
+}
+
+/**
+  * @brief  Sets the WWDG Prescaler.
+  * @param  WWDG_Prescaler: specifies the WWDG Prescaler.
+  *   This parameter can be one of the following values:
+  *     @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1/4096)/1
+  *     @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1/4096)/2
+  *     @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1/4096)/4
+  *     @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1/4096)/8
+  * @retval None
+  */
+void WWDG_SetPrescaler(uint32_t WWDG_Prescaler)
+{
+  uint32_t tmpreg = 0;
+  /* Check the parameters */
+  assert_param(IS_WWDG_PRESCALER(WWDG_Prescaler));
+  /* Clear WDGTB[1:0] bits */
+  tmpreg = WWDG->CFR & CFR_WDGTB_MASK;
+  /* Set WDGTB[1:0] bits according to WWDG_Prescaler value */
+  tmpreg |= WWDG_Prescaler;
+  /* Store the new value */
+  WWDG->CFR = tmpreg;
+}
+
+/**
+  * @brief  Sets the WWDG window value.
+  * @param  WindowValue: specifies the window value to be compared to the downcounter.
+  *   This parameter value must be lower than 0x80.
+  * @retval None
+  */
+void WWDG_SetWindowValue(uint8_t WindowValue)
+{
+  __IO uint32_t tmpreg = 0;
+
+  /* Check the parameters */
+  assert_param(IS_WWDG_WINDOW_VALUE(WindowValue));
+  /* Clear W[6:0] bits */
+
+  tmpreg = WWDG->CFR & CFR_W_MASK;
+
+  /* Set W[6:0] bits according to WindowValue value */
+  tmpreg |= WindowValue & (uint32_t) BIT_MASK;
+
+  /* Store the new value */
+  WWDG->CFR = tmpreg;
+}
+
+/**
+  * @brief  Enables the WWDG Early Wakeup interrupt(EWI).
+  * @note   Once enabled this interrupt cannot be disabled except by a system reset.
+  * @param  None
+  * @retval None
+  */
+void WWDG_EnableIT(void)
+{
+  *(__IO uint32_t *) CFR_EWI_BB = (uint32_t)ENABLE;
+}
+
+/**
+  * @brief  Sets the WWDG counter value.
+  * @param  Counter: specifies the watchdog counter value.
+  *   This parameter must be a number between 0x40 and 0x7F (to prevent generating
+  *   an immediate reset) 
+  * @retval None
+  */
+void WWDG_SetCounter(uint8_t Counter)
+{
+  /* Check the parameters */
+  assert_param(IS_WWDG_COUNTER(Counter));
+  /* Write to T[6:0] bits to configure the counter value, no need to do
+     a read-modify-write; writing a 0 to WDGA bit does nothing */
+  WWDG->CR = Counter & BIT_MASK;
+}
+/**
+  * @}
+  */
+
+/** @defgroup WWDG_Group2 WWDG activation functions
+ *  @brief   WWDG activation functions 
+ *
+@verbatim   
+ ===============================================================================
+                       WWDG activation function
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables WWDG and load the counter value.                  
+  * @param  Counter: specifies the watchdog counter value.
+  *   This parameter must be a number between 0x40 and 0x7F (to prevent generating
+  *   an immediate reset)
+  * @retval None
+  */
+void WWDG_Enable(uint8_t Counter)
+{
+  /* Check the parameters */
+  assert_param(IS_WWDG_COUNTER(Counter));
+  WWDG->CR = WWDG_CR_WDGA | Counter;
+}
+/**
+  * @}
+  */
+
+/** @defgroup WWDG_Group3 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions 
+ *
+@verbatim   
+ ===============================================================================
+                 Interrupts and flags management functions
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Checks whether the Early Wakeup interrupt flag is set or not.
+  * @param  None
+  * @retval The new state of the Early Wakeup interrupt flag (SET or RESET)
+  */
+FlagStatus WWDG_GetFlagStatus(void)
+{
+  FlagStatus bitstatus = RESET;
+    
+  if ((WWDG->SR) != (uint32_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  Clears Early Wakeup interrupt flag.
+  * @param  None
+  * @retval None
+  */
+void WWDG_ClearFlag(void)
+{
+  WWDG->SR = (uint32_t)RESET;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2113 - 0
app/MDKProject/lora_gateway.uvoptx


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1192 - 0
app/MDKProject/lora_gateway.uvprojx


BIN
app/OBJ/lora_gateway.axf


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 18443 - 0
app/OBJ/lora_gateway.hex


+ 87 - 0
app/SX1278/platform/platform.h

@@ -0,0 +1,87 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       platform.h
+ * \brief        
+ *
+ * \version    1.0
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ */
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#ifndef __GNUC__
+#define inline
+#endif
+
+/*!
+ * Platform definition
+ */
+#define Bleeper                                     3
+#define SX1243ska                                   2
+#define SX12xxEiger                                 1
+#define SX12000DVK                                  0
+
+/*!
+ * Platform choice. Please uncoment the PLATFORM define and choose your platform
+ * or add/change the PLATFORM definition on the compiler Defines option
+ */
+#define PLATFORM                                    SX12xxEiger
+
+#if( PLATFORM == SX12xxEiger )
+/*!
+ * Radio choice. Please uncomment the wanted radio and comment the others
+ * or add/change wanted radio definition on the compiler Defines option
+ */
+//#define USE_SX1232_RADIO
+//#define USE_SX1272_RADIO
+#define USE_SX1276_RADIO
+//#define USE_SX1243_RADIO
+
+/*!
+ * Module choice. There are three existing module with the SX1276.
+ * Please set the connected module to the value 1 and set the others to 0
+ */
+#ifdef USE_SX1276_RADIO
+#define MODULE_SX1276RF1IAS                         0
+#define MODULE_SX1276RF1JAS                         0
+#define MODULE_SX1276RF1KAS                         1
+#endif
+
+    #include "sx12xxEiger.h"
+    #define USE_UART                                0
+
+#elif( PLATFORM == SX12000DVK )
+/*!
+ * Radio choice. Please uncomment the wanted radio and comment the others
+ * or add/change wanted radio definition on the compiler Defines option
+ */
+//#define USE_SX1232_RADIO
+//#define USE_SX1272_RADIO
+#define USE_SX1276_RADIO
+//#define USE_SX1243_RADIO
+
+//    #include "sx1200dvk/sx1200dvk.h"
+
+#elif( PLATFORM == SX1243ska )
+
+#elif( PLATFORM == Bleeper )
+    #define USE_SX1272_RADIO
+    
+    #include "bleeper/bleeper.h"
+    #define USE_UART                                0
+
+#else
+    #error "Missing define: Platform (ie. SX12xxEiger)"
+#endif
+
+#endif // __PLATFORM_H__

+ 130 - 0
app/SX1278/platform/sx12xxEiger.c

@@ -0,0 +1,130 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx12xxEiger.c
+ * \brief        
+ *
+ * \version    1.0
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ */
+#include <stdint.h> 
+#include "spi.h"
+#include "i2c.h"
+#include "ioe.h"
+#include "led.h"
+#include "uart.h"
+#include "sx12xxEiger.h"
+
+//#if( defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) )
+//
+//#include "usbd_cdc_core.h"
+//#include "usbd_usr.h"
+//#include "usbd_desc.h"
+//
+//#else
+//
+//#include "usb_regs.h"
+//#include "usb_core.h"
+//#include "usb_init.h"
+//#include "usb_pwr.h"
+//#include "usb_bsp.h"
+//#include "usb_sil.h"
+//
+//#endif
+
+// System tick (1ms)
+volatile uint32_t TickCounter = 0;
+
+//#if( defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) )
+//
+//#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
+//  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
+//    #pragma data_alignment=4   
+//  #endif
+//#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
+//   
+//__ALIGN_BEGIN USB_OTG_CORE_HANDLE    USB_OTG_dev __ALIGN_END ;
+//
+//#else
+//
+//#endif
+
+void BoardInit( void )
+{
+//    uint8_t i;
+//
+//    /* Setup SysTick Timer for 1 us interrupts ( not too often to save power ) */
+//    if( SysTick_Config( SystemCoreClock / 1000 ) )
+//    { 
+//        /* Capture error */ 
+//        while (1);
+//    }
+//
+//    // Initialize SPI
+//    SpiInit( );
+//
+//    // Initialize I2C
+//    I2cInit( );
+//    
+//    // Initialize IO expander
+//    IoeInit( );
+//    
+//    // Initialize LED
+//    for( i = 0; i < LED_NB; i++ )
+//    {
+//        LedInit( ( tLed )i );
+//    }
+//    IoePinOn( LED_1_PIN );
+//    IoePinOn( LED_2_PIN );
+//    IoePinOn( LED_3_PIN );
+//    
+//#if( defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) )
+//    
+//    USBD_Init( &USB_OTG_dev,
+//#ifdef USE_USB_OTG_HS 
+//               USB_OTG_HS_CORE_ID,
+//#else            
+//               USB_OTG_FS_CORE_ID,
+//#endif  
+//               &USR_desc, 
+//               &USBD_CDC_cb, 
+//               &USR_cb );
+//#else    
+//        /* Configure the used GPIOs*/
+//        GPIO_Configuration( );
+//        /* Additional EXTI configuration (configure both edges) */
+//        EXTI_Configuration( );
+//
+//        USB_Interrupts_Config( );
+//        Set_USBClock( );
+//        USB_Init( );
+//#endif
+}
+
+void Delay ( uint32_t delay )
+{
+    // Wait delay ms
+    uint32_t startTick = TickCounter;
+    while( ( TickCounter - startTick ) < delay );   
+}
+
+void LongDelay ( uint8_t delay )
+{
+    uint32_t longDelay;
+    uint32_t startTick;
+
+    longDelay = delay * 1000;
+
+    // Wait delay s
+    startTick = TickCounter;
+    while( ( TickCounter - startTick ) < longDelay );   
+}

+ 94 - 0
app/SX1278/platform/sx12xxEiger.h

@@ -0,0 +1,94 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx12xxEiger.h
+ * \brief        
+ *
+ * \version    1.0
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ */
+#ifndef __SX12XXEIGER_H__
+#define __SX12XXEIGER_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+//#include "stm32f2xx.h"
+
+#define USE_USB                                     1
+
+#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
+#define BACKUP_REG_BOOTLOADER                       RTC_BKP_DR0      /* Booloader enter*/
+#else
+#define BACKUP_REG_BOOTLOADER                       BKP_DR1          /* Booloader enter*/
+#endif
+
+#define FW_VERSION                                  "2.1.0"
+#define SK_NAME                                     "SX12xxEiger"
+
+/*!
+ * Functions return codes definition
+ */
+typedef enum
+{
+    SX_OK,
+    SX_ERROR,
+    SX_BUSY,
+    SX_EMPTY,
+    SX_DONE,
+    SX_TIMEOUT,
+    SX_UNSUPPORTED,
+    SX_WAIT,
+    SX_CLOSE,
+    SX_YES,
+    SX_NO,          
+}tReturnCodes;
+
+extern volatile uint32_t TickCounter;
+
+/**
+  * @brief   Small printf for GCC/RAISONANCE
+  */
+#ifdef __GNUC__
+/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
+   set to 'Yes') calls __io_putchar() */
+#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
+
+#endif /* __GNUC__ */
+
+/*!
+ * Initializes board peripherals
+ */
+void BoardInit( void );
+
+
+/*!
+ * Delay code execution for "delay" ms
+ */
+void Delay ( uint32_t delay );
+
+/*!
+ * Delay code execution for "delay" s
+ */
+void LongDelay ( uint8_t delay );
+
+/*!
+ * \brief Computes a random number between min and max
+ *
+ * \param [IN] min range minimum value
+ * \param [IN] max range maximum value
+ * \retval random random value in range min..max
+ */
+uint32_t randr( uint32_t min, uint32_t max );
+
+#endif // __SX12XXEIGER_H__

+ 65 - 0
app/SX1278/radio/radio.c

@@ -0,0 +1,65 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       radio.c
+ * \brief      Generic radio driver ( radio abstraction )
+ *
+ * \version    2.0.0 
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ *
+ * Last modified by Gregory Cristian on Apr 25 2013
+ */
+#include "platform.h"
+
+#include "radio.h"
+
+#if defined( USE_SX1232_RADIO )
+    #include "sx1232.h"
+#elif defined( USE_SX1272_RADIO )
+    #include "sx1272.h"
+#elif defined( USE_SX1276_RADIO )
+    #include "sx1276.h"
+#else
+    #error "Missing define: USE_XXXXXX_RADIO (ie. USE_SX1272_RADIO)"
+#endif    
+
+tRadioDriver RadioDriver;
+
+tRadioDriver* RadioDriverInit( void )
+{
+#if defined( USE_SX1232_RADIO )
+    RadioDriver.Init = SX1232Init;
+    RadioDriver.Reset = SX1232Reset;
+    RadioDriver.StartRx = SX1232StartRx;
+    RadioDriver.GetRxPacket = SX1232GetRxPacket;
+    RadioDriver.SetTxPacket = SX1232SetTxPacket;
+    RadioDriver.Process = SX1232Process;
+#elif defined( USE_SX1272_RADIO )
+    RadioDriver.Init = SX1272Init;
+    RadioDriver.Reset = SX1272Reset;
+    RadioDriver.StartRx = SX1272StartRx;
+    RadioDriver.GetRxPacket = SX1272GetRxPacket;
+    RadioDriver.SetTxPacket = SX1272SetTxPacket;
+    RadioDriver.Process = SX1272Process;
+#elif defined( USE_SX1276_RADIO )
+    RadioDriver.Init = SX1276Init;
+    RadioDriver.Reset = SX1276Reset;
+    RadioDriver.StartRx = SX1276StartRx;
+    RadioDriver.GetRxPacket = SX1276GetRxPacket;
+    RadioDriver.SetTxPacket = SX1276SetTxPacket;
+    RadioDriver.Process = SX1276Process;
+#else
+    #error "Missing define: USE_XXXXXX_RADIO (ie. USE_SX1272_RADIO)"
+#endif    
+
+    return &RadioDriver;
+}

+ 67 - 0
app/SX1278/radio/radio.h

@@ -0,0 +1,67 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       radio.h
+ * \brief      Generic radio driver ( radio abstraction )
+ *
+ * \version    2.0.B2 
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ *
+ * Last modified by Gregory Cristian on Apr 25 2013
+ */
+#ifndef __RADIO_H__
+#define __RADIO_H__
+
+
+/*!
+ * SX1272 and SX1276 General parameters definition
+ */
+#define LORA                                        1         // [0: OFF, 1: ON]
+
+/*!
+ * RF process function return codes
+ */
+typedef enum
+{
+    RF_IDLE,
+    RF_BUSY,
+    RF_RX_DONE,
+    RF_RX_TIMEOUT,
+    RF_TX_DONE,
+    RF_TX_TIMEOUT,
+    RF_LEN_ERROR,
+    RF_CHANNEL_EMPTY,
+    RF_CHANNEL_ACTIVITY_DETECTED,
+}tRFProcessReturnCodes;
+
+/*!
+ * Radio driver structure defining the different function pointers
+ */
+typedef struct sRadioDriver
+{
+    void ( *Init )( void );
+    void ( *Reset )( void );
+    void ( *StartRx )( void );
+    void ( *GetRxPacket )( void *buffer, uint16_t *size );
+    void ( *SetTxPacket )( const void *buffer, uint16_t size );
+    uint32_t ( *Process )( void );
+}tRadioDriver;
+
+/*!
+ * \brief Initializes the RadioDriver structure with specific radio
+ *        functions.
+ *
+ * \retval radioDriver Pointer to the radio driver variable
+ */
+tRadioDriver* RadioDriverInit( void );
+
+#endif // __RADIO_H__

+ 606 - 0
app/SX1278/radio/sx1276-Fsk.c

@@ -0,0 +1,606 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx1276.c
+ * \brief      SX1276 RF chip driver
+ *
+ * \version    2.0.0 
+ * \date       May 6 2013
+ * \author     Gregory Cristian
+ *
+ * Last modified by Miguel Luis on Jun 19 2013
+ */
+#include <string.h>
+#include <math.h>
+
+#include "platform.h"
+
+#if defined( USE_SX1276_RADIO )
+
+#include "radio.h"
+
+#include "sx1276-Hal.h"
+#include "sx1276.h"
+
+#include "sx1276-FskMisc.h"
+#include "sx1276-Fsk.h"
+
+// Default settings
+tFskSettings FskSettings = 
+{
+    870000000,      // RFFrequency
+    9600,           // Bitrate
+    50000,          // Fdev
+    20,             // Power
+    100000,         // RxBw
+    150000,         // RxBwAfc
+    true,           // CrcOn
+    true,           // AfcOn    
+    255             // PayloadLength (set payload size to the maximum for variable mode, else set the exact payload length)
+};
+
+/*!
+ * SX1276 FSK registers variable
+ */
+tSX1276* SX1276;
+
+/*!
+ * Local RF buffer for communication support
+ */
+static uint8_t RFBuffer[RF_BUFFER_SIZE];
+
+/*!
+ * Chunk size of data write in buffer 
+ */
+static uint8_t DataChunkSize = 32;
+
+
+/*!
+ * RF state machine variable
+ */
+static uint8_t RFState = RF_STATE_IDLE;
+
+/*!
+ * Rx management support variables
+ */
+
+/*!
+ * PacketTimeout holds the RF packet timeout
+ * SyncSize = [0..8]
+ * VariableSize = [0;1]
+ * AddressSize = [0;1]
+ * PayloadSize = [0..RF_BUFFER_SIZE]
+ * CrcSize = [0;2]
+ * PacketTimeout = ( ( 8 * ( VariableSize + AddressSize + PayloadSize + CrcSize ) / BR ) * 1000.0 ) + 1
+ * Computed timeout is in miliseconds
+ */
+static uint32_t PacketTimeout;
+
+/*!
+ * Preamble2SyncTimeout
+ * Preamble2SyncTimeout = ( ( 8 * ( PremableSize + SyncSize ) / RFBitrate ) * 1000.0 ) + 1
+ * Computed timeout is in miliseconds
+ */
+static uint32_t Preamble2SyncTimeout;
+
+static bool PreambleDetected = false;
+static bool SyncWordDetected = false;
+static bool PacketDetected = false;
+static uint16_t RxPacketSize = 0;
+static uint8_t RxBytesRead = 0;
+static uint8_t TxBytesSent = 0;
+static double RxPacketRssiValue;
+static uint32_t RxPacketAfcValue;
+static uint8_t RxGain = 1;
+static uint32_t RxTimeoutTimer = 0;
+static uint32_t Preamble2SyncTimer = 0;
+
+/*!
+ * Tx management support variables
+ */
+static uint16_t TxPacketSize = 0;
+static uint32_t TxTimeoutTimer = 0;
+
+void SX1276FskInit( void )
+{
+    RFState = RF_STATE_IDLE;
+
+    SX1276FskSetDefaults( );
+    
+    SX1276ReadBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
+
+    // Set the device in FSK mode and Sleep Mode
+    SX1276->RegOpMode = RF_OPMODE_MODULATIONTYPE_FSK | RF_OPMODE_SLEEP;
+    SX1276Write( REG_OPMODE, SX1276->RegOpMode );
+
+    SX1276->RegPaRamp = RF_PARAMP_MODULATIONSHAPING_01;
+    SX1276Write( REG_PARAMP, SX1276->RegPaRamp );
+
+    SX1276->RegLna = RF_LNA_GAIN_G1;
+    SX1276Write( REG_LNA, SX1276->RegLna );
+
+    if( FskSettings.AfcOn == true )
+    {
+        SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_ON |
+                              RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
+    }
+    else
+    {
+        SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_OFF |
+                              RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
+    }
+
+    SX1276->RegPreambleLsb = 8;
+    
+    SX1276->RegPreambleDetect = RF_PREAMBLEDETECT_DETECTOR_ON | RF_PREAMBLEDETECT_DETECTORSIZE_2 |
+                                RF_PREAMBLEDETECT_DETECTORTOL_10;
+
+    SX1276->RegRssiThresh = 0xFF;
+
+    SX1276->RegSyncConfig = RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON | RF_SYNCCONFIG_PREAMBLEPOLARITY_AA |
+                            RF_SYNCCONFIG_SYNC_ON |
+                            RF_SYNCCONFIG_SYNCSIZE_4;
+
+    SX1276->RegSyncValue1 = 0x69;
+    SX1276->RegSyncValue2 = 0x81;
+    SX1276->RegSyncValue3 = 0x7E;
+    SX1276->RegSyncValue4 = 0x96;
+
+    SX1276->RegPacketConfig1 = RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RF_PACKETCONFIG1_DCFREE_OFF |
+                               ( FskSettings.CrcOn << 4 ) | RF_PACKETCONFIG1_CRCAUTOCLEAR_ON |
+                               RF_PACKETCONFIG1_ADDRSFILTERING_OFF | RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT;
+    SX1276FskGetPacketCrcOn( ); // Update CrcOn on FskSettings
+
+    SX1276->RegPayloadLength = FskSettings.PayloadLength;
+
+    // we can now update the registers with our configuration
+    SX1276WriteBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
+
+    // then we need to set the RF settings 
+    SX1276FskSetRFFrequency( FskSettings.RFFrequency );
+    SX1276FskSetBitrate( FskSettings.Bitrate );
+    SX1276FskSetFdev( FskSettings.Fdev );
+
+    SX1276FskSetDccBw( &SX1276->RegRxBw, 0, FskSettings.RxBw );
+    SX1276FskSetDccBw( &SX1276->RegAfcBw, 0, FskSettings.RxBwAfc );
+    SX1276FskSetRssiOffset( 0 );
+
+#if( ( MODULE_SX1276RF1IAS == 1 ) || ( MODULE_SX1276RF1KAS == 1 ) )
+    if( FskSettings.RFFrequency > 860000000 )
+    {
+        SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_RFO );
+        SX1276FskSetPa20dBm( false );
+        FskSettings.Power = 14;
+        SX1276FskSetRFPower( FskSettings.Power );
+    }
+    else
+    {
+        SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_PABOOST );
+        SX1276FskSetPa20dBm( true );
+        FskSettings.Power = 20;
+        SX1276FskSetRFPower( FskSettings.Power );
+    } 
+#elif( MODULE_SX1276RF1JAS == 1 )
+    if( FskSettings.RFFrequency > 860000000 )
+    {
+        SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_PABOOST );
+        SX1276FskSetPa20dBm( true );
+        FskSettings.Power = 20;
+        SX1276FskSetRFPower( FskSettings.Power );
+    }
+    else
+    {
+        SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_RFO );
+        SX1276FskSetPa20dBm( false );
+        FskSettings.Power = 14;
+        SX1276FskSetRFPower( FskSettings.Power );
+    } 
+#endif
+
+    SX1276FskSetOpMode( RF_OPMODE_STANDBY );
+
+    // Calibrate the HF
+    SX1276FskRxCalibrate( );
+}
+
+void SX1276FskSetDefaults( void )
+{
+    // REMARK: See SX1276 datasheet for modified default values.
+
+    SX1276Read( REG_VERSION, &SX1276->RegVersion );
+}
+
+void SX1276FskSetOpMode( uint8_t opMode )
+{
+    static uint8_t opModePrev = RF_OPMODE_STANDBY;
+    static bool antennaSwitchTxOnPrev = true;
+    bool antennaSwitchTxOn = false;
+
+    opModePrev = SX1276->RegOpMode & ~RF_OPMODE_MASK;
+
+    if( opMode != opModePrev )
+    {
+        if( opMode == RF_OPMODE_TRANSMITTER )
+        {
+            antennaSwitchTxOn = true;
+        }
+        else
+        {
+            antennaSwitchTxOn = false;
+        }
+        if( antennaSwitchTxOn != antennaSwitchTxOnPrev )
+        {
+            antennaSwitchTxOnPrev = antennaSwitchTxOn;
+            RXTX( antennaSwitchTxOn ); // Antenna switch control
+        }
+        SX1276->RegOpMode = ( SX1276->RegOpMode & RF_OPMODE_MASK ) | opMode;
+
+        SX1276Write( REG_OPMODE, SX1276->RegOpMode );        
+    }
+}
+
+uint8_t SX1276FskGetOpMode( void )
+{
+    SX1276Read( REG_OPMODE, &SX1276->RegOpMode );
+    
+    return SX1276->RegOpMode & ~RF_OPMODE_MASK;
+}
+
+int32_t SX1276FskReadFei( void )
+{
+    SX1276ReadBuffer( REG_FEIMSB, &SX1276->RegFeiMsb, 2 );                          // Reads the FEI value
+
+    return ( int32_t )( double )( ( ( uint16_t )SX1276->RegFeiMsb << 8 ) | ( uint16_t )SX1276->RegFeiLsb ) * ( double )FREQ_STEP;
+}
+
+int32_t SX1276FskReadAfc( void )
+{
+    SX1276ReadBuffer( REG_AFCMSB, &SX1276->RegAfcMsb, 2 );                            // Reads the AFC value
+    return ( int32_t )( double )( ( ( uint16_t )SX1276->RegAfcMsb << 8 ) | ( uint16_t )SX1276->RegAfcLsb ) * ( double )FREQ_STEP;
+}
+
+uint8_t SX1276FskReadRxGain( void )
+{
+    SX1276Read( REG_LNA, &SX1276->RegLna );
+    return( SX1276->RegLna >> 5 ) & 0x07;
+}
+
+double SX1276FskReadRssi( void )
+{
+    SX1276Read( REG_RSSIVALUE, &SX1276->RegRssiValue );                               // Reads the RSSI value
+
+    return -( double )( ( double )SX1276->RegRssiValue / 2.0 );
+}
+
+uint8_t SX1276FskGetPacketRxGain( void )
+{
+    return RxGain;
+}
+
+double SX1276FskGetPacketRssi( void )
+{
+    return RxPacketRssiValue;
+}
+
+uint32_t SX1276FskGetPacketAfc( void )
+{
+    return RxPacketAfcValue;
+}
+
+void SX1276FskStartRx( void )
+{
+    SX1276FskSetRFState( RF_STATE_RX_INIT );
+}
+
+void SX1276FskGetRxPacket( void *buffer, uint16_t *size )
+{
+    *size = RxPacketSize;
+    RxPacketSize = 0;
+    memcpy( ( void * )buffer, ( void * )RFBuffer, ( size_t )*size );
+}
+
+void SX1276FskSetTxPacket( const void *buffer, uint16_t size )
+{
+    TxPacketSize = size;
+    memcpy( ( void * )RFBuffer, buffer, ( size_t )TxPacketSize ); 
+
+    RFState = RF_STATE_TX_INIT;
+}
+
+// Remark: SX1276 must be fully initialized before calling this function
+uint16_t SX1276FskGetPacketPayloadSize( void )
+{
+    uint16_t syncSize;
+    uint16_t variableSize;
+    uint16_t addressSize;
+    uint16_t payloadSize;
+    uint16_t crcSize;
+
+    syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
+    variableSize = ( ( SX1276->RegPacketConfig1 & 0x80 ) == 0x80 ) ? 1 : 0;
+    addressSize = ( ( SX1276->RegPacketConfig1 & 0x06 ) != 0x00 ) ? 1 : 0;
+    payloadSize = SX1276->RegPayloadLength;
+    crcSize = ( ( SX1276->RegPacketConfig1 & 0x10 ) == 0x10 ) ? 2 : 0;
+    
+    return syncSize + variableSize + addressSize + payloadSize + crcSize;
+}
+
+// Remark: SX1276 must be fully initialized before calling this function
+uint16_t SX1276FskGetPacketHeaderSize( void )
+{
+    uint16_t preambleSize;
+    uint16_t syncSize;
+
+    preambleSize = ( ( uint16_t )SX1276->RegPreambleMsb << 8 ) | ( uint16_t )SX1276->RegPreambleLsb;
+    syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
+    
+    return preambleSize + syncSize;
+}
+
+uint8_t SX1276FskGetRFState( void )
+{
+    return RFState;
+}
+
+void SX1276FskSetRFState( uint8_t state )
+{
+    RFState = state;
+}
+
+uint32_t SX1276FskProcess( void )
+{
+    uint32_t result = RF_BUSY;
+
+    switch( RFState )
+    {
+    case RF_STATE_IDLE:
+        break;
+    // Rx management
+    case RF_STATE_RX_INIT:
+        // DIO mapping setup
+        if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_ON ) == RF_PACKETCONFIG1_CRC_ON )
+        {
+            //                           CrcOk,                   FifoLevel,               SyncAddr,               FifoEmpty
+            SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_01 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_11 | RF_DIOMAPPING1_DIO3_00;
+        }
+        else
+        {
+            //                           PayloadReady,            FifoLevel,               SyncAddr,               FifoEmpty
+            SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_00 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_11 | RF_DIOMAPPING1_DIO3_00;
+        }
+        //                          Preamble,                   Data
+        SX1276->RegDioMapping2 = RF_DIOMAPPING2_DIO4_11 | RF_DIOMAPPING2_DIO5_10 | RF_DIOMAPPING2_MAP_PREAMBLEDETECT;
+        SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
+
+        SX1276FskSetOpMode( RF_OPMODE_RECEIVER );
+    
+        memset( RFBuffer, 0, ( size_t )RF_BUFFER_SIZE );
+
+        PacketTimeout = ( uint16_t )( round( ( 8.0 * ( ( double )SX1276FskGetPacketPayloadSize( ) ) / ( double )FskSettings.Bitrate ) * 1000.0 ) + 1.0 );
+        PacketTimeout = PacketTimeout + ( PacketTimeout >> 1 ); // Set the Packet timeout as 1.5 times the full payload transmission time
+
+        Preamble2SyncTimeout = PacketTimeout;
+
+        Preamble2SyncTimer = RxTimeoutTimer = GET_TICK_COUNT( );
+
+        SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | 0x20; // 32 bytes of data
+        SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
+
+        PreambleDetected = false;
+        SyncWordDetected = false;
+        PacketDetected = false;
+        RxBytesRead = 0;
+        RxPacketSize = 0;
+        RFState = RF_STATE_RX_SYNC;
+        break;
+    case RF_STATE_RX_SYNC:
+        if( ( DIO4 == 1 ) && ( PreambleDetected == false ) )// Preamble
+        {
+            PreambleDetected = true;
+            Preamble2SyncTimer = GET_TICK_COUNT( );
+        }
+        if( ( DIO2 == 1 ) && ( PreambleDetected == true ) && ( SyncWordDetected == false ) ) // SyncAddr
+        {
+            SyncWordDetected = true;
+        
+            RxPacketRssiValue = SX1276FskReadRssi( );
+
+            RxPacketAfcValue = SX1276FskReadAfc( );
+            RxGain = SX1276FskReadRxGain( );
+        
+            Preamble2SyncTimer = RxTimeoutTimer = GET_TICK_COUNT( );
+
+            RFState = RF_STATE_RX_RUNNING;
+        }
+
+        // Preamble 2 SyncAddr timeout
+        if( ( SyncWordDetected == false ) && ( PreambleDetected == true ) && ( ( GET_TICK_COUNT( ) - Preamble2SyncTimer ) > Preamble2SyncTimeout ) )
+        {
+            RFState = RF_STATE_RX_INIT;
+            SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
+        }
+        if( ( SyncWordDetected == false ) &&
+            ( PreambleDetected == false ) &&
+            ( PacketDetected == false ) &&
+            ( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout ) )
+        {
+            RFState = RF_STATE_RX_TIMEOUT;
+        }
+        break;
+    case RF_STATE_RX_RUNNING:
+        if( RxPacketSize > RF_BUFFER_SIZE_MAX )
+        {
+            RFState = RF_STATE_RX_LEN_ERROR;
+            break;
+        }
+#if 1
+        if( DIO1 == 1 ) // FifoLevel
+        {
+            if( ( RxPacketSize == 0 ) && ( RxBytesRead == 0 ) ) // Read received packet size
+            {
+                if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
+                {
+                    SX1276ReadFifo( ( uint8_t* )&RxPacketSize, 1 );
+                }
+                else
+                {
+                    RxPacketSize = SX1276->RegPayloadLength;
+                }
+            }
+
+            if( ( RxPacketSize - RxBytesRead ) > ( SX1276->RegFifoThresh & 0x3F ) )
+            {
+                SX1276ReadFifo( ( RFBuffer + RxBytesRead ), ( SX1276->RegFifoThresh & 0x3F ) );
+                RxBytesRead += ( SX1276->RegFifoThresh & 0x3F );
+            }
+            else
+            {
+                SX1276ReadFifo( ( RFBuffer + RxBytesRead ), RxPacketSize - RxBytesRead );
+                RxBytesRead += ( RxPacketSize - RxBytesRead );
+            }
+        }
+#endif
+        if( DIO0 == 1 ) // PayloadReady/CrcOk
+        {
+            RxTimeoutTimer = GET_TICK_COUNT( );
+            if( ( RxPacketSize == 0 ) && ( RxBytesRead == 0 ) ) // Read received packet size
+            {
+                if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
+                {
+                    SX1276ReadFifo( ( uint8_t* )&RxPacketSize, 1 );
+                }
+                else
+                {
+                    RxPacketSize = SX1276->RegPayloadLength;
+                }
+                SX1276ReadFifo( RFBuffer + RxBytesRead, RxPacketSize - RxBytesRead );
+                RxBytesRead += ( RxPacketSize - RxBytesRead );
+                PacketDetected = true;
+                RFState = RF_STATE_RX_DONE;
+            }
+            else
+            {
+                SX1276ReadFifo( RFBuffer + RxBytesRead, RxPacketSize - RxBytesRead );
+                RxBytesRead += ( RxPacketSize - RxBytesRead );
+                PacketDetected = true;
+                RFState = RF_STATE_RX_DONE;
+            }
+        }
+        
+        // Packet timeout
+        if( ( PacketDetected == false ) && ( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout ) )
+        {
+            RFState = RF_STATE_RX_TIMEOUT;
+        }
+        break;
+    case RF_STATE_RX_DONE:
+        RxBytesRead = 0;
+        RFState = RF_STATE_RX_INIT;
+        result = RF_RX_DONE;
+        break;
+    case RF_STATE_RX_TIMEOUT:
+        RxBytesRead = 0;
+        RxPacketSize = 0;
+        SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
+        RFState = RF_STATE_RX_INIT;
+        result = RF_RX_TIMEOUT;
+        break;
+    case RF_STATE_RX_LEN_ERROR:
+        RxBytesRead = 0;
+        RxPacketSize = 0;
+        SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
+        RFState = RF_STATE_RX_INIT;
+        result = RF_LEN_ERROR;
+        break;
+    // Tx management
+    case RF_STATE_TX_INIT:
+        // Packet DIO mapping setup
+        //                           PacketSent,               FifoLevel,              FifoFull,               TxReady
+        SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_00 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_00 | RF_DIOMAPPING1_DIO3_01;
+        //                           LowBat,                   Data
+        SX1276->RegDioMapping2 = RF_DIOMAPPING2_DIO4_00 | RF_DIOMAPPING2_DIO5_10;
+        SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
+
+        SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | 0x18; // 24 bytes of data
+        SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
+
+        SX1276FskSetOpMode( RF_OPMODE_TRANSMITTER );
+        RFState = RF_STATE_TX_READY_WAIT;
+        TxBytesSent = 0;
+        break;
+    case RF_STATE_TX_READY_WAIT:
+        if( DIO3 == 1 )    // TxReady
+        {
+            if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
+            {
+                SX1276WriteFifo( ( uint8_t* )&TxPacketSize, 1 );
+            }
+            
+            if( ( TxPacketSize > 0 ) && ( TxPacketSize <= 64 ) )
+            {
+                DataChunkSize = TxPacketSize;
+            }
+            else
+            {
+                DataChunkSize = 32;
+            }
+            
+            SX1276WriteFifo( RFBuffer, DataChunkSize );
+            TxBytesSent += DataChunkSize;
+            TxTimeoutTimer = GET_TICK_COUNT( );
+            RFState = RF_STATE_TX_RUNNING;
+        }
+        break;
+
+    case RF_STATE_TX_RUNNING:
+        if( DIO1 == 0 )    // FifoLevel below thresold
+        {  
+            if( ( TxPacketSize - TxBytesSent ) > DataChunkSize )
+            {
+                SX1276WriteFifo( ( RFBuffer + TxBytesSent ), DataChunkSize );
+                TxBytesSent += DataChunkSize;
+            }
+            else 
+            {
+                // we write the last chunk of data
+                SX1276WriteFifo( RFBuffer + TxBytesSent, TxPacketSize - TxBytesSent );
+                TxBytesSent += TxPacketSize - TxBytesSent;
+            }
+        }
+
+        if( DIO0 == 1 ) // PacketSent
+        {
+            TxTimeoutTimer = GET_TICK_COUNT( );
+            RFState = RF_STATE_TX_DONE;
+            SX1276FskSetOpMode( RF_OPMODE_STANDBY );
+        }
+         
+        // Packet timeout
+        if( ( GET_TICK_COUNT( ) - TxTimeoutTimer ) > TICK_RATE_MS( 1000 ) )
+        {
+            RFState = RF_STATE_TX_TIMEOUT;
+        }
+        break;
+    case RF_STATE_TX_DONE:
+        RFState = RF_STATE_IDLE;
+        result = RF_TX_DONE;
+        break;
+    case RF_STATE_TX_TIMEOUT:
+        RFState = RF_STATE_IDLE;
+        result = RF_TX_TIMEOUT;
+        break;
+    default:
+        break;
+    }
+    return result;
+}
+
+#endif // USE_SX1276_RADIO

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1460 - 0
app/SX1278/radio/sx1276-Fsk.h


+ 521 - 0
app/SX1278/radio/sx1276-FskMisc.c

@@ -0,0 +1,521 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx1276-FskMisc.c
+ * \brief      SX1276 RF chip high level functions driver
+ *
+ * \remark     Optional support functions.
+ *             These functions are defined only to easy the change of the
+ *             parameters.
+ *             For a final firmware the radio parameters will be known so
+ *             there is no need to support all possible parameters.
+ *             Removing these functions will greatly reduce the final firmware
+ *             size.
+ *
+ * \version    2.0.0 
+ * \date       May 6 2013
+ * \author     Gregory Cristian
+ *
+ * Last modified by Miguel Luis on Jun 19 2013
+ */
+//#include <math.h>
+
+#include "platform.h"
+
+#if defined( USE_SX1276_RADIO )
+
+#include "sx1276-Hal.h"
+#include "sx1276.h"
+
+#include "sx1276-Fsk.h"
+#include "sx1276-FskMisc.h"
+
+extern tFskSettings FskSettings;
+
+void SX1276FskSetRFFrequency( uint32_t freq )
+{
+    FskSettings.RFFrequency = freq;
+
+    freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP );
+    SX1276->RegFrfMsb = ( uint8_t )( ( freq >> 16 ) & 0xFF );
+    SX1276->RegFrfMid = ( uint8_t )( ( freq >> 8 ) & 0xFF );
+    SX1276->RegFrfLsb = ( uint8_t )( freq & 0xFF );
+    SX1276WriteBuffer( REG_FRFMSB, &SX1276->RegFrfMsb, 3 );
+}
+
+uint32_t SX1276FskGetRFFrequency( void )
+{
+    SX1276ReadBuffer( REG_FRFMSB, &SX1276->RegFrfMsb, 3 );
+    FskSettings.RFFrequency = ( ( uint32_t )SX1276->RegFrfMsb << 16 ) | ( ( uint32_t )SX1276->RegFrfMid << 8 ) | ( ( uint32_t )SX1276->RegFrfLsb );
+    FskSettings.RFFrequency = ( uint32_t )( ( double )FskSettings.RFFrequency * ( double )FREQ_STEP );
+
+    return FskSettings.RFFrequency;
+}
+
+void SX1276FskRxCalibrate( void )
+{
+    // the function RadioRxCalibrate is called just after the reset so all register are at their default values
+    uint8_t regPaConfigInitVal;
+    uint32_t initialFreq;
+
+    // save register values;
+    SX1276Read( REG_PACONFIG, &regPaConfigInitVal );
+    initialFreq = SX1276FskGetRFFrequency( );
+
+    // Cut the PA just in case
+    SX1276->RegPaConfig = 0x00; // RFO output, power = -1 dBm
+    SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
+
+    // Set Frequency in HF band
+    SX1276FskSetRFFrequency( 860000000 );
+
+    // Rx chain re-calibration workaround
+    SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );    
+    SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START;
+    SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
+
+    SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
+    // rx_cal_run goes low when calibration in finished
+    while( ( SX1276->RegImageCal & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING )
+    {
+        SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
+    }
+
+    // reload saved values into the registers
+    SX1276->RegPaConfig = regPaConfigInitVal;
+    SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
+
+    SX1276FskSetRFFrequency( initialFreq );
+
+}
+
+void SX1276FskSetBitrate( uint32_t bitrate )
+{
+    FskSettings.Bitrate = bitrate;
+    
+    bitrate = ( uint16_t )( ( double )XTAL_FREQ / ( double )bitrate );
+    SX1276->RegBitrateMsb    = ( uint8_t )( bitrate >> 8 );
+    SX1276->RegBitrateLsb    = ( uint8_t )( bitrate & 0xFF );
+    SX1276WriteBuffer( REG_BITRATEMSB, &SX1276->RegBitrateMsb, 2 );    
+}
+
+uint32_t SX1276FskGetBitrate( void )
+{
+    SX1276ReadBuffer( REG_BITRATEMSB, &SX1276->RegBitrateMsb, 2 );
+    FskSettings.Bitrate = ( ( ( uint32_t )SX1276->RegBitrateMsb << 8 ) | ( ( uint32_t )SX1276->RegBitrateLsb ) );
+    FskSettings.Bitrate = ( uint16_t )( ( double )XTAL_FREQ / ( double )FskSettings.Bitrate );
+
+    return FskSettings.Bitrate;
+}
+
+void SX1276FskSetFdev( uint32_t fdev )
+{
+    FskSettings.Fdev = fdev;
+
+    SX1276Read( REG_FDEVMSB, &SX1276->RegFdevMsb ); 
+
+    fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP );
+    SX1276->RegFdevMsb    = ( ( SX1276->RegFdevMsb & RF_FDEVMSB_FDEV_MASK ) | ( ( ( uint8_t )( fdev >> 8 ) ) & ~RF_FDEVMSB_FDEV_MASK ) );
+    SX1276->RegFdevLsb    = ( uint8_t )( fdev & 0xFF );
+    SX1276WriteBuffer( REG_FDEVMSB, &SX1276->RegFdevMsb, 2 );    
+}
+
+uint32_t SX1276FskGetFdev( void )
+{
+    SX1276ReadBuffer( REG_FDEVMSB, &SX1276->RegFdevMsb, 2 );
+    FskSettings.Fdev = ( ( ( uint32_t )( ( SX1276->RegFdevMsb << 8 ) & ~RF_FDEVMSB_FDEV_MASK ) ) | ( ( uint32_t )SX1276->RegFdevLsb ) );
+    FskSettings.Fdev = ( uint16_t )( ( double )FskSettings.Fdev * ( double )FREQ_STEP );
+
+    return FskSettings.Fdev;
+}
+
+void SX1276FskSetRFPower( int8_t power )
+{
+    SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
+    SX1276Read( REG_PADAC, &SX1276->RegPaDac );
+    
+    if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
+    {
+        if( ( SX1276->RegPaDac & 0x87 ) == 0x87 )
+        {
+            if( power < 5 )
+            {
+                power = 5;
+            }
+            if( power > 20 )
+            {
+                power = 20;
+            }
+            SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
+            SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
+        }
+        else
+        {
+            if( power < 2 )
+            {
+                power = 2;
+            }
+            if( power > 17 )
+            {
+                power = 17;
+            }
+            SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
+            SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
+        }
+    }
+    else
+    {
+        if( power < -1 )
+        {
+            power = -1;
+        }
+        if( power > 14 )
+        {
+            power = 14;
+        }
+        SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
+        SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
+    }
+    SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
+    FskSettings.Power = power;
+}
+
+int8_t SX1276FskGetRFPower( void )
+{
+    SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
+    SX1276Read( REG_PADAC, &SX1276->RegPaDac );
+
+    if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
+    {
+        if( ( SX1276->RegPaDac & 0x07 ) == 0x07 )
+        {
+            FskSettings.Power = 5 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
+        }
+        else
+        {
+            FskSettings.Power = 2 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
+        }
+    }
+    else
+    {
+        FskSettings.Power = -1 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
+    }
+    return FskSettings.Power;
+}
+
+/*!
+ * \brief Computes the Rx bandwidth with the mantisse and exponent
+ *
+ * \param [IN] mantisse Mantisse of the bandwidth value
+ * \param [IN] exponent Exponent of the bandwidth value
+ * \retval bandwidth Computed bandwidth
+ */
+static uint32_t SX1276FskComputeRxBw( uint8_t mantisse, uint8_t exponent )
+{
+    // rxBw
+    if( ( SX1276->RegOpMode & RF_OPMODE_MODULATIONTYPE_FSK ) == RF_OPMODE_MODULATIONTYPE_FSK )
+    {
+        return ( uint32_t )( ( double )XTAL_FREQ / ( mantisse * ( double )pow( 2, exponent + 2 ) ) );
+    }
+    else
+    {
+        return ( uint32_t )( ( double )XTAL_FREQ / ( mantisse * ( double )pow( 2, exponent + 3 ) ) );
+    }
+}
+
+/*!
+ * \brief Computes the mantisse and exponent from the bandwitdh value
+ *
+ * \param [IN] rxBwValue Bandwidth value
+ * \param [OUT] mantisse Mantisse of the bandwidth value
+ * \param [OUT] exponent Exponent of the bandwidth value
+ */
+static void SX1276FskComputeRxBwMantExp( uint32_t rxBwValue, uint8_t* mantisse, uint8_t* exponent )
+{
+    uint8_t tmpExp = 0;
+    uint8_t tmpMant = 0;
+
+    double tmpRxBw = 0;
+    double rxBwMin = 10e6;
+
+    for( tmpExp = 0; tmpExp < 8; tmpExp++ )
+    {
+        for( tmpMant = 16; tmpMant <= 24; tmpMant += 4 )
+        {
+            if( ( SX1276->RegOpMode & RF_OPMODE_MODULATIONTYPE_FSK ) == RF_OPMODE_MODULATIONTYPE_FSK )
+            {
+                tmpRxBw = ( double )XTAL_FREQ / ( tmpMant * ( double )pow( 2, tmpExp + 2 ) );
+            }
+            else
+            {
+                tmpRxBw = ( double )XTAL_FREQ / ( tmpMant * ( double )pow( 2, tmpExp + 3 ) );
+            }
+            if( fabs( tmpRxBw - rxBwValue ) < rxBwMin )
+            {
+                rxBwMin = fabs( tmpRxBw - rxBwValue );
+                *mantisse = tmpMant;
+                *exponent = tmpExp;
+            }
+        }
+    }
+}
+
+void SX1276FskSetDccBw( uint8_t* reg, uint32_t dccValue, uint32_t rxBwValue )
+{
+    uint8_t mantisse = 0;
+    uint8_t exponent = 0;
+    
+    if( reg == &SX1276->RegRxBw )
+    {
+        *reg = ( uint8_t )dccValue & 0x60;
+    }
+    else
+    {
+        *reg = 0;
+    }
+
+    SX1276FskComputeRxBwMantExp( rxBwValue, &mantisse, &exponent );
+
+    switch( mantisse )
+    {
+        case 16:
+            *reg |= ( uint8_t )( 0x00 | ( exponent & 0x07 ) );
+            break;
+        case 20:
+            *reg |= ( uint8_t )( 0x08 | ( exponent & 0x07 ) );
+            break;
+        case 24:
+            *reg |= ( uint8_t )( 0x10 | ( exponent & 0x07 ) );
+            break;
+        default:
+            // Something went terribely wrong
+            break;
+    }
+
+    if( reg == &SX1276->RegRxBw )
+    {
+        SX1276Write( REG_RXBW, *reg );
+        FskSettings.RxBw = rxBwValue;
+    }
+    else
+    {
+        SX1276Write( REG_AFCBW, *reg );
+        FskSettings.RxBwAfc = rxBwValue;
+    }
+}
+
+uint32_t SX1276FskGetBw( uint8_t* reg )
+{
+    uint32_t rxBwValue = 0;
+    uint8_t mantisse = 0;
+    switch( ( *reg & 0x18 ) >> 3 )
+    {
+        case 0:
+            mantisse = 16;
+            break;
+        case 1:
+            mantisse = 20;
+            break;
+        case 2:
+            mantisse = 24;
+            break;
+        default:
+            break;
+    }
+    rxBwValue = SX1276FskComputeRxBw( mantisse, ( uint8_t )*reg & 0x07 );
+    if( reg == &SX1276->RegRxBw )
+    {
+        return FskSettings.RxBw = rxBwValue;
+    }
+    else
+    {
+        return FskSettings.RxBwAfc = rxBwValue;
+    }
+}
+
+void SX1276FskSetPacketCrcOn( bool enable )
+{
+    SX1276Read( REG_PACKETCONFIG1, &SX1276->RegPacketConfig1 );
+    SX1276->RegPacketConfig1 = ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_MASK ) | ( enable << 4 );
+    SX1276Write( REG_PACKETCONFIG1, SX1276->RegPacketConfig1 );
+    FskSettings.CrcOn = enable;
+}
+
+bool SX1276FskGetPacketCrcOn( void )
+{
+    SX1276Read( REG_PACKETCONFIG1, &SX1276->RegPacketConfig1 );
+    FskSettings.CrcOn = ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_ON ) >> 4;
+    return FskSettings.CrcOn;
+}
+
+void SX1276FskSetAfcOn( bool enable )
+{
+    SX1276Read( REG_RXCONFIG, &SX1276->RegRxConfig );
+    SX1276->RegRxConfig = ( SX1276->RegRxConfig & RF_RXCONFIG_AFCAUTO_MASK ) | ( enable << 4 );
+    SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig );
+    FskSettings.AfcOn = enable;
+}
+
+bool SX1276FskGetAfcOn( void )
+{
+    SX1276Read( REG_RXCONFIG, &SX1276->RegRxConfig );
+    FskSettings.AfcOn = ( SX1276->RegRxConfig & RF_RXCONFIG_AFCAUTO_ON ) >> 4;
+    return FskSettings.AfcOn;
+}
+
+void SX1276FskSetPayloadLength( uint8_t value )
+{
+    SX1276->RegPayloadLength = value;
+    SX1276Write( REG_PAYLOADLENGTH, SX1276->RegPayloadLength );
+    FskSettings.PayloadLength = value;
+}
+
+uint8_t SX1276FskGetPayloadLength( void )
+{
+    SX1276Read( REG_PAYLOADLENGTH, &SX1276->RegPayloadLength );
+    FskSettings.PayloadLength = SX1276->RegPayloadLength;
+    return FskSettings.PayloadLength;
+}
+
+void SX1276FskSetPa20dBm( bool enale )
+{
+    SX1276Read( REG_PADAC, &SX1276->RegPaDac );
+    SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
+
+    if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
+    {    
+        if( enale == true )
+        {
+            SX1276->RegPaDac = 0x87;
+        }
+    }
+    else
+    {
+        SX1276->RegPaDac = 0x84;
+    }
+    SX1276Write( REG_PADAC, SX1276->RegPaDac );
+}
+
+bool SX1276FskGetPa20dBm( void )
+{
+    SX1276Read( REG_PADAC, &SX1276->RegPaDac );
+    
+    return ( ( SX1276->RegPaDac & 0x07 ) == 0x07 ) ? true : false;
+}
+
+void SX1276FskSetPAOutput( uint8_t outputPin )
+{
+    SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
+    SX1276->RegPaConfig = (SX1276->RegPaConfig & RF_PACONFIG_PASELECT_MASK ) | outputPin;
+    SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
+}
+
+uint8_t SX1276FskGetPAOutput( void )
+{
+    SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
+    return SX1276->RegPaConfig & ~RF_PACONFIG_PASELECT_MASK;
+}
+
+
+void SX1276FskSetPaRamp( uint8_t value )
+{
+    SX1276Read( REG_PARAMP, &SX1276->RegPaRamp );
+    SX1276->RegPaRamp = ( SX1276->RegPaRamp & RF_PARAMP_MASK ) | ( value & ~RF_PARAMP_MASK );
+    SX1276Write( REG_PARAMP, SX1276->RegPaRamp );
+}
+
+uint8_t SX1276FskGetPaRamp( void )
+{
+    SX1276Read( REG_PARAMP, &SX1276->RegPaRamp );
+    return SX1276->RegPaRamp & ~RF_PARAMP_MASK;
+}
+
+void SX1276FskSetRssiOffset( int8_t offset )
+{
+    SX1276Read( REG_RSSICONFIG, &SX1276->RegRssiConfig );
+    if( offset < 0 )
+    {
+        offset = ( ~offset & 0x1F );
+        offset += 1;
+        offset = -offset;
+    }
+    SX1276->RegRssiConfig |= ( uint8_t )( ( offset & 0x1F ) << 3 );
+    SX1276Write( REG_RSSICONFIG, SX1276->RegRssiConfig );
+}
+
+int8_t SX1276FskGetRssiOffset( void )
+{
+    SX1276Read( REG_RSSICONFIG, &SX1276->RegRssiConfig );
+    int8_t offset = SX1276->RegRssiConfig >> 3;
+    if( ( offset & 0x10 ) == 0x10 )
+    {
+        offset = ( ~offset & 0x1F );
+        offset += 1;
+        offset = -offset;
+    }
+    return offset;
+}
+
+int8_t SX1276FskGetRawTemp( void )
+{
+    int8_t temp = 0;
+    uint8_t previousOpMode;
+    uint32_t startTick;
+    
+    // Enable Temperature reading
+    SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
+    SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_TEMPMONITOR_MASK ) | RF_IMAGECAL_TEMPMONITOR_ON;
+    SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
+
+    // save current Op Mode
+    SX1276Read( REG_OPMODE, &SX1276->RegOpMode );
+    previousOpMode = SX1276->RegOpMode;
+
+    // put device in FSK RxSynth
+    SX1276->RegOpMode = RF_OPMODE_SYNTHESIZER_RX;
+    SX1276Write( REG_OPMODE, SX1276->RegOpMode );
+
+    // Wait 1ms
+    startTick = GET_TICK_COUNT( );
+    while( ( GET_TICK_COUNT( ) - startTick ) < TICK_RATE_MS( 1 ) );  
+
+    // Disable Temperature reading
+    SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
+    SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_TEMPMONITOR_MASK ) | RF_IMAGECAL_TEMPMONITOR_OFF;
+    SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
+
+    // Read temperature
+    SX1276Read( REG_TEMP, &SX1276->RegTemp );
+    
+    temp = SX1276->RegTemp & 0x7F;
+    
+    if( ( SX1276->RegTemp & 0x80 ) == 0x80 )
+    {
+        temp *= -1;
+    }
+
+    // Reload previous Op Mode
+    SX1276Write( REG_OPMODE, previousOpMode );
+
+    return temp;
+}
+
+int8_t SX1276FskCalibreateTemp( int8_t actualTemp )
+{
+    return actualTemp - SX1276FskGetRawTemp( );
+}
+
+int8_t SX1276FskGetTemp( int8_t compensationFactor )
+{
+    return SX1276FskGetRawTemp( ) + compensationFactor;
+}
+
+#endif // USE_SX1276_RADIO

+ 241 - 0
app/SX1278/radio/sx1276-FskMisc.h

@@ -0,0 +1,241 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx1276-FskMisc.h
+ * \brief      SX1276 RF chip high level functions driver
+ *
+ * \remark     Optional support functions.
+ *             These functions are defined only to easy the change of the
+ *             parameters.
+ *             For a final firmware the radio parameters will be known so
+ *             there is no need to support all possible parameters.
+ *             Removing these functions will greatly reduce the final firmware
+ *             size.
+ *
+ * \version    2.0.B2 
+ * \date       May 6 2013
+ * \author     Gregory Cristian
+ *
+ * Last modified by Miguel Luis on Jun 19 2013
+ */
+#ifndef __SX1276_FSK_MISC_H__
+#define __SX1276_FSK_MISC_H__
+
+/*!
+ * \brief Writes the new RF frequency value
+ *
+ * \param [IN] freq New RF frequency value in [Hz]
+ */
+void SX1276FskSetRFFrequency( uint32_t freq );
+
+/*!
+ * \brief Reads the current RF frequency value
+ *
+ * \retval freq Current RF frequency value in [Hz]
+ */
+uint32_t SX1276FskGetRFFrequency( void );
+
+/*!
+ * \brief Calibrate RSSI and I/Q mismatch for HF 
+ *
+ * \retval none
+ */
+void SX1276FskRxCalibrate( void );
+
+/*!
+ * \brief Writes the new bitrate value
+ *
+ * \param [IN] bitrate New bitrate value in [bps]
+ */
+void SX1276FskSetBitrate( uint32_t bitrate );
+
+/*!
+ * \brief Reads the current bitrate value
+ *
+ * \retval bitrate Current bitrate value in [bps]
+ */
+uint32_t SX1276FskGetBitrate( void );
+
+/*!
+ * \brief Writes the new frequency deviation value
+ *
+ * \param [IN] fdev New frequency deviation value in [Hz]
+ */
+void SX1276FskSetFdev( uint32_t fdev );
+
+/*!
+ * \brief Reads the current frequency deviation value
+ *
+ * \retval fdev Current frequency deviation value in [Hz]
+ */
+uint32_t SX1276FskGetFdev( void );
+
+/*!
+ * \brief Writes the new RF output power value
+ *
+ * \param [IN] power New output power value in [dBm]
+ */
+void SX1276FskSetRFPower( int8_t power );
+
+/*!
+ * \brief Reads the current RF output power value
+ *
+ * \retval power Current output power value in [dBm]
+ */
+int8_t SX1276FskGetRFPower( void );
+
+/*!
+ * \brief Writes the DC offset canceller and Rx bandwidth values
+ *
+ * \remark For SX1276 there is no DCC setting. dccValue should be 0
+ *         ie: SX1276SetDccBw( &SX1276.RegRxBw, 0, 62500 );
+ *
+ * \param [IN] reg Register pointer to either SX1231.RegRxBw or SX1231.RegAfcBw
+ * \param [IN] dccValue New DC offset canceller value in [Hz] ( SX1231 only )
+ * \param [IN] rxBwValue New Rx bandwidth value in [Hz]
+ */
+void SX1276FskSetDccBw( uint8_t* reg, uint32_t dccValue, uint32_t rxBwValue );
+
+/*!
+ * \brief Reads the current bandwidth setting
+ *
+ * \param [IN] reg Register pointer to either SX1231.RegRxBw or SX1231.RegAfcBw
+ *
+ * \retval bandwidth Bandwidth value
+ */
+uint32_t SX1276FskGetBw( uint8_t* reg );
+
+/*!
+ * \brief Enables/Disables CRC
+ *
+ * \param [IN] enable CRC enable/disable
+ */
+void SX1276FskSetPacketCrcOn( bool enable );
+
+/*!
+ * \brief Reads the current CRC Enable/Disbale value
+ *
+ * \retval enable Current CRC Enable/Disbale value
+ */
+bool SX1276FskGetPacketCrcOn( void );
+
+/*!
+ * \brief Enables/Disables AFC
+ *
+ * \param [IN] enable AFC enable/disable
+ */
+void SX1276FskSetAfcOn( bool enable );
+
+/*!
+ * \brief Reads the current AFC Enable/Disbale value
+ *
+ * \retval enable Current AFC Enable/Disbale value
+ */
+bool SX1276FskGetAfcOn( void );
+
+/*!
+ * \brief Writes the new payload length value
+ *
+ * \param [IN] value New payload length value
+ */
+void SX1276FskSetPayloadLength( uint8_t value );
+
+/*!
+ * \brief Reads the current payload length value
+ *
+ * \retval value Current payload length value
+ */
+uint8_t SX1276FskGetPayloadLength( void );
+
+/*!
+ * \brief Enables/Disables the 20 dBm PA
+ *
+ * \param [IN] enable [true, false]
+ */
+void SX1276FskSetPa20dBm( bool enale );
+
+/*!
+ * \brief Gets the current 20 dBm PA status
+ *
+ * \retval enable [true, false]
+ */
+bool SX1276FskGetPa20dBm( void );
+
+/*!
+ * \brief Set the RF Output pin 
+ *
+ * \param [IN] RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
+ */
+void SX1276FskSetPAOutput( uint8_t outputPin );
+
+/*!
+ * \brief Gets the used RF Ouptu pin
+ *
+ * \retval RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
+ */
+uint8_t SX1276FskGetPAOutput( void );
+
+/*!
+ * \brief Writes the new PA rise/fall time of ramp up/down value
+ *
+ * \param [IN] value New PaRamp value
+ */
+void SX1276FskSetPaRamp( uint8_t value );
+
+/*!
+ * \brief Reads the current PA rise/fall time of ramp up/down value
+ *
+ * \retval value Current PaRamp value
+ */
+uint8_t SX1276FskGetPaRamp( void );
+
+/*!
+ * \brief Applies an offset to the RSSI. Compensates board components
+ *
+ * \param [IN] offset Offset to be applied (+/-)
+ */
+void SX1276FskSetRssiOffset( int8_t offset );
+
+/*!
+ * \brief Gets the current RSSI offset.
+ *
+ * \retval offset Current offset (+/-)
+ */
+int8_t SX1276FskGetRssiOffset( void );
+
+/*!
+ * \brief Writes the new value for the preamble size
+ *
+ * \param [IN] size New value of pramble size
+ */
+void SX1276FskSetPreambleSize( uint16_t size );
+
+/*!
+ * Reads the raw temperature
+ * \retval temperature New raw temperature reading in 2's complement format
+ */
+int8_t SX1276FskGetRawTemp( void );
+
+/*!
+ * Computes the temperature compensation factor
+ * \param [IN] actualTemp Actual temperature measured by an external device
+ * \retval compensationFactor Computed compensation factor
+ */
+int8_t SX1276FskCalibreateTemp( int8_t actualTemp );
+
+/*!
+ * Gets the actual compensated temperature
+ * \param [IN] compensationFactor Return value of the calibration function
+ * \retval New compensated temperature value
+ */
+int8_t SX1276FskGetTemp( int8_t compensationFactor );
+
+#endif //__SX1276_FSK_MISC_H__

+ 169 - 0
app/SX1278/radio/sx1276-Hal.c

@@ -0,0 +1,169 @@
+/*
+ * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
+ * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+ * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+ * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+ * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ * 
+ * Copyright (C) SEMTECH S.A.
+ */
+/*! 
+ * \file       sx1276-Hal.c
+ * \brief      SX1276 Hardware Abstraction Layer
+ *
+ * \version    2.0.B2 
+ * \date       Nov 21 2012
+ * \author     Miguel Luis
+ *
+ * Last modified by Miguel Luis on Jun 19 2013
+ */
+#include <stdint.h>
+#include <stdbool.h> 
+
+#include "platform.h"
+
+#if defined( USE_SX1276_RADIO )
+
+
+#include "spi.h"
+#include "sx1276-Hal.h"
+
+/*!
+ * SX1276 RESET I/O definitions
+ */
+#define RESET_IOPORT                                GPIOB
+#define RESET_PIN                                   GPIO_Pin_11
+
+
+/*!
+ * SX1276 DIO pins  I/O definitions
+ */
+#define DIO0_IOPORT                                 GPIOG
+#define DIO0_PIN                                    GPIO_Pin_6
+
+void SX1276InitIo( void )
+{
+	RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOB, ENABLE); 
+	// Configure RESET PIN as output
+	GPIO_InitTypeDef GPIO_InitStruct;
+  GPIO_InitStruct.GPIO_Pin = RESET_PIN;
+	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
+	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
+	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
+	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
+	GPIO_Init(RESET_IOPORT, &GPIO_InitStruct);
+	//DIO0_PIN.mode(INPUT);
+	RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOG, ENABLE); 
+  GPIO_InitStruct.GPIO_Pin = DIO0_PIN;
+	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
+	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
+	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+	GPIO_Init(DIO0_IOPORT, &GPIO_InitStruct);
+	spi_config();
+}
+
+void SX1276SetReset( uint8_t state )
+{
+  GPIO_WriteBit( RESET_IOPORT, RESET_PIN,(BitAction) state );	
+}
+
+void SX1276Write( uint8_t addr, uint8_t data )
+{
+    SX1276WriteBuffer( addr, &data, 1 );
+}
+
+void SX1276Read( uint8_t addr, uint8_t *data )
+{
+    SX1276ReadBuffer( addr, data, 1 );
+}
+
+void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+{
+    uint8_t i;
+
+    //NSS = 0;
+		SpiNSSEnable(0);
+    SPI2_ReadWriteByte( addr | 0x80 );
+    for( i = 0; i < size; i++ )
+    {
+        SPI2_ReadWriteByte( buffer[i] );
+    }
+
+    //NSS = 1;
+    SpiNSSEnable(1);
+}
+
+void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+{
+    uint8_t i;
+
+    //NSS = 0;
+    SpiNSSEnable(0);
+
+    SPI2_ReadWriteByte( addr & 0x7F );
+
+    for( i = 0; i < size; i++ )
+    {
+        buffer[i] = SPI2_ReadWriteByte( 0 );
+    }
+
+    //NSS = 1;
+    SpiNSSEnable( 1 );
+}
+
+void SX1276WriteFifo( uint8_t *buffer, uint8_t size )
+{
+    SX1276WriteBuffer( 0, buffer, size );
+}
+
+void SX1276ReadFifo( uint8_t *buffer, uint8_t size )
+{
+    SX1276ReadBuffer( 0, buffer, size );
+}
+
+inline uint8_t SX1276ReadDio0( void )
+{
+    return GPIO_ReadInputDataBit( DIO0_IOPORT, DIO0_PIN );
+}
+
+inline uint8_t SX1276ReadDio1( void )
+{
+    return 1;
+}
+
+inline uint8_t SX1276ReadDio2( void )
+{
+    return 1;
+}
+
+inline uint8_t SX1276ReadDio3( void )
+{
+    return 1;
+}
+
+inline uint8_t SX1276ReadDio4( void )
+{
+    return 1;
+}
+
+inline uint8_t SX1276ReadDio5( void )
+{
+    return 1;
+}
+
+inline void SX1276WriteRxTx( uint8_t txEnable )
+{
+//    if( txEnable != 0 )
+//    {
+//        IoePinOn( FEM_CTX_PIN );
+//        IoePinOff( FEM_CPS_PIN );
+//    }
+//    else
+//    {
+//        IoePinOff( FEM_CTX_PIN );
+//        IoePinOn( FEM_CPS_PIN );
+//    }
+}
+
+#endif // USE_SX1276_RADIO

+ 0 - 0
app/SX1278/radio/sx1276-Hal.h


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio