浏览代码

add sntp driver

balbekova 8 年之前
父节点
当前提交
58ad6c3c23
共有 2 个文件被更改,包括 305 次插入0 次删除
  1. 249 0
      modules/Ethernet/sntp.c
  2. 56 0
      modules/Ethernet/sntp.h

+ 249 - 0
modules/Ethernet/sntp.c

@@ -0,0 +1,249 @@
+#include "sntp.h"
+#include "rtc.h"
+#include "settings_api.h"
+
+#include <string.h>
+#include <time.h>
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+
+#define SENDFAIL_TIMEOUT 5000 /* 5 seconds */
+#define SENT_TIMEOUT 60000 /* 1 minute */
+#define BADREPLY_TIMEOUT 60000 /* 1 minute */
+#define VALID_TIMEOUT (8 * 3600000) /* 8 hours */
+
+/* number of seconds between 1900 and 1970 */
+#define DIFF_SEC_1900_1970         (2208988800UL)
+
+struct sntp_packet
+{
+  uint8_t status;
+  uint8_t stratum;
+  uint8_t ppoll;
+  uint8_t precision;
+  uint32_t distance;
+  uint32_t dispersion;
+  uint32_t refid;
+  uint64_t reftime;
+  uint64_t org;
+  uint64_t rec;
+  uint64_t xmt;
+};
+
+static unsigned int timeout;
+static struct udp_pcb* upcb;
+static struct ip_addr server;
+static int port = 123;
+
+/**
+  * @brief  Общая структура настроек
+  */
+extern SETTINGS_t sSettings;
+
+/**
+  * @brief  Разовая синхронизация времени при старте контроллера
+  */
+extern TaskHandle_t xHandleSntpOnceSinhro;
+
+/**
+  * @brief  Синхронизация времени единоразово при включении контроллера
+  * @retval 
+  */
+void vTaskOnceSynchro(void *arg)
+{
+  for (;;) 
+  {
+	if (sSettings.sSNTP.sntpEnable)
+	{  
+      vTaskDelay(7000);
+  	  SNTP_Poll();
+	  //printf("Once time sinhro\n\r");
+	  vTaskDelete(xHandleSntpOnceSinhro);
+	}
+	else
+	  vTaskDelete(xHandleSntpOnceSinhro);
+  }
+}
+
+/**
+  * @brief  Периодическая синхронизация времени.
+  *         Выполняется раз в сутки с 0 часов.
+  * @retval 
+  */
+void vTaskPeriodicSynchro(void *arg)
+{
+  TM_RTC_t data;
+  
+  static uint8_t fSinhro = 0;
+  
+  for (;;) 
+  {
+	vTaskDelay(10000);
+	if (sSettings.sSNTP.sntpEnable)
+	{
+	  TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
+	  
+	  /* Если пришло время синхронизации */
+	  if ((data.hours == 0) && (fSinhro == 0))
+	  {
+		SNTP_Poll();
+	    fSinhro = 1;
+		//printf("Periodic time sinhro\n\r");
+	  }
+	  
+	  if (data.hours > 1)
+	    fSinhro = 0;
+	}
+   	
+  }
+}
+
+/**
+  * @brief  Отладочный таск. Выводим время в консоль.
+  * @retval 
+  */
+void vTaskSntp(void *arg)
+{
+  TM_RTC_t data;
+  
+  for (;;)
+  {
+    vTaskDelay(1000);
+	TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
+	printf("%d.%d.%d %d:%d:%d \n\r", data.date,data.month,data.year,data.hours,data.minutes,data.seconds);
+  }
+}
+
+/**
+  * @brief  Инициализация SNTP.
+  * @retval 
+  */
+void SNTP_Init(void)
+{
+  
+  
+  SNTP_SetServerAddr(sSettings.sSNTP.ip);
+  SNTP_Enable(sSettings.sSNTP.sntpEnable);
+}
+
+static void recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, 
+				 struct ip_addr *addr, u16_t port)
+{
+  time_t t;
+  int utcSec = 0;
+  TM_RTC_t data;
+  
+  if (p->len == sizeof(struct sntp_packet))
+  {
+    int i;
+    struct sntp_packet aligned;
+    //myassert(p->len == p->tot_len); /* don't accept chained pbuf */
+    memcpy(&aligned, p->payload, sizeof(aligned));
+    i = (aligned.status >> 3) & 7;
+    
+	if ((i < 1) || (i > 4)) /* SNTP version 1..4 */
+      goto out;
+
+    i = aligned.status & 7;
+
+	if ((i != 4) && (i != 5)) /* mode 4 or 5: server or broadcast */
+      goto out;
+
+	if (aligned.xmt == 0)
+      goto out;
+	
+	utcSec = (int)(3600.0*sSettings.sSNTP.timeZone);
+	t = (ntohl(aligned.xmt) - 2208988800 + utcSec );
+	
+	TM_RTC_SetDataTimeUnix((uint32_t)t);
+	
+	/* Сохраним время последней синхронизации */
+	TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
+		
+	memset(sSettings.sSNTP.data, 0, sizeof(sSettings.sSNTP.data));
+	
+	sprintf(sSettings.sSNTP.data, "%02d.%02d.%02d %02d:%02d:%02d", 
+			data.date, data.month, data.year,
+			data.hours, data.minutes, data.seconds);
+	
+    timeout = VALID_TIMEOUT;
+    
+  }
+  out:
+    pbuf_free(p);
+}
+
+void SNTP_Enable(bool enable)
+{
+  if (enable)
+  {
+    if (upcb == 0)
+    {
+      err_t ret;
+      upcb = udp_new();
+      if (upcb != 0)
+	  {
+		ret = udp_bind(upcb, IP_ADDR_ANY, port);
+
+	    if (ret != ERR_OK)
+        {
+          udp_remove(upcb);
+          upcb = 0;
+        }
+        else
+        {
+          udp_recv(upcb, recv, 0);
+        }
+        timeout = 0;
+	  }
+    }
+  }
+  else if (upcb != 0)
+  {
+    udp_remove(upcb);
+    upcb = 0;
+  }
+}
+
+bool SNTP_IsEnabled(void)
+{
+  return upcb != 0;
+}
+
+void SNTP_SetServerAddr(char *addr)
+{
+  server.addr = ipaddr_addr(addr);
+}
+
+int sntp_getserverport(void)
+{
+  return port;
+}
+
+static void send_request(void)
+{
+  struct sntp_packet packet;
+  struct pbuf* psend;
+  memset(&packet, 0, sizeof(packet));
+  packet.status = (3 << 3) /* SNTP vesion 3 */ | (3 << 0); /* Mode: client */
+  psend = pbuf_alloc(PBUF_RAW, sizeof(packet), PBUF_REF);
+  
+  if (psend != 0)
+  {
+    psend->payload = &packet;
+    timeout = (udp_sendto(upcb, psend, &server, port) == ERR_OK) ? SENT_TIMEOUT : SENDFAIL_TIMEOUT;
+    pbuf_free(psend);
+  }
+}
+
+void SNTP_Poll(void)
+{
+  if (upcb)
+    send_request();
+}

