diff --git a/userspace/tools/Makefile b/userspace/tools/Makefile
index acb65105fe7ec5faec55c252fea10125fb5f96c6..247fd11a8be785e896543d5e5c0af24b2882ca66 100644
--- a/userspace/tools/Makefile
+++ b/userspace/tools/Makefile
@@ -90,6 +90,8 @@ wrs_dump_shmem: wrs_dump_shmem.o wrs_dump_shmem_ppsi.o time_lib.o
 wr_mon: wr_mon.o term.o  time_lib.o
 	${CC} -o $@ $^ $(LDFLAGS)
 
+nmea/wr_nmea.o: nmea/serial.h nmea/wr_nmea.h nmea/nmea.h
+nmea/nmea.o: nmea/nmea.h
 wr_date: nmea/wr_nmea.o nmea/nmea.o nmea/serial_linux.o
 wr_date: wr_date.o time_lib.o
 	${CC} -o $@ $^ $(LDFLAGS)
diff --git a/userspace/tools/nmea/serial.h b/userspace/tools/nmea/serial.h
index 483f583a5c31fbdf2402e130f3bbf61786748d97..31e9214f834376ca573af9ea94beef637e73068d 100644
--- a/userspace/tools/nmea/serial.h
+++ b/userspace/tools/nmea/serial.h
@@ -19,6 +19,7 @@ int serial_read(char *data, int len);
 int serial_write(char *data, int len);
 void serial_write_byte(unsigned char b);
 unsigned char serial_read_byte(void);
+char serial_read_byte_w_timeout(unsigned int *timeout_s);
 int serial_data_avail(void);
 
 void sys_delay(int msecs);
diff --git a/userspace/tools/nmea/serial_linux.c b/userspace/tools/nmea/serial_linux.c
index 83f1374997a118694eefb76e302d4a3b22f2a48c..14c71aff69577e13120c997f34c7b361cd518ad4 100644
--- a/userspace/tools/nmea/serial_linux.c
+++ b/userspace/tools/nmea/serial_linux.c
@@ -96,6 +96,36 @@ int serial_read(char *data, int len)
     return nbytes;
 };
 
+/* serial_read with timeout as seconds */
+int serial_read_w_timeout(char *data, int len, unsigned int *timeout_s)
+{
+    int nbytes = 0;
+    int select_ret;
+    fd_set set;
+    struct timeval tv;
+
+    FD_ZERO(&set);
+    FD_SET(serial_fd, &set);
+
+    while (len) {
+	tv.tv_sec = *timeout_s;
+	tv.tv_usec = 0;
+
+	select_ret = select(serial_fd + 1, &set, NULL, NULL, &tv);
+
+	if (!select_ret) {
+		/* Timeout */
+		*timeout_s = 0;
+		return 0;
+	}
+	if (read(serial_fd, data, 1) == 1) {
+	    len--; data++; nbytes++;
+	}
+    }
+
+    return nbytes;
+};
+
 void serial_write_byte(unsigned char b)
 {
 #ifdef DEBUG
@@ -118,6 +148,20 @@ char serial_read_byte(void)
 
 }
 
+/* serial_read_byte with timeout as seconds */
+char serial_read_byte_w_timeout(unsigned int *timeout_s)
+{
+    char b;
+
+    serial_read_w_timeout(&b, 1, timeout_s);
+#ifdef DEBUG
+    printf("%02x ", b);
+#endif /* DEBUG */
+
+    return b;
+
+}
+
 int serial_data_avail(void)
 {
     fd_set set;
diff --git a/userspace/tools/nmea/wr_nmea.c b/userspace/tools/nmea/wr_nmea.c
index afbeaf0591518ea86483b25793dad015905e09b1..03a789c70b4497bb89f418ae80d9a474450b7c4e 100644
--- a/userspace/tools/nmea/wr_nmea.c
+++ b/userspace/tools/nmea/wr_nmea.c
@@ -32,26 +32,71 @@ int nmea_init(struct wr_nmea *nmea, char *dev, int baud, char *fmt)
 	return 0;
 }
 
-static void read_nmea_msg(char *msgbuf, int len)
+static int read_nmea_msg(char *msgbuf, int len)
 {
 	int i = 0;
 	char c;
+	unsigned int nmea_timeout_max = 10;
+	unsigned int nmea_timeout;
+
+	while (1) {
+		if (nmea_timeout_max <= 0) {
+			/* Timeout */
+			return -1;
+		}
+
+		nmea_timeout = 1;
+		c = serial_read_byte_w_timeout(&nmea_timeout);
+		if (nmea_timeout == 0) {
+			nmea_timeout_max--;
+			continue;
+		}
+
+		/* Start of message found */
+		if (c == '$')
+		    break;
+	}
 
-	while ((c = serial_read_byte()) != '$') {};
-		*msgbuf++ = c;
-	while ((c = serial_read_byte()) != '\r' && (i++) < len - 1)
+	/* Copy start of message ('$') */
+	*msgbuf++ = c;
+
+	while (1) {
+		if (nmea_timeout_max <= 0) {
+			/* Timeout */
+			return -1;
+		}
+
+		nmea_timeout = 1;
+		c = serial_read_byte_w_timeout(&nmea_timeout);
+		if (nmea_timeout == 0) {
+			nmea_timeout_max--;
+			continue;
+		}
+
+		if (c == '\r')
+			break;
+		i++;
+		if (i >= len)
+			break;
 		*msgbuf++ = c;
+	}
+
 	*msgbuf++ = '\r';
 	*msgbuf++ = '\n';
 
-	*msgbuf++ = 0 ;
+	*msgbuf++ = 0;
+
+	return 0;
 }
 
-void read_nmea_msg_type(char *msgbuf, int len, const char *msg_type)
+int read_nmea_msg_type(char *msgbuf, int len, const char *msg_type)
 {
 	do {
-		read_nmea_msg(msgbuf, len);
+		if (read_nmea_msg(msgbuf, len) < 0)
+			return -1;
 	} while (strncmp(&msgbuf[1], msg_type, 5) != 0); //ignore starting "$"
+
+	return 0;
 }
 
 int nmea_read_tai(struct wr_nmea *nmea, int64_t *t_out)
@@ -59,11 +104,12 @@ int nmea_read_tai(struct wr_nmea *nmea, int64_t *t_out)
     char buf[1024];
 
     serial_open(nmea->dev, nmea->baud);
-    read_nmea_msg_type(buf, 1024, nmea->fmt);
+    if (read_nmea_msg_type(buf, 1024, nmea->fmt) < 0)
+	return -1;
     serial_close();
 
     if(nmea->parse(buf, strlen(buf), (nmea->utc)) < 0)
-	return -1;
+	return -2;
 
     pr_info("NMEA time: %d/%d/%d %02d:%02d:%02d.%02d\n",
 	    nmea->utc->year+1900,
diff --git a/userspace/tools/wr_date.c b/userspace/tools/wr_date.c
index 1876e927e393c4c7a6a2e6e250c2f0c8ed8a119f..ede197e4ee1171a1d72166740e15acf3de4ac462 100644
--- a/userspace/tools/wr_date.c
+++ b/userspace/tools/wr_date.c
@@ -138,19 +138,29 @@ int get_kern_leaps(void)
 
 static int wrdate_get_nmea(int64_t *t_out)
 {
-	if (nmea_read_tai(&nmea, t_out) < 0) {
-		fprintf(stderr, "wr_date: %s: error reading nmea\n", __func__);
+	int ret;
+	
+	ret = nmea_read_tai(&nmea, t_out);
+
+	if (ret == -1) {
+		fprintf(stderr, "Timeout on reading nmea\n");
+		return -1;
+	}
+
+	if (ret == -2) {
+		fprintf(stderr, "Error while parsing nmea message\n");
 		return -1;
 	}
+
 	return 0;
 }
 
-static void wrdate_gettimeofday(struct timeval *tv)
+static int wrdate_gettimeofday(struct timeval *tv)
 {
 	if (opt_nmea_en) {
-		wrdate_get_nmea((int64_t *)&tv->tv_sec);
+		return wrdate_get_nmea((int64_t *)&tv->tv_sec);
 	} else {
-		gettimeofday(tv, NULL);
+		return gettimeofday(tv, NULL);
 	}
 }
 
@@ -166,7 +176,8 @@ int wrdate_get(volatile struct PPSG_WB *pps, int tohost)
 
 	tai_offset = get_kern_leaps();
 	if (opt_not) {
-		wrdate_gettimeofday(&sw);
+		if (wrdate_gettimeofday(&sw) < 0)
+			return 1;
 		taih = 0;
 		tail = sw.tv_sec + tai_offset;
 		nsec = sw.tv_usec * 1000;
@@ -181,7 +192,8 @@ int wrdate_get(volatile struct PPSG_WB *pps, int tohost)
 		} while((tmp1 != taih) || (tmp2 != tail));
 	}
 
-	wrdate_gettimeofday(&sw);
+	if (wrdate_gettimeofday(&sw) < 0)
+		return 1;
 	tai = opt_nmea_en ? (sw.tv_sec) : (uint64_t)(taih) << 32 | tail;
 
 	/* Before printing (which takes time), set host time if so asked to */