Quellcode durchsuchen

add peripheral modules

balbekova vor 8 Jahren
Ursprung
Commit
52bcbd4af0

+ 44 - 0
peripheral_modules/inc/attributes.h

@@ -0,0 +1,44 @@
+/**
+ *  Attributes for different compilers
+ * 
+ *	@author 	Tilen Majerle
+ *	@email		tilen@majerle.eu
+ *	@website	http://stm32f4-discovery.com
+ *	@version 	v1.0
+ *	@ide		Keil uVision 5
+ *	@license	GNU GPL v3
+ *	
+ * |----------------------------------------------------------------------
+ * | Copyright (C) Tilen Majerle, 2014
+ * | 
+ * | This program is free software: you can redistribute it and/or modify
+ * | it under the terms of the GNU General Public License as published by
+ * | the Free Software Foundation, either version 3 of the License, or
+ * | any later version.
+ * |  
+ * | This program is distributed in the hope that it will be useful,
+ * | but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * | GNU General Public License for more details.
+ * | 
+ * | You should have received a copy of the GNU General Public License
+ * | along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * |----------------------------------------------------------------------
+ *
+ * Different compilers uses different special keywords for functions/variables. etc.
+ * For this purpose that file has been made. On one place to all possible attributes used in my libs.
+ */
+#ifndef TM_ATTRIBUTES_H
+#define TM_ATTRIBUTES_H
+
+/* Check for GNUC */
+#if defined (__GNUC__)
+	#ifndef __weak		
+		#define __weak   	__attribute__((weak))
+	#endif	/* Weak attribute */
+	#ifndef __packed	
+		#define __packed 	__attribute__((__packed__))
+	#endif	/* Packed attribute */
+#endif
+
+#endif

+ 124 - 0
peripheral_modules/inc/gpio.h

@@ -0,0 +1,124 @@
+#ifndef GPIO_H
+#define GPIO_H
+
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define GLITCH_TIMEOUT 200
+
+
+/* 
+ * Alternative function numbers definitions
+ */
+enum af_n {AF0 = 0, AF1, AF2, AF3, AF4, AF5, AF6, AF7,
+	   AF8, AF9, AF10, AF11, AF12, AF13, AF14, AF15};
+
+
+#define _GPIO_AF_SHIFT   10
+/* Flags for gpio init */
+#define GPIO_IN		0x01
+#define GPIO_IN_PU	0x02
+#define GPIO_OUT	0x04
+#define GPIO_SET	0x08
+#define GPIO_INV	0x10
+#define GPIO_OD		0x20
+#define GPIO_BKP	0x40
+#define GPIO_NOINIT	0x80
+#define GPIO_DIR_CHANGE	0x100
+#define GPIO_AF		0x200
+#define AF_TIM1		((AF1 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM2  	((AF1 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM3  	((AF2 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM4  	((AF2 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM5  	((AF2 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM8  	((AF3 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM9  	((AF3 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM10 	((AF3 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM11 	((AF3 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_I2C1 	((AF4 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_I2C2		((AF4 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_I2C3 	((AF4 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_SPI1 	((AF5 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_SPI2 	((AF5 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_SPI3 	((AF6 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART1 	((AF7 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART2 	((AF7 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART3	((AF7 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART4	((AF8 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART5 	((AF8 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_USART6 	((AF8 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_CAN1 	((AF9 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_CAN2 	((AF9 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM12 	((AF9 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM13 	((AF9 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_TIM14 	((AF9 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_OTG_FS 	((AF10 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_OTG_HS 	((AF10 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_ETH		((AF11 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_FSMC 	((AF12 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_SDIO 	((AF12 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_OTG_HS_FS	((AF12 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_DCMI 	((AF13 << _GPIO_AF_SHIFT) | GPIO_AF)
+#define AF_EVENTOUT	((AF14 << _GPIO_AF_SHIFT) | GPIO_AF)
+
+typedef struct {
+	GPIO_TypeDef *port;
+	uint8_t pin;
+	uint16_t flags;
+} gpio_pindef_t;
+
+#include "board.h"
+
+gpio_pindef_t gpio_pins[GPIO_TOTAL_COUNT];
+
+/*
+ * GPIO register bitmasks
+ */
+#define GPIO_MODER_MASK		0x03
+#define GPIO_TYPER_MASK		0x01
+#define GPIO_SPEEDR_MASK	0x03
+#define GPIO_PUPDR_MASK		0x03
+#define GPIO_AFR_MASK		0x0f
+
+/* 
+ * Port configuration values.
+ * A configuration is passing to gpio_hw_config_pin() bitwise in
+ * a 16-bit 'conf' parameter where low byte representing a port
+ * configuration and high using only for representing a number of an
+ * alternative function (if GPIO_MODE_AF is chosen).
+ * Shifts is using to encode/decode the config bits to/from 'conf'.
+ */
+#define GPIO_MODE_CFG_SHIFT	0
+#define GPIO_TYPE_CFG_SHIFT 	2
+#define GPIO_SPEED_CFG_SHIFT 	4
+#define GPIO_PUPD_CFG_SHIFT	6
+
+#define GPIO_MODE_IN_CFG	(0x00 << GPIO_MODE_CFG_SHIFT)
+#define GPIO_MODE_OUT_CFG	(0x01 << GPIO_MODE_CFG_SHIFT)
+#define GPIO_MODE_AF_CFG	(0x02 << GPIO_MODE_CFG_SHIFT)
+#define GPIO_MODE_ANALOG_CFG	(0x03 << GPIO_MODE_CFG_SHIFT)
+#define GPIO_TYPE_PP_CFG	(0x00 << GPIO_TYPE_CFG_SHIFT)
+#define GPIO_TYPE_OD_CFG	(0x01 << GPIO_TYPE_CFG_SHIFT)
+#define GPIO_SPEED_LOW_CFG	(0x00 << GPIO_SPEED_CFG_SHIFT)
+#define GPIO_SPEED_MED_CFG	(0x01 << GPIO_SPEED_CFG_SHIFT)
+#define GPIO_SPEED_FAST_CFG	(0x02 << GPIO_SPEED_CFG_SHIFT)
+#define GPIO_SPEED_HIGH_CFG	(0x03 << GPIO_SPEED_CFG_SHIFT)
+#define GPIO_PU_CFG		(0x01 << GPIO_PUPD_CFG_SHIFT)
+#define GPIO_PD_CFG		(0x02 << GPIO_PUPD_CFG_SHIFT)
+
+void gpio_init(void);
+void gpio_set(gpio_t pin, bool value);
+bool gpio_get(gpio_t pin);
+bool gpio_is_output(gpio_t pin);
+void gpio_set_direction(gpio_t pin, bool out);
+void gpio_hw_config_pin(GPIO_TypeDef *port, uint8_t pin, uint16_t conf);
+//void gpio_connect_af(GPIO_TypeDef *port, uint8_t pin, uint8_t af);
+void gpio_connect_af(gpio_t id, uint8_t af_n);
+void exti_handler(void);
+void gpio_test(void);
+
+#endif /* GPIO_H */

+ 472 - 0
peripheral_modules/inc/rtc.h

@@ -0,0 +1,472 @@
+/**
+ * @author  Tilen Majerle
+ * @email   tilen@majerle.eu
+ * @website http://stm32f4-discovery.com
+ * @link    http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/
+ * @version 1.7.1
+ * @ide     Keil uVision
+ * @license GNU GPL v3
+ * @brief   Internal RTC library for STM32F4xx devices
+ *	
+@verbatim
+   ----------------------------------------------------------------------
+    Copyright (C) Tilen Majerle, 2015
+    
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    any later version.
+     
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------
+@endverbatim
+ */
+#ifndef TM_RTC_H
+#define TM_RTC_H 171
+
+/* C++ detection */
+#ifdef __cplusplus
+extern C {
+#endif
+
+/**
+ * @addtogroup TM_STM32F4xx_Libraries
+ * @{
+ */
+
+/**
+ * @defgroup TM_RTC
+ * @brief    RTC Library for STM32F4xx devices - http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/
+ * @{
+ *
+ * \par Features
+ *
+@verbatim
+- Support Internal or external clock source
+  - PC14 and PC15 pins are used for external crystal oscillator
+  - STM32F4/429 Discovery does not have RTC crystal onboard. Check board's manual on how to set it up
+- Support wakeup interrupt
+- Support to set 2 internal alarms to trigger interrupts
+  - They can also wake up STM32F4 from any low power mode
+- Get seconds from 01.01.1970 00:00:00
+- Get readable time from seconds from 01.01.1970 00:00:00
+- Support to save/get data in binary or BCD format
+- Support for read/write data to/from RTC backup registers
+- Support for subsecond
+- Support to write data in string format
+- Date and time are checked before saved for valid input data
+- Get days in month and year
+@endverbatim
+ *
+ * \par Pinout for RTC external 32768Hz crystal
+ *
+@verbatim
+ STM32F4XX  Oscillator   Description
+	
+ PC14       OSC1         Oscillator terminal 1
+ PC15       OSC2         Oscillator terminal 2
+@endverbatim
+ *
+ * \par Changelog
+ *
+@verbatim
+ Version 1.7.1
+   - March 25, 2015
+   - Fixed issue with RTC wakeup interrupts
+
+ Version 1.7
+   - March 15, 2015
+   - Added support for read/write data to/from RTC backup registers
+
+ Version 1.6
+   - February 17, 2015
+   - Created typedef TM_RTC_t from TM_RTC_Time_t
+
+ Version 1.5
+   - December 21, 2014
+   - Added 2 new functions:
+      TM_RTC_GetDaysInMonth: returns number of days in specific month and year
+      TM_RTC_GetDaysInYear: returns number of days in specific year
+
+ Version 1.4
+   - December 21, 2014
+   - TM_RTC_SetDateTime now checks for valid input data before save
+   - Added function TM_RTC_SetDateTimeString which allows you to set your
+      date and time using string format
+
+ Version 1.3
+   - December 03, 2014
+   - Fixed bug when reading month in december was set to 0
+
+ Version 1.2
+   - October 27, 2014
+   - Added support to read subseconds from time
+   - This can be used for stopwatch
+
+ Version 1.1
+   - October 20, 2014
+   - Added support for Alarm set
+
+ Version 1.0.2
+   - September 24, 2014
+   - TM_RTC_RequestHandler function has now "__weak" attribute to prevent errors,
+      if function is not implemented by user
+
+ Version 1.0.1
+   - September 01, 2014
+   - Date to unix convert bug fix
+
+ Version 1.0
+   - First release
+@endverbatim
+ *
+ * \par Dependencies
+ *
+@verbatim
+ - STM32F4xx
+ - STM32F4xx RCC
+ - STM32F4xx RTC
+ - STM32F4xx PWR
+ - STM32F4xx EXTI
+ - MISC
+ - defines.h
+ - attributes.h
+@endverbatim
+ */
+#include "stm32f4xx.h"
+#include "attributes.h"
+
+/**
+ * @defgroup TM_RTC_Macros
+ * @brief    Library defines
+ *
+ * All these settings can be overwritten in defines.h file if necessary
+ *
+ * @{
+ */
+
+/* RTC clock is: f_clk = RTCCLK(LSI or LSE) / ((RTC_SYNC_PREDIV + 1) * (RTC_ASYNC_PREDIV + 1)) */
+/* Sync pre division for clock */
+#ifndef RTC_SYNC_PREDIV
+#define RTC_SYNC_PREDIV					0x3FF
+#endif
+/* Async pre division for clock */
+#ifndef RTC_ASYNC_PREDIV
+#define RTC_ASYNC_PREDIV				0x1F
+#endif
+/* NVIC global Priority set */
+#ifndef RTC_PRIORITY
+#define RTC_PRIORITY					0x04
+#endif
+/* Sub priority for wakeup trigger */
+#ifndef RTC_WAKEUP_SUBPRIORITY
+#define RTC_WAKEUP_SUBPRIORITY			0x00
+#endif
+/* Sub priority for alarm trigger */
+#ifndef RTC_ALARM_SUBPRIORITY
+#define RTC_ALARM_SUBPRIORITY			0x01
+#endif
+
+ /**
+ * @}
+ */
+ 
+/**
+ * @defgroup TM_RTC_Typedefs
+ * @brief    Library Typedefs
+ * @{
+ */
+
+/**
+ * @brief  RTC Struct for date/time
+ */
+typedef struct {
+	uint8_t seconds;     /*!< Seconds parameter, from 00 to 59 */
+	uint16_t subseconds; /*!< Subsecond downcounter. When it reaches zero, it's reload value is the same as
+                                 @ref RTC_SYNC_PREDIV, so in our case 0x3FF = 1023, 1024 steps in one second */
+	uint8_t minutes;     /*!< Minutes parameter, from 00 to 59 */
+	uint8_t hours;       /*!< Hours parameter, 24Hour mode, 00 to 23 */
+	uint8_t day;         /*!< Day in a week, from 1 to 7 */
+	uint8_t date;        /*!< Date in a month, 1 to 31 */
+	uint8_t month;       /*!< Month in a year, 1 to 12 */
+	uint8_t year;        /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */
+	uint32_t unix;       /*!< Seconds from 01.01.1970 00:00:00 */
+} TM_RTC_t;
+
+/**
+ * @brief  Backward compatibility for RTC time
+ */
+typedef TM_RTC_t TM_RTC_Time_t;
+
+/**
+ * @brief RTC Result enumeration
+ */
+typedef enum {
+	TM_RTC_Result_Ok,   /*!< Everything OK */
+	TM_RTC_Result_Error /*!< An error occurred */
+} TM_RTC_Result_t;
+
+/**
+ * @brief RTC date and time format
+ */
+typedef enum {
+	TM_RTC_Format_BIN = 0x00, /*!< RTC data in binary format */
+	TM_RTC_Format_BCD         /*!< RTC data in binary-coded decimal format */
+} TM_RTC_Format_t;
+
+/**
+ * @brief  RTC Interrupt enumeration
+ */
+typedef enum {
+	TM_RTC_Int_Disable = 0x00, /*!< Disable RTC wakeup interrupts */
+	TM_RTC_Int_60s,            /*!< RTC Wakeup interrupt every 60 seconds */
+	TM_RTC_Int_30s,            /*!< RTC Wakeup interrupt every 30 seconds */
+	TM_RTC_Int_15s,            /*!< RTC Wakeup interrupt every 15 seconds */
+	TM_RTC_Int_10s,            /*!< RTC Wakeup interrupt every 10 seconds */
+	TM_RTC_Int_5s,             /*!< RTC Wakeup interrupt every 5 seconds */
+	TM_RTC_Int_2s,             /*!< RTC Wakeup interrupt every 2 seconds */
+	TM_RTC_Int_1s,             /*!< RTC Wakeup interrupt every 1 seconds */
+	TM_RTC_Int_500ms,          /*!< RTC Wakeup interrupt every 500 milliseconds */
+	TM_RTC_Int_250ms,          /*!< RTC Wakeup interrupt every 250 milliseconds */
+	TM_RTC_Int_125ms           /*!< RTC Wakeup interrupt every 125 milliseconds */
+} TM_RTC_Int_t;
+
+/**
+ * @brief  Select RTC clock source
+ * @note   Internal clock is not accurate and should not be used in production
+ */
+typedef enum {
+	TM_RTC_ClockSource_Internal = 0x00, /*!< Use internal clock source for RTC (LSI oscillator) */
+	TM_RTC_ClockSource_External         /*!< Use external clock source for RTC (LSE oscillator) */
+} TM_RTC_ClockSource_t;
+
+/**
+ * @brief  RTC Alarm type
+ */
+typedef enum {
+	TM_RTC_AlarmType_DayInWeek, /*!< Trigger alarm every day in a week, days from 1 to 7 (Monday to Sunday) */
+	TM_RTC_AlarmType_DayInMonth /*!< Trigger alarm every month */
+} TM_RTC_AlarmType_t;
+
+/**
+ * @brief  Alarm identifier you will use for Alarm functions
+ */
+typedef enum {
+	TM_RTC_Alarm_A = 0x00, /*!< Work with alarm A */
+	TM_RTC_Alarm_B         /*!< Work with alarm B */
+} TM_RTC_Alarm_t;
+
+/**
+ * @brief  RTC structure for alarm time
+ */
+typedef struct {
+	TM_RTC_AlarmType_t alarmtype; /*!< Alarm type setting. @ref TM_RTC_AlarmType_t for more info */
+	uint8_t seconds;              /*!< Alarm seconds value */
+	uint8_t minutes;              /*!< Alarm minutes value */
+	uint8_t hours;                /*!< Alarm hours value */
+	uint8_t day;                  /*!< Alarm day value. If you select trigger for alarm every week, then this parameter has value between
+                                          1 and 7, representing days in a week, Monday to Sunday
+                                          If you select trigger for alarm every month, then this parameter has value between
+                                          1 - 31, representing days in a month. */
+} TM_RTC_AlarmTime_t;
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup TM_RTC_Functions
+ * @brief    Library Functions
+ * @{
+ */
+
+
+void TM_RTC_SetDataTimeUnix(uint32_t unixTime);
+
+/**
+  * @brief  Кореектировака времени.
+  */
+void TM_RTC_Correction(float utc);
+
+/**
+ * @brief  Initializes RTC and starts counting
+ * @param  source. RTC Clock source @ref TM_RTC_ClockSource_t to be used for RTC
+ * @note   Internal clock source is not so accurate
+ * @note   If you reset your MCU and RTC still has power, it will count independent of MCU status
+ * @retval Returns RTC status.
+ *            - 1: RTC has already been initialized and time is set
+ *            - 0: RTC was now initialized first time. Now you can set your first clock
+ */
+uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source);
+
+/**
+ * @brief  Get number of seconds from date and time since 01.01.1970 00:00:00
+ * @param  *data: Pointer to @ref TM_RTC_t data structure
+ * @retval Calculated seconds from date and time since 01.01.1970 00:00:00
+ */
+uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data);
+
+/**
+ * @brief  Get formatted time from seconds till 01.01.1970 00:00:00
+ *         It fills struct with valid data
+ * @note   Valid if year is greater or equal (>=) than 2000
+ * @param  *data: Pointer to @ref TM_RTC_Time_t struct to store formatted data in
+ * @param  unix: Seconds from 01.01.1970 00:00:00 to calculate user friendly time
+ * @retval None
+ */
+void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix);
+
+/**
+ * @brief  Select RTC wakeup interrupts interval
+ * @note   This function can also be used to disable interrupt
+ * @param  int_value: Look for @ref TM_RTC_Int_t for valid inputs
+ * @retval None
+ */
+void TM_RTC_Interrupts(TM_RTC_Int_t int_value);
+
+/**
+ * @brief  Set date and time to internal RTC registers
+ * @param  *data: Pointer to filled @ref TM_RTC_t structure with date and time
+ * @param  format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration
+ * @retval RTC datetime status @ref TM_RTC_Result_t:
+ *            - @ref TM_RTC_Result_Ok: Date and Time set OK
+ *            - @ref TM_RTC_Result_Error: Date and time is wrong
+ */
+TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format);
+
+/**
+ * @brief  Set date and time using string formatted date time
+ * @note   Valid string format is: <b>dd.mm.YY.x;HH:ii:ss</b>
+ *            - <b>dd</b>: date, 2 digits, decimal
+ *            - <b>mm</b>: month, 2 digits, decimal
+ *            - <b>YY</b>: year, last 2 digits, decimal
+ *            - <b>x</b>: day in a week: 1 digit, 1 = Monday, 7 = Sunday
+ *            - <b>HH</b>: hours, 24-hour mode, 2 digits, decimal
+ *            - <b>ii</b>: minutes, 2 digits, decimal
+ *            - <b>ss</b>: seconds, 2 digits, decimal
+ * @param  *str: Pointer to string with datetime format
+ * @retval RTC datetime status @ref TM_RTC_Result_t:
+ *            - @ref TM_RTC_Result_Ok: Date and Time set OK
+ *            - @ref TM_RTC_Result_Error: Date and time is wrong
+ */
+TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str);
+
+/**
+ * @brief  Get date and time from internal RTC registers
+ * @param  *data: Pointer to @ref TM_RTC_t structure to save data to
+ * @param  format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration
+ * @retval None
+ */
+void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format);
+
+/**
+ * @brief  Get number of days in month
+ * @note   This function also detects if it is leap year and returns different number for February
+ * @param  month: Month number in year, valid numbers are 1 - 12 
+ * @param  year: Year number where you want to get days in month, last 2 digits
+ * @retval Number of days in specific month and year
+ */
+uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year);
+
+/**
+ * @brief  Get number of days in specific year
+ * @note   This function also detects if it is leap year
+ * @param  year: Year number where you want to get days in month, last 2 digits
+ * @retval Number of days in year
+ */
+uint16_t TM_RTC_GetDaysInYear(uint8_t year);
+
+/**
+ * @brief  Write RTC backup register value.
+ *            This method allows you to write 32bit value from backup register 0 - 18.
+ * @note   RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power.
+ *
+ * @note   My library uses register 19 to store info about RTC settings and is not available for USER to store data there.
+ *
+ * @note   RTC HAS to be initialized first before you can use this method.
+ * @param  location: RTC backup register location. 0 to 18 are valid
+ * @param  value: 32-bit long value to be stored in RTC backup register
+ * @retval Value at specific RTC backup register location
+ */
+void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value);
+
+/**
+ * @brief  Read RTC backup register value.
+ *            This method allows you to read 32bit value from backup register 0 - 18.
+ * @note   RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power.
+ *
+ * @note   My library uses register 19 to store info about RTC settings and is not available for USER to store data there.
+ *
+ * @note   RTC HAS to be initialized first before you can use this method.
+ * @param  location: RTC backup register location. 0 to 18 are valid
+ * @retval Value at specific RTC backup register location
+ */
+uint32_t TM_RTC_ReadBackupRegister(uint8_t location);
+
+/**
+ * @brief  Enables alarm A or alarm B
+ * @param  Alarm: Specify which alarm to set. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration
+ * @param  *AlarmTime: Pointer to @ref TM_RTC_AlarmTime_t structure to get data from.
+ * @param  format: RTC date and time format. This parameter can be a value of @ref TM_RTC_Format_t enumeration.
+ * @retval None
+ */
+void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* AlarmTime, TM_RTC_Format_t format);
+
+/**
+ * @brief  Disables specific alarm
+ * @param  Alarm: Select which alarm you want to disable. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration
+ * @retval None
+ */
+void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm);
+
+/**
+ * @brief  RTC Wakeup handler function. Called when wakeup interrupt is triggered
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_RequestHandler(void);
+
+/**
+ * @brief  RTC Alarm A handler function. Called when interrupt is triggered for alarm A
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_AlarmAHandler(void);
+
+/**
+ * @brief  RTC Alarm B handler function. Called when interrupt is triggered for alarm B.
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_AlarmBHandler(void);
+
+/**
+  * @brief  У�тановливает врем� �рабатывани� профилактики �ульфатации дл� отладки
+  * @retval 
+  */
+void RTC_SetDebugProfTime(void);
+
+/**
+  * @brief  Óñòàíîâëèâàåò âðåìÿ ñðàáàòûâàíèÿ ïðîôèëàêòèêè ñóëüôàòàöèè
+  */
+void RTC_SetProfTime(char *date);
+
+/* C++ detection */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 41 - 0
peripheral_modules/inc/usart.h

@@ -0,0 +1,41 @@
+/******************************* (C) LiteMesh **********************************
+ * @module  usart
+ * @file    usart.h
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   Template
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+/* Define to prevent recursive  ----------------------------------------------*/
+#ifndef USART_H
+#define USART_H
+
+/**
+  * @brief  
+  */
+#define USER_USART         USART1
+
+#define UPS_USART         			USART2
+#define UPS_USART_BAUD				115200
+#define	UPS_USART_WORD_LEN			8
+#define	UPS_USART_PARITY			USART_Parity_No
+#define UPS_USART_STOP_BIT			USART_StopBits_1
+
+/**
+  * @brief  
+  */
+void InitUSART(void);
+   
+/**
+  * @brief  
+  * @retval 
+  */
+
+
+#endif /* #ifndef USART_H */
+
+/****************************** (C) LiteMesh ***************** end of file ****/

+ 24 - 0
peripheral_modules/inc/wdg.h

@@ -0,0 +1,24 @@
+/********************************* (C) РОТЕК ***********************************
+ * @module  wdg
+ * @file    wdg.h
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   External watchdog
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+/* Define to prevent recursive  ----------------------------------------------*/
+#ifndef WDG_H
+#define WDG_H
+  
+/**
+  * @brief  Дергаем пином (сброс внешнего WDT)
+  */
+void vTaskWdt(void *pvParameters);
+
+#endif /* #ifndef WDG_H */
+
+/********************************* (C) РОТЕК **********************************/

+ 132 - 0
peripheral_modules/src/gpio.c

@@ -0,0 +1,132 @@
+#include "gpio.h"
+
+gpio_pindef_t gpio_pins[] = {
+	GPIO_TABLE(EXPAND_AS_DEFS)
+};
+
+void gpio_hw_config_pin(GPIO_TypeDef *port, uint8_t pin, uint16_t conf) {
+	uint8_t shift;
+	shift = pin * 2;
+
+	port->MODER &= ~(GPIO_MODER_MASK << shift);
+	port->MODER |= (uint32_t)((conf >> GPIO_MODE_CFG_SHIFT) & GPIO_MODER_MASK) << shift;
+	port->OTYPER &= ~(GPIO_TYPER_MASK << pin);
+	port->OTYPER |= (uint32_t)((conf >> GPIO_TYPE_CFG_SHIFT) & GPIO_TYPER_MASK) << pin;
+	port->OSPEEDR &= ~(GPIO_SPEEDR_MASK << shift);
+	port->OSPEEDR |= (uint32_t)((conf >> GPIO_SPEED_CFG_SHIFT) & GPIO_SPEEDR_MASK) << shift;
+	port->PUPDR &= ~(GPIO_PUPDR_MASK << shift);
+	port->PUPDR |= (uint32_t)((conf >> GPIO_PUPD_CFG_SHIFT) & GPIO_PUPDR_MASK) << shift;
+}
+
+void gpio_connect_af(gpio_t id, uint8_t af_n) {
+	gpio_pindef_t *pin = &gpio_pins[id];
+	uint8_t shift;
+	if (pin->pin < 8) {
+		shift = pin->pin * 4;
+		pin->port->AFR[0] &= ~((uint32_t)GPIO_AFR_MASK << shift);
+		pin->port->AFR[0] |= af_n << shift;
+	}
+	else {
+		shift = (pin->pin - 8) * 4;
+		pin->port->AFR[1] &= ~((uint32_t)GPIO_AFR_MASK << shift);
+		pin->port->AFR[1] |= af_n << shift;
+	}
+}
+
+/*
+ * TODO add analog flag and setup ADC pins in a proper way
+ */
+static void gpio_set_config(gpio_t id) {
+	gpio_pindef_t *pin = &gpio_pins[id];
+	if (pin->flags & GPIO_AF) {
+		uint8_t af_n = (uint8_t)(pin->flags >> _GPIO_AF_SHIFT);
+		gpio_connect_af(id, af_n);
+		gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_AF_CFG | 
+				GPIO_SPEED_HIGH_CFG);
+	}
+	else if (pin->flags & GPIO_IN)
+		gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_IN_CFG | 
+				GPIO_SPEED_HIGH_CFG);
+	else if (pin->flags & GPIO_IN_PU) {
+		gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_IN_CFG | GPIO_PU_CFG |
+				GPIO_SPEED_HIGH_CFG);
+		gpio_set(id, pin->flags & GPIO_SET);
+	}
+	else if (pin->flags & GPIO_OUT) {
+		gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_OUT_CFG |
+				((pin->flags & GPIO_OD) ? 
+				 GPIO_TYPE_OD_CFG : GPIO_TYPE_PP_CFG) |
+				GPIO_SPEED_HIGH_CFG);
+		gpio_set(id, pin->flags & GPIO_SET);
+	}
+}
+
+void gpio_init(void) {
+	uint32_t i;
+
+	GPIO_DeInit(GPIOA);
+	GPIO_DeInit(GPIOB);
+	GPIO_DeInit(GPIOC);
+	GPIO_DeInit(GPIOD);
+	GPIO_DeInit(GPIOE);
+
+	// configure clocks
+	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN |
+			RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN |
+			RCC_AHB1ENR_GPIOEEN;
+
+	// configure gpios
+	for (i = 0; i < GPIO_TOTAL_COUNT; i++) {
+		if (gpio_pins[i].flags & GPIO_NOINIT)
+			continue;
+		else {
+			gpio_set_config(i);
+		}
+	}
+}
+
+void gpio_set(gpio_t pin, bool value) {
+	if (gpio_pins[pin].flags & GPIO_INV)
+		value = !value;
+	if (value)
+		gpio_pins[pin].port->BSRRL = 1 << gpio_pins[pin].pin;
+	else
+		gpio_pins[pin].port->BSRRH = 1 << gpio_pins[pin].pin;
+}
+
+bool gpio_get(gpio_t pin) {
+	bool value;
+	if (gpio_pins[pin].flags & GPIO_NOINIT) {
+		return false;
+	}
+	else {
+		value = (gpio_pins[pin].port->IDR & (1 << gpio_pins[pin].pin)) >> gpio_pins[pin].pin;
+		return (gpio_pins[pin].flags & GPIO_INV) ? !value : value;
+	}
+}
+
+bool gpio_is_output(gpio_t pin) {
+	return (gpio_pins[pin].flags & GPIO_OUT) ? true : false;
+}
+
+void gpio_set_direction(gpio_t pin, bool out) {
+	if (out) {
+		gpio_pins[pin].flags &= ~(GPIO_IN | GPIO_IN_PU);
+		gpio_pins[pin].flags |= GPIO_OUT;
+	}
+	else {
+		gpio_pins[pin].flags &= ~(GPIO_OUT | GPIO_OD);
+		gpio_pins[pin].flags |= GPIO_IN;
+	}
+	gpio_set_config(pin);
+}
+
+void gpio_test() {
+
+}
+
+typedef struct {
+	gpio_pindef_t *gpio;
+	void (*handler)(void);
+} exti_handler_t;
+