+ 56 - 0
modules/Ethernet/sntp.h

@@ -0,0 +1,56 @@
+#ifndef __SNTP_H__
+#define __SNTP_H__
+
+#include "lwip/udp.h"
+#include "lwip/def.h"
+#include "lwip/timers.h"
+#include "lwip/udp.h"
+#include "lwip/dns.h"
+#include "lwip/ip_addr.h"
+#include "lwip/pbuf.h"
+
+#include "stdbool.h"
+
+/**
+  * @brief  Синхронизация времени единоразово при включении контроллера
+  */
+void vTaskOnceSynchro(void *arg);
+
+/**
+  * @brief  Периодическая синхронизация времени.
+  *         Выполняется раз в сутки с 0 часов.
+  */
+void vTaskPeriodicSynchro(void *arg);
+
+void vTaskSntp(void *arg);
+
+/**
+  * @brief  Инициализация SNTP.
+  * @retval 
+  */
+void SNTP_Init(void);
+
+void SNTP_Enable(bool enable);
+
+bool SNTP_IsEnabled(void);
+
+void SNTP_SetServerAddr(char *addr);
+int sntp_getserverport(void);
+void SNTP_Poll(void);
+
+
+
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sntp_init(void);
+void sntp_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+*/
+
+#endif /* __SNTP_H__ */