+ 864 - 0
peripheral_modules/src/rtc.c

@@ -0,0 +1,864 @@
+/**	
+ * |----------------------------------------------------------------------
+ * | Copyright (C) Tilen Majerle, 2014
+ * | 
+ * | This program is free software: you can redistribute it and/or modify
+ * | it under the terms of the GNU General Public License as published by
+ * | the Free Software Foundation, either version 3 of the License, or
+ * | any later version.
+ * |  
+ * | This program is distributed in the hope that it will be useful,
+ * | but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * | GNU General Public License for more details.
+ * | 
+ * | You should have received a copy of the GNU General Public License
+ * | along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * |----------------------------------------------------------------------
+ */
+#include "rtc.h"
+
+/* Private macros */
+/* Internal status registers for RTC */
+#define RTC_STATUS_REG      			RTC_BKP_DR19 /* Status Register */
+#define RTC_STATUS_INIT_OK  			0x1234       /* RTC initialised */
+#define RTC_STATUS_TIME_OK  			0x4321       /* RTC time OK */
+#define	RTC_STATUS_ZERO					0x0000
+
+/* Internal RTC defines */
+#define TM_RTC_LEAP_YEAR(year) 			((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
+#define TM_RTC_DAYS_IN_YEAR(x)			TM_RTC_LEAP_YEAR(x) ? 366 : 365
+#define TM_RTC_OFFSET_YEAR				1970
+#define TM_RTC_SECONDS_PER_DAY			86400
+#define TM_RTC_SECONDS_PER_HOUR			3600
+#define TM_RTC_SECONDS_PER_MINUTE		60
+#define TM_RTC_BCD2BIN(x)				((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
+#define TM_RTC_CHAR2NUM(x)				((x) - '0')
+#define TM_RTC_CHARISNUM(x)				((x) >= '0' && (x) <= '9')
+
+/* Internal functions */
+void TM_RTC_Config(TM_RTC_ClockSource_t source);
+/* Default RTC status */
+uint32_t TM_RTC_Status = RTC_STATUS_ZERO;
+/* RTC declarations */
+RTC_TimeTypeDef RTC_TimeStruct;
+RTC_InitTypeDef RTC_InitStruct;
+RTC_DateTypeDef RTC_DateStruct;
+NVIC_InitTypeDef NVIC_InitStruct;
+EXTI_InitTypeDef EXTI_InitStruct;
+
+RTC_InitTypeDef   RTC_InitStructure;
+RTC_TimeTypeDef   RTC_TimeStructure;
+RTC_DateTypeDef   RTC_DateStructure;
+
+#define RTC_CLOCK_SOURCE_LSE           /* LSE used as RTC source clock */
+#define FIRST_DATA          0x32F2
+#define RTC_BKP_DR_NUMBER   0x14
+
+__IO uint32_t uwAsynchPrediv = 0;
+__IO uint32_t uwSynchPrediv = 0;
+__IO uint32_t uwTimeDisplay = 0;
+
+uint32_t uwErrorIndex = 0;
+uint32_t uwIndex = 0;
+
+uint32_t aBKPDataReg[RTC_BKP_DR_NUMBER] =
+  {
+    RTC_BKP_DR0, RTC_BKP_DR1, RTC_BKP_DR2, 
+    RTC_BKP_DR3, RTC_BKP_DR4, RTC_BKP_DR5,
+    RTC_BKP_DR6, RTC_BKP_DR7, RTC_BKP_DR8, 
+    RTC_BKP_DR9, RTC_BKP_DR10, RTC_BKP_DR11, 
+    RTC_BKP_DR12, RTC_BKP_DR13, RTC_BKP_DR14, 
+    RTC_BKP_DR15, RTC_BKP_DR16, RTC_BKP_DR17, 
+    RTC_BKP_DR18,  RTC_BKP_DR19
+  };
+
+/* Days in a month */
+uint8_t TM_RTC_Months[2][12] = {
+	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},	/* Not leap year */
+	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}	/* Leap year */
+};
+
+/**
+  * @brief  Writes data to all Backup data registers.
+  * @param  FirstBackupData: data to write to first backup data register.
+  * @retval None
+  */
+static void WriteToBackupReg(uint16_t FirstBackupData)
+{
+  uint32_t index = 0;
+
+  for (index = 0; index < RTC_BKP_DR_NUMBER; index++)
+  {
+    RTC_WriteBackupRegister(aBKPDataReg[index], FirstBackupData + (index * 0x5A));
+  }
+
+}
+
+uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source) 
+{
+  uint32_t status;
+  uint8_t stat = 1;
+  TM_RTC_t datatime;
+	
+  /* Enable PWR peripheral clock */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
+
+  /* Allow access to BKP Domain */
+  PWR_BackupAccessCmd(ENABLE);
+	
+  /* Get RTC status */
+  status = RTC_ReadBackupRegister(RTC_STATUS_REG);
+	
+  if (status == RTC_STATUS_TIME_OK) 
+  {
+    TM_RTC_Status = RTC_STATUS_TIME_OK;
+		
+    /* Start internal clock if we choose internal clock */
+    if (source == TM_RTC_ClockSource_Internal)
+      TM_RTC_Config(TM_RTC_ClockSource_Internal);
+
+    /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
+    RTC_WaitForSynchro();
+		
+    /* Clear interrupt flags */
+    RTC_ClearITPendingBit(RTC_IT_WUT);
+    EXTI->PR = 0x00400000;
+		
+    /* Get date and time */
+    TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
+  } 
+  else if (status == RTC_STATUS_INIT_OK) 
+  {
+    TM_RTC_Status = RTC_STATUS_INIT_OK;
+		
+    /* Start internal clock if we choose internal clock */
+    if (source == TM_RTC_ClockSource_Internal)
+      TM_RTC_Config(TM_RTC_ClockSource_Internal);
+
+    /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
+    RTC_WaitForSynchro();
+		
+    /* Clear interrupt flags */
+    RTC_ClearITPendingBit(RTC_IT_WUT);
+    EXTI->PR = 0x00400000;
+		
+    /* Get date and time */
+    //TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
+  } 
+  else 
+  {
+    TM_RTC_Status = RTC_STATUS_ZERO;
+    /* Return status = 0 -> RTC Never initialized before */
+    stat = RTC_STATUS_ZERO;
+    /* Config RTC */
+	TM_RTC_Config(source);
+		
+    /* Set date and time */
+    datatime.date = 1;
+    datatime.day = 1;
+    datatime.month = 1;
+    datatime.year = 0;
+    datatime.hours = 0;
+    datatime.minutes = 0;
+    datatime.seconds = 0;
+
+    /* Set date and time */
+    TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
+		
+    /* Initialized OK */
+    TM_RTC_Status = RTC_STATUS_INIT_OK;
+  }
+  /* If first time initialized */
+  if (stat == RTC_STATUS_ZERO) 
+	return 0;
+  
+  return TM_RTC_Status;  
+
+}
+
+void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
+{
+  TM_RTC_t data;
+  
+  TM_RTC_GetDateTimeFromUnix(&data, unixTime);
+  TM_RTC_SetDateTime(&data, TM_RTC_Format_BIN);
+}
+
+/**
+  * @brief  Кореектировака времени.
+  * @param  Часовой пояс
+  * @retval 
+  */
+void TM_RTC_Correction(float utc)
+{
+  TM_RTC_t data;
+  TM_RTC_t newData;
+  int      utcSec;
+  uint32_t unixTime;
+  
+  /* Получаем текущее время */
+  TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
+  
+  /* Рассчитываем поправку */
+  utcSec = (int)(3600.0*utc);
+  unixTime = data.unix + utcSec;
+  
+  /* Устанавливаем новое время */
+  TM_RTC_GetDateTimeFromUnix(&newData, unixTime);
+  TM_RTC_SetDateTime(&newData, TM_RTC_Format_BIN);
+}
+
+TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
+	TM_RTC_t tmp;
+	
+	/* Check date and time validation */
+	if (format == TM_RTC_Format_BCD) {
+		tmp.date = TM_RTC_BCD2BIN(data->date);
+		tmp.month = TM_RTC_BCD2BIN(data->month);
+		tmp.year = TM_RTC_BCD2BIN(data->year);
+		tmp.hours = TM_RTC_BCD2BIN(data->hours);
+		tmp.minutes = TM_RTC_BCD2BIN(data->minutes);
+		tmp.seconds = TM_RTC_BCD2BIN(data->seconds);
+		tmp.day = TM_RTC_BCD2BIN(data->day);
+	} else {
+		tmp.date = data->date;
+		tmp.month = data->month;
+		tmp.year = data->year;
+		tmp.hours = data->hours;
+		tmp.minutes = data->minutes;
+		tmp.seconds = data->seconds;
+		tmp.day = data->day;
+	}
+	
+	/* Check year and month */
+	if (
+		tmp.year > 99 || 
+		tmp.month == 0 || 
+		tmp.month > 12 ||
+		tmp.date == 0 ||
+		tmp.date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + tmp.year) ? 1 : 0][tmp.month - 1] ||
+		tmp.hours > 23 ||
+		tmp.minutes > 59 ||
+		tmp.seconds > 59 ||
+		tmp.day == 0 ||
+		tmp.day > 7
+	) {
+		/* Invalid date */
+		return TM_RTC_Result_Error; 
+	}
+	
+	/* Fill time */
+	RTC_TimeStruct.RTC_Hours = data->hours;
+	RTC_TimeStruct.RTC_Minutes = data->minutes;
+	RTC_TimeStruct.RTC_Seconds = data->seconds;
+	/* Fill date */
+	RTC_DateStruct.RTC_Date = data->date;
+	RTC_DateStruct.RTC_Month = data->month;
+	RTC_DateStruct.RTC_Year = data->year;
+	RTC_DateStruct.RTC_WeekDay = data->day;
+	
+	/* Set the RTC time base to 1s and hours format to 24h */
+	RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
+	RTC_InitStruct.RTC_AsynchPrediv = RTC_ASYNC_PREDIV;
+	RTC_InitStruct.RTC_SynchPrediv = RTC_SYNC_PREDIV;
+	RTC_Init(&RTC_InitStruct);
+
+	/* Set time */
+	if (format == TM_RTC_Format_BCD) {
+		RTC_SetTime(RTC_Format_BCD, &RTC_TimeStruct);
+	} else {
+		RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
+	}
+	
+	/* Set date */
+	if (format == TM_RTC_Format_BCD) {
+		RTC_SetDate(RTC_Format_BCD, &RTC_DateStruct);
+	} else {
+		RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
+	}	
+	
+	if (TM_RTC_Status != RTC_STATUS_ZERO) {
+		/* Write backup registers */
+		RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_TIME_OK);
+	}
+	
+	/* Return OK */
+	return TM_RTC_Result_Ok;
+}
+
+TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str) {
+	TM_RTC_t tmp;
+	uint8_t i = 0;
+	
+	/* Get date */
+	tmp.date = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get month */
+	tmp.month = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get year */
+	tmp.year = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get day in a week */
+	tmp.day = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get hours */
+	tmp.hours = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get minutes */
+	tmp.minutes = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get seconds */
+	tmp.seconds = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Return status from set date time function */
+	return TM_RTC_SetDateTime(&tmp, TM_RTC_Format_BIN);
+}
+
+void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
+	uint32_t unix;
+
+	/* Get time */
+	if (format == TM_RTC_Format_BIN) {
+		RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
+	} else {
+		RTC_GetTime(RTC_Format_BCD, &RTC_TimeStruct);
+	}
+	
+	/* Format hours */
+	data->hours = RTC_TimeStruct.RTC_Hours;
+	data->minutes = RTC_TimeStruct.RTC_Minutes;
+	data->seconds = RTC_TimeStruct.RTC_Seconds;
+	
+	/* Get subseconds */
+	data->subseconds = RTC->SSR;
+	
+	/* Get date */
+	if (format == TM_RTC_Format_BIN) {
+		RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
+	} else {
+		RTC_GetDate(RTC_Format_BCD, &RTC_DateStruct);
+	}
+	
+	/* Format date */
+	data->year = RTC_DateStruct.RTC_Year;
+	data->month = RTC_DateStruct.RTC_Month;
+	data->date = RTC_DateStruct.RTC_Date;
+	data->day = RTC_DateStruct.RTC_WeekDay;
+	
+	/* Calculate unix offset */
+	unix = TM_RTC_GetUnixTimeStamp(data);
+	data->unix = unix;
+}
+
+uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year) {
+	/* Check input data */
+	if (
+		month == 0 ||
+		month > 12
+	) {
+		/* Error */
+		return 0;
+	}
+	
+	/* Return days in month */
+	return TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + year) ? 1 : 0][month - 1];
+}
+
+uint16_t TM_RTC_GetDaysInYear(uint8_t year) {
+	/* Return days in year */
+	return TM_RTC_DAYS_IN_YEAR(2000 + year);
+}
+
+void TM_RTC_Config(TM_RTC_ClockSource_t source) {
+	if (source == TM_RTC_ClockSource_Internal) {
+		/* Enable the LSI OSC */
+		RCC_LSICmd(ENABLE);
+
+		/* Wait till LSI is ready */
+		while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
+
+		/* Select the RTC Clock Source */
+		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
+	} else if (source == TM_RTC_ClockSource_External) {
+		/* Enable the LSE OSC */
+		RCC_LSEConfig(RCC_LSE_ON);
+
+		/* Wait till LSE is ready */ 
+		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
+
+		/* Select the RTC Clock Source */
+		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
+	}
+	
+	/* Enable the RTC Clock */
+	RCC_RTCCLKCmd(ENABLE);
+	
+	/* Wait for register synchronization */
+	RTC_WaitForSynchro();
+
+	/* Write status */
+	RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_INIT_OK);
+}
+
+void TM_RTC_Interrupts(TM_RTC_Int_t int_value) {
+	uint32_t int_val;
+	
+	/* Clear pending bit */
+	EXTI->PR = 0x00400000;
+	
+	/* Disable wakeup interrupt */
+	RTC_WakeUpCmd(DISABLE);
+	
+	/* Disable RTC interrupt flag */
+	RTC_ITConfig(RTC_IT_WUT, DISABLE);
+	
+	/* NVIC init for RTC */
+	NVIC_InitStruct.NVIC_IRQChannel = RTC_WKUP_IRQn;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_WAKEUP_SUBPRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;
+	NVIC_Init(&NVIC_InitStruct); 
+	
+	/* RTC connected to EXTI_Line22 */
+	EXTI_InitStruct.EXTI_Line = EXTI_Line22;
+	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
+	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
+	EXTI_InitStruct.EXTI_LineCmd = DISABLE;
+	EXTI_Init(&EXTI_InitStruct);
+	
+	if (int_value != TM_RTC_Int_Disable) {
+		/* Enable NVIC */
+		NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+		NVIC_Init(&NVIC_InitStruct); 
+		/* Enable EXT1 interrupt */
+		EXTI_InitStruct.EXTI_LineCmd = ENABLE;
+		EXTI_Init(&EXTI_InitStruct);
+
+		/* First disable wake up command */
+		RTC_WakeUpCmd(DISABLE);
+
+		if (int_value == TM_RTC_Int_60s) {
+			int_val = 0x3BFFF; 		/* 60 seconds = 60 * 4096 / 1 = 245760 */
+		} else if (int_value == TM_RTC_Int_30s) {
+			int_val = 0x1DFFF;		/* 30 seconds */
+		} else if (int_value == TM_RTC_Int_15s) {
+			int_val = 0xEFFF;		/* 15 seconds */
+		} else if (int_value == TM_RTC_Int_10s) {
+			int_val = 0x9FFF;		/* 10 seconds */
+		} else if (int_value == TM_RTC_Int_5s) {
+			int_val = 0x4FFF;		/* 5 seconds */
+		} else if (int_value == TM_RTC_Int_2s) {
+			int_val = 0x1FFF;		/* 2 seconds */
+		} else if (int_value == TM_RTC_Int_1s) {
+			int_val = 0x0FFF;		/* 1 second */
+		} else if (int_value == TM_RTC_Int_500ms) {
+			int_val = 0x7FF;		/* 500 ms */
+		} else if (int_value == TM_RTC_Int_250ms) {
+			int_val = 0x3FF;		/* 250 ms */
+		} else if (int_value == TM_RTC_Int_125ms) {
+			int_val = 0x1FF;		/* 125 ms */
+		}		
+
+		/* Clock divided by 8, 32768 / 8 = 4096 */
+		/* 4096 ticks for 1second interrupt */
+		RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div8);
+		
+		/* Set RTC wakeup counter */
+		RTC_SetWakeUpCounter(int_val);
+		/* Enable wakeup interrupt */
+		RTC_ITConfig(RTC_IT_WUT, ENABLE);
+		/* Enable wakeup command */
+		RTC_WakeUpCmd(ENABLE);
+	}
+}
+
+uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data) {
+	uint32_t days = 0, seconds = 0;
+	uint16_t i;
+	uint16_t year = (uint16_t) (data->year + 2000);
+	/* Year is below offset year */
+	if (year < TM_RTC_OFFSET_YEAR) {
+		return 0;
+	}
+	/* Days in back years */
+	for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
+		days += TM_RTC_DAYS_IN_YEAR(i);
+	}
+	/* Days in current year */
+	for (i = 1; i < data->month; i++) {
+		days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
+	}
+	/* Day starts with 1 */
+	days += data->date - 1;
+	seconds = days * TM_RTC_SECONDS_PER_DAY;
+	seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
+	seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
+	seconds += data->seconds;
+	
+	/* seconds = days * 86400; */
+	return seconds;
+}
+
+void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix) {
+	uint16_t year;
+	
+	/* Store unix time to unix in struct */
+	data->unix = unix;
+	/* Get seconds from unix */
+	data->seconds = unix % 60;
+	/* Go to minutes */
+	unix /= 60;
+	/* Get minutes */
+	data->minutes = unix % 60;
+	/* Go to hours */
+	unix /= 60;
+	/* Get hours */
+	data->hours = unix % 24;
+	/* Go to days */
+	unix /= 24;
+	
+	/* Get week day */
+	/* Monday is day one */
+	data->day = (unix + 3) % 7 + 1;
+
+	/* Get year */
+	year = 1970;
+	while (1) {
+		if (TM_RTC_LEAP_YEAR(year)) {
+			if (unix >= 366) {
+				unix -= 366;
+			} else {
+				break;
+			}
+		} else if (unix >= 365) {
+			unix -= 365;
+		} else {
+			break;
+		}
+		year++;
+	}
+	/* Get year in xx format */
+	data->year = (uint8_t) (year - 2000);
+	/* Get month */
+	for (data->month = 0; data->month < 12; data->month++) {
+		if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
+			unix -= TM_RTC_Months[1][data->month];
+		} else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
+			unix -= TM_RTC_Months[0][data->month];
+		} else {
+			break;
+		}
+	}
+	/* Get month */
+	/* Month starts with 1 */
+	data->month++;
+	/* Get date */
+	/* Date starts with 1 */
+	data->date = unix + 1;
+}
+
+void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* DataTime, TM_RTC_Format_t format) {
+	RTC_AlarmTypeDef RTC_AlarmStruct;
+	
+	/* Disable alarm first */
+	TM_RTC_DisableAlarm(Alarm);
+	
+	/* Set RTC alarm settings */
+	/* Set alarm time */
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Hours = DataTime->hours;
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Minutes = DataTime->minutes;
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Seconds = DataTime->seconds;
+	RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
+	
+	/* Alarm type is every week the same day in a week */
+	if (DataTime->alarmtype == TM_RTC_AlarmType_DayInWeek) {
+		/* Alarm trigger every week the same day in a week */
+		RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay;
+		
+		/* Week day can be between 1 and 7 */
+		if (DataTime->day == 0) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
+		} else if (DataTime->day > 7) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 7;
+		} else {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
+		}
+	} else { /* Alarm type is every month the same day */
+		/* Alarm trigger every month the same day in a month */
+		RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
+	
+		/* Month day can be between 1 and 31 */
+		if (DataTime->day == 0) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
+		} else if (DataTime->day > 31) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 31;
+		} else {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
+		}
+	}
+
+	switch (Alarm) {
+		case TM_RTC_Alarm_A:		
+			/* Configure the RTC Alarm A */
+			RTC_SetAlarm(format, RTC_Alarm_A, &RTC_AlarmStruct);
+		
+			/* Enable Alarm A */
+			RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
+			
+			/* Enable Alarm A interrupt */
+			RTC_ITConfig(RTC_IT_ALRA, ENABLE);
+		
+			/* Clear Alarm A pending bit */
+			RTC_ClearFlag(RTC_IT_ALRA);
+			break;
+		case TM_RTC_Alarm_B:
+			/* Configure the RTC Alarm B */
+			RTC_SetAlarm(format, RTC_Alarm_B, &RTC_AlarmStruct);
+		
+			/* Enable Alarm B */
+			RTC_AlarmCmd(RTC_Alarm_B, ENABLE);
+		
+			/* Enable Alarm B interrupt */
+			RTC_ITConfig(RTC_IT_ALRB, ENABLE);
+		
+			/* Clear Alarm B pending bit */
+			RTC_ClearFlag(RTC_IT_ALRB);
+			break;
+		default:
+			break;
+	}
+}
+
+void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm) {
+	switch (Alarm) {
+		case TM_RTC_Alarm_A:
+			/* Disable Alarm A */
+			RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
+			
+			/* Disable Alarm A interrupt */
+			RTC_ITConfig(RTC_IT_ALRA, DISABLE);
+		
+			/* Clear Alarm A pending bit */
+			RTC_ClearFlag(RTC_IT_ALRA);
+			break;
+		case TM_RTC_Alarm_B:
+			/* Disable Alarm B */
+			RTC_AlarmCmd(RTC_Alarm_B, DISABLE);
+		
+			/* Disable Alarm B interrupt */
+			RTC_ITConfig(RTC_IT_ALRB, DISABLE);
+		
+			/* Clear Alarm B pending bit */
+			RTC_ClearFlag(RTC_IT_ALRB);
+			break;
+		default:
+			break;
+	}
+	
+	/* Clear RTC Alarm pending bit */
+	EXTI->PR = 0x00020000;
+	
+	/* Configure EXTI 17 as interrupt */
+	EXTI_InitStruct.EXTI_Line = EXTI_Line17;
+	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
+	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
+	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
+	
+	/* Initialite Alarm EXTI interrupt */
+	EXTI_Init(&EXTI_InitStruct);
+
+	/* Configure the RTC Alarm Interrupt */
+	NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_ALARM_SUBPRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+	
+	/* Initialize RTC Alarm Interrupt */
+	NVIC_Init(&NVIC_InitStruct);
+}
+
+void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value) {
+	/* Check input, 0 to 18 registers are allowed */
+	if (location > 18) {
+		return;
+	}
+	
+	/* Write data to backup register */
+	*(uint32_t *)((&RTC->BKP0R) + 4 * location) = value;
+}
+
+uint32_t TM_RTC_ReadBackupRegister(uint8_t location){
+	/* Check input, 0 to 18 registers are allowed */
+	if (location > 18) {
+		return 0;
+	}
+	
+	/* Read data from backup register */
+	return *(uint32_t *)((&RTC->BKP0R) + 4 * location);
+}
+
+/* Callbacks */
+__weak void TM_RTC_RequestHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+__weak void TM_RTC_AlarmAHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+__weak void TM_RTC_AlarmBHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+/* Private RTC IRQ handlers */
+void RTC_WKUP_IRQHandler(void) {
+	/* Check for RTC interrupt */
+	if (RTC_GetITStatus(RTC_IT_WUT) != RESET) {
+		/* Clear interrupt flags */
+		RTC_ClearITPendingBit(RTC_IT_WUT);
+		
+		/* Call user function */
+		TM_RTC_RequestHandler();
+	}
+	
+	/* Clear EXTI line 22 bit */
+	EXTI->PR = 0x00400000;
+}
+
+void RTC_Alarm_IRQHandler(void) {
+	/* RTC Alarm A check */
+	if (RTC_GetITStatus(RTC_IT_ALRA) != RESET) {
+		/* Clear RTC Alarm A interrupt flag */
+		RTC_ClearITPendingBit(RTC_IT_ALRA);
+		
+		/* Call user function for Alarm A */
+		TM_RTC_AlarmAHandler();
+	}
+	
+	/* RTC Alarm B check */
+	if (RTC_GetITStatus(RTC_IT_ALRB) != RESET) {
+		/* Clear RTC Alarm A interrupt flag */
+		RTC_ClearITPendingBit(RTC_IT_ALRB);
+		
+		/* Call user function for Alarm B */
+		TM_RTC_AlarmBHandler();
+	}
+	
+	/* Clear EXTI line 17 bit */
+	EXTI->PR = 0x00020000;
+}
+
+/**
+  * @brief  Установливает время срабатывания профилактики сульфатации для отладки
+  * @retval 
+  */
+void RTC_SetDebugProfTime(void)
+{
+  TM_RTC_t currentTime;
+  uint32_t unixTime;
+  
+  TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
+  
+  unixTime = TM_RTC_GetUnixTimeStamp(&currentTime);
+    
+  unixTime += 30;
+  
+  TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
+}
+
+/**
+  * @brief  Установливает время срабатывания профилактики сульфатации
+  */
+void RTC_SetProfTime(char *str)
+{
+  TM_RTC_t tmp;
+  uint32_t unixTime;
+  uint8_t i = 0;
+	
+  /* Get date */
+  tmp.date = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get month */
+  tmp.month = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  //i++;
+  i+=3;
+  
+  /* Get year */
+  tmp.year = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+  i++;
+	
+  /* Get hours */
+  tmp.hours = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get minutes */
+  tmp.minutes = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get seconds */
+  tmp.seconds = 0;
+	
+  /* Устанавливаем +1 для профилактики */
+  tmp.year += 1;
+  unixTime = TM_RTC_GetUnixTimeStamp(&tmp);  
+  TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
+}

+ 75 - 0
peripheral_modules/src/usart.c

@@ -0,0 +1,75 @@
+/********************************* (C) РОТЕК ***********************************
+ * @module  usart
+ * @file    usart.c
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   Template
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+#include "stm32f4xx.h"  
+#include "usart.h"
+//#include "port_microrl.h"
+#include "main.h"
+//#include <stdio.h>
+
+
+USART_InitTypeDef USART_InitStructure;
+
+void uart_hw_init(USART_TypeDef *uart, uint32_t baud, uint16_t wordlen, uint16_t parity, uint16_t stop) {
+	uint16_t wordlen_tmp;
+
+	if (wordlen == 8)
+		wordlen_tmp = USART_WordLength_8b;
+	if (wordlen == 9)
+		wordlen_tmp = USART_WordLength_9b;
+
+	USART_InitStructure.USART_BaudRate = baud;
+	USART_InitStructure.USART_WordLength = wordlen_tmp;
+	USART_InitStructure.USART_StopBits = stop;
+	USART_InitStructure.USART_Parity = parity;
+	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+
+	USART_DeInit(uart);
+
+	if (uart == USART1) {
+		RCC->APB2ENR |= RCC_APB2Periph_USART1;
+		NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x04, 0));
+		NVIC_EnableIRQ(USART1_IRQn);
+		USART_Init(USART1, &USART_InitStructure);
+		USART_Cmd(USART1, ENABLE);
+		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
+		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
+	}
+
+	if (uart == USART2) {
+		RCC->APB1ENR |= RCC_APB1Periph_USART2;
+		NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x04, 0));
+		NVIC_EnableIRQ(USART2_IRQn);
+		USART_Init(USART2, &USART_InitStructure);
+		USART_Cmd(USART2, ENABLE);
+		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
+		USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
+	}
+
+    if (uart == USART3) {
+        RCC->APB1ENR |= RCC_APB1Periph_USART3;
+        NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x04, 0));
+        NVIC_EnableIRQ(USART3_IRQn);
+        USART_Init(USART3, &USART_InitStructure);
+        USART_Cmd(USART3, ENABLE);
+    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
+    USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
+    }
+}
+
+void InitUSART(void) {
+	uart_hw_init(UPS_USART, UPS_USART_BAUD, UPS_USART_WORD_LEN, UPS_USART_PARITY, UPS_USART_STOP_BIT);
+}
+
+
+/********************************* (C) РОТЕК **********************************/

+ 34 - 0
peripheral_modules/src/wdg.c

@@ -0,0 +1,34 @@
+/********************************* (C) РОТЕК ***********************************
+ * @module  wdg
+ * @file    wdg.c
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   External watchdog (pin PE15)
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+#include "stm32f4xx.h"  
+#include "wdg.h"
+#include "gpio.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+/**
+  * @brief  Сброс внешнего WDT
+  */
+void vTaskWdt(void *param)
+{
+  uint8_t val = 0;
+  for (;;)
+  {	
+	val ^= 1;
+	gpio_set(_WDG, val);
+    vTaskDelay(125);
+  }	
+}
+
+/********************************* (C) РОТЕК **********************************/