20170525_jeffrey - silenceuncrio/diary GitHub Wiki

0855

今天先 base on release/v1.5 這個 branch 來做 Modbus WEB UI

0945

Modbus web page 搞定

來關心一下 openvpn p12 的 上傳 跟 下載

1025

morris 額外準備了兩片 華邦 放在 零下40度 的 恆濕恆溫機

先來關心這兩台的狀況一下

這兩台華邦的機子目前 bootdelay 都是 0

NAND 相關的暫存器 值 為 0001 f019h

觀察 U-Boot 的開機訊息可以看到 溫度的資訊

CPU:   Temperature -140462639 C

經過觀察發現最後的兩位數會有變化

就拿來當溫度的參考

剛開機時兩台 U-Boot 顯示的溫度都是 -46

linux kernel 載入成功

不過 rootfs mount fail

隨著測試的次數

兩台 U-Boot 顯示的溫度慢慢會拉升到 -36

linux kernel 載入成功

不過 rootfs mount fail

經過和 morris 的討論後先把 恆濕恆溫機 調整成 零下 30度

1120

搞定 openvpn p12 的 上傳 跟 下載

1150

零下 30 度的華邦 1 號開了三次都挑戰成功... 順便改 bootdelay 為 3

  • -33 度 ok
  • -29 度 ok
  • -27 度 ok

華邦 2 號第一次挑戰失敗 U-Boot 顯示的溫度 -31

  • -31 度 fail
  • -29 度 ok
  • -29 度 ok

再度調整 chamber 成 -35 度 下午繼續挑戰

1405

  • A - HYS[16] - Hysteresis; Disabled(0) | Enabled(1)
  • B - PUS[15:14] - Pull Up / Down Config
    • 00 100K Ohm Pull Down
    • 01 47K Ohm Pull Up
    • 10 100K Ohm Pull Up
    • 11 22K Ohm Pull Up
  • C - PUE[13] - Pull / Keep Select; Keeper(0) | Pull(1)
  • D - PKE[12] - Pull / Keep; Disabled(0) | Enabled(1)
  • E - ODE[11] - Open Drain; Disabled(0) | Enabled(1)
  • F - SPEED[7:6] - Speed; low(50MHz)(00) | medium(100MHz) (01) | medium(100MHz)(10) | max(200MHz)(11)
  • G - DSE[5:3] - Drive Strength
    • 000 output driver disabled;
    • 001 R0(260 Ohm @3.3V, 150 [email protected], 240 Ohm for DDR)
    • 010 R0/2
    • 011 R0/3
    • 100 R0/4
    • 101 R0/5
    • 110 R0/6
    • 111 R0/7
  • H - SRE[0] - Slew Rate; Slow(0) | Fast(1)
 3           2            1           0
1098 7654 3210 9876 5432 1098 7654 3210
---- ---- ---- ---A BBCD E--- FFGG G--H
                  1 1111 0    0001 1  1 - 0001f019 - SD
                  0 1011 0    1011 0  1 - 0000b0b1 - NAND
                  1 1111 0    0011 1  0 - 0001f038 - SD -> DSE(111) -> SRE(0)
                  1 1111 0    1111 1  1 - 0001f0f9 - SD -> SPEED(11) -> DSE(111)
                  1 0111 0    0001 1  1 - 00017019 - SD -> PUS(01)
                  1 0011 0    0001 1  1 - 00013019 - SD -> PUS(00)
                  1 1100 0    0001 1  1 - 0001c019 - SD -> PUE(0) -> PKE(0)
                  1 1101 0    0001 1  1 - 0001d019 - SD -> PUE(0) -> PKE(1)

套了上述幾個不同的設定都沒甚麼特別的發現

兩台大概都要 uboot 顯示溫度為 -30 度左右才開得起來

華邦 1 號有表現比較好一些

1535

華邦 二人組 -35 度 挑戰 失敗

調整 恆濕恆溫機 成 零下 25 度

待會再來看看 華邦 二人組 的表現

1605

華邦 二人組 -25 度 挑戰 成功

不過讓他們關機個 30 分鐘再試試看

1625

試著讓 uboot 零下溫度顯示正常

參考 thermal: imx_thermal: fix busywait if IMX6 temp <0C

看來不是這個

參考 Temperature monitor of IMX6UL doesn't work as expected

就是這個 issue 啦

我已經請官網也 mail 個 patch 給我... 就先等等吧

1725

已經收到 patch 囉

0001-fix-thermal.patch

From 32d2dbe7063dd5020038b33751b0a9c101334dc3 Mon Sep 17 00:00:00 2001
From: Peng Fan <[email protected]>
Date: Tue, 28 Mar 2017 16:57:07 +0800
Subject: [PATCH] fix thermal

Signed-off-by: Peng Fan <[email protected]>
---
 drivers/thermal/imx_thermal.c |  14 ++--
 include/linux/math64.h        | 172 ++++++++++++++++++++++++++++++++++++++++++
 lib/div64.c                   | 143 +++++++++++++++++++++++++++++++++--
 3 files changed, 317 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 123248d..671b3f2 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -9,6 +9,7 @@
 #include <config.h>
 #include <common.h>
 #include <div64.h>
+#include <linux/math64.h>
 #include <fuse.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -55,8 +56,9 @@ static int read_cpu_temperature(struct udevice *dev)
 	struct thermal_data *priv = dev_get_priv(dev);
 	u32 fuse = priv->fuse;
 	int t1, n1;
-	u64 c1, c2;
-	u64 temp64;
+	s64 c1, c2;
+	s64 temp64;
+	s32 rem;
 
 	/*
 	 * Sensor data layout:
@@ -73,7 +75,7 @@ static int read_cpu_temperature(struct udevice *dev)
 	 * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
 	 * offset = 3.580661
 	 * offset = OFFSET / 1000000
-	 * (Nmeas - n1) / (Tmeas - t1) = slope
+	 * (Nmeas - n1) / (Tmeas - t1 - offset) = slope
 	 * We want to reduce this down to the minimum computation necessary
 	 * for each temperature read.  Also, we want Tmeas in millicelsius
 	 * and we don't want to lose precision from integer division. So...
@@ -83,12 +85,12 @@ static int read_cpu_temperature(struct udevice *dev)
 	 * Let constant c1 = (-1000000 / slope)
 	 * milli_Tmeas = (n1 - Nmeas) * c1 + 1000000 * t1 + OFFSET
 	 * Let constant c2 = n1 *c1 + 1000000 * t1
-	 * milli_Tmeas = (c2 - Nmeas * c1) / 1000000 + OFFSET
+	 * milli_Tmeas = (c2 - Nmeas * c1) + OFFSET
 	 * Tmeas = ((c2 - Nmeas * c1) + OFFSET) / 1000000
 	 */
 	temp64 = FACTOR0;
 	temp64 *= 1000000;
-	do_div(temp64, FACTOR1 * n1 - FACTOR2);
+	temp64 = div_s64_rem(temp64, FACTOR1 * n1 - FACTOR2, &rem);
 	c1 = temp64;
 	c2 = n1 * c1 + 1000000 * t1;
 
@@ -123,7 +125,7 @@ static int read_cpu_temperature(struct udevice *dev)
 	writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
 
 	/* Tmeas = (c2 - Nmeas * c1 + OFFSET) / 1000000 */
-	temperature = lldiv(c2 - n_meas * c1 + OFFSET, 1000000);
+	temperature = div_s64_rem(c2 - n_meas * c1 + OFFSET, 1000000, &rem);
 
 	/* power down anatop thermal sensor */
 	writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
diff --git a/include/linux/math64.h b/include/linux/math64.h
index 6d760d7..08584c8 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -1,10 +1,15 @@
 #ifndef _LINUX_MATH64_H
 #define _LINUX_MATH64_H
 
+#include <div64.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 
 #if BITS_PER_LONG == 64
 
+#define div64_long(x, y) div64_s64((x), (y))
+#define div64_ul(x, y)   div64_u64((x), (y))
+
 /**
  * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
  *
@@ -27,6 +32,15 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
 }
 
 /**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ */
+static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
  * div64_u64 - unsigned 64bit divide with 64bit divisor
  */
 static inline u64 div64_u64(u64 dividend, u64 divisor)
@@ -34,8 +48,19 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
 	return dividend / divisor;
 }
 
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ */
+static inline s64 div64_s64(s64 dividend, s64 divisor)
+{
+	return dividend / divisor;
+}
+
 #elif BITS_PER_LONG == 32
 
+#define div64_long(x, y) div_s64((x), (y))
+#define div64_ul(x, y)   div_u64((x), (y))
+
 #ifndef div_u64_rem
 static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 {
@@ -48,10 +73,18 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
 #endif
 
+#ifndef div64_u64_rem
+extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder);
+#endif
+
 #ifndef div64_u64
 extern u64 div64_u64(u64 dividend, u64 divisor);
 #endif
 
+#ifndef div64_s64
+extern s64 div64_s64(s64 dividend, s64 divisor);
+#endif
+
 #endif /* BITS_PER_LONG */
 
 /**
@@ -82,4 +115,143 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
 
 u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
 
+static __always_inline u32
+__iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+	u32 ret = 0;
+
+	while (dividend >= divisor) {
+		/* The following asm() prevents the compiler from
+		   optimising this loop into a modulo operation.  */
+		asm("" : "+rm"(dividend));
+
+		dividend -= divisor;
+		ret++;
+	}
+
+	*remainder = dividend;
+
+	return ret;
+}
+
+#ifndef mul_u32_u32
+/*
+ * Many a GCC version messes this up and generates a 64x64 mult :-(
+ */
+static inline u64 mul_u32_u32(u32 a, u32 b)
+{
+	return (u64)a * b;
+}
+#endif
+
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+	return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+	return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+	u32 ah, al;
+	u64 ret;
+
+	al = a;
+	ah = a >> 32;
+
+	ret = mul_u32_u32(al, mul) >> shift;
+	if (ah)
+		ret += mul_u32_u32(ah, mul) << (32 - shift);
+
+	return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} rl, rm, rn, rh, a0, b0;
+	u64 c;
+
+	a0.ll = a;
+	b0.ll = b;
+
+	rl.ll = mul_u32_u32(a0.l.low, b0.l.low);
+	rm.ll = mul_u32_u32(a0.l.low, b0.l.high);
+	rn.ll = mul_u32_u32(a0.l.high, b0.l.low);
+	rh.ll = mul_u32_u32(a0.l.high, b0.l.high);
+
+	/*
+	 * Each of these lines computes a 64-bit intermediate result into "c",
+	 * starting at bits 32-95.  The low 32-bits go into the result of the
+	 * multiplication, the high 32-bits are carried into the next step.
+	 */
+	rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
+	rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
+	rh.l.high = (c >> 32) + rh.l.high;
+
+	/*
+	 * The 128-bit result of the multiplication is in rl.ll and rh.ll,
+	 * shift it right and throw away the high part of the result.
+	 */
+	if (shift == 0)
+		return rl.ll;
+	if (shift < 64)
+		return (rl.ll >> shift) | (rh.ll << (64 - shift));
+	return rh.ll >> (shift & 63);
+}
+#endif /* mul_u64_u64_shr */
+
+#endif
+
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} u, rl, rh;
+
+	u.ll = a;
+	rl.ll = mul_u32_u32(u.l.low, mul);
+	rh.ll = mul_u32_u32(u.l.high, mul) + rl.l.high;
+
+	/* Bits 32-63 of the result will be in rh.l.low. */
+	rl.l.high = do_div(rh.ll, divisor);
+
+	/* Bits 0-31 of the result will be in rl.l.low.	*/
+	do_div(rl.ll, divisor);
+
+	rl.l.high = rh.l.low;
+	return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
 #endif /* _LINUX_MATH64_H */
diff --git a/lib/div64.c b/lib/div64.c
index 319fca5..8685508 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -9,18 +9,23 @@
  * Generic C version of 64bit/32bit division and modulo, with
  * 64bit result and 32bit remainder.
  *
- * The fast case for (n>>32 == 0) is handled inline by do_div().
+ * The fast case for (n>>32 == 0) is handled inline by do_div(). 
  *
  * Code generated for this function might be very inefficient
  * for some CPUs. __div64_32() can be overridden by linking arch-specific
- * assembly versions such as arch/powerpc/lib/div64.S and arch/sh/lib/div64.S.
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
+ * or by defining a preprocessor macro in arch/include/asm/div64.h.
  */
 
-#include <div64.h>
-#include <linux/types.h>
-#include <linux/compiler.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
 
-uint32_t notrace __div64_32(uint64_t *n, uint32_t base)
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
+#ifndef __div64_32
+uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
 {
 	uint64_t rem = *n;
 	uint64_t b = base;
@@ -52,3 +57,129 @@ uint32_t notrace __div64_32(uint64_t *n, uint32_t base)
 	*n = res;
 	return rem;
 }
+EXPORT_SYMBOL(__div64_32);
+#endif
+
+#ifndef div_s64_rem
+s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+	u64 quotient;
+
+	if (dividend < 0) {
+		quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
+		*remainder = -*remainder;
+		if (divisor > 0)
+			quotient = -quotient;
+	} else {
+		quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
+		if (divisor < 0)
+			quotient = -quotient;
+	}
+	return quotient;
+}
+EXPORT_SYMBOL(div_s64_rem);
+#endif
+
+/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend:	64bit dividend
+ * @divisor:	64bit divisor
+ * @remainder:  64bit remainder
+ *
+ * This implementation is a comparable to algorithm used by div64_u64.
+ * But this operation, which includes math for calculating the remainder,
+ * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
+ * systems.
+ */
+#ifndef div64_u64_rem
+u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+	u32 high = divisor >> 32;
+	u64 quot;
+
+	if (high == 0) {
+		u32 rem32;
+		quot = div_u64_rem(dividend, divisor, &rem32);
+		*remainder = rem32;
+	} else {
+		int n = 1 + fls(high);
+		quot = div_u64(dividend >> n, divisor >> n);
+
+		if (quot != 0)
+			quot--;
+
+		*remainder = dividend - quot * divisor;
+		if (*remainder >= divisor) {
+			quot++;
+			*remainder -= divisor;
+		}
+	}
+
+	return quot;
+}
+EXPORT_SYMBOL(div64_u64_rem);
+#endif
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend:	64bit dividend
+ * @divisor:	64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'.  The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
+ */
+#ifndef div64_u64
+u64 div64_u64(u64 dividend, u64 divisor)
+{
+	u32 high = divisor >> 32;
+	u64 quot;
+
+	if (high == 0) {
+		quot = div_u64(dividend, divisor);
+	} else {
+		int n = 1 + fls(high);
+		quot = div_u64(dividend >> n, divisor >> n);
+
+		if (quot != 0)
+			quot--;
+		if ((dividend - quot * divisor) >= divisor)
+			quot++;
+	}
+
+	return quot;
+}
+EXPORT_SYMBOL(div64_u64);
+#endif
+
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend:	64bit dividend
+ * @divisor:	64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+	s64 quot, t;
+
+	quot = div64_u64(abs(dividend), abs(divisor));
+	t = (dividend ^ divisor) >> 63;
+
+	return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#endif
+
+#endif /* BITS_PER_LONG == 32 */
+
+/*
+ * Iterative div/mod for use when dividend is not expected to be much
+ * bigger than divisor.
+ */
+u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+	return __iter_div_u64_rem(dividend, divisor, remainder);
+}
+EXPORT_SYMBOL(iter_div_u64_rem);
-- 
2.6.2

build 來試試

直接套官網提供的 patch 會 build 不過

人工吧

  • bitbake u-boot-imx -c devshell
  • quilt new fix_thermal.patch
  • quilt add drivers/thermal/imx_thermal.c
  • quilt add include/linux/math64.h
  • quilt add lib/div64.c
  • 人工 patch
  • quilt refresh
  • cp patches/fix_thermal.patch to meta-proscend/recipes-bsp/u-boot/files/
  • modify meta-proscend\recipes-bsp\u-boot\u-boot-imx_2015.04.bbappend
    FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
    
    SRC_URI_append = " \
        file://000_enable_ENET_CLK_when_booting.patch \
        file://add_mx6ul_14x14_evk_nand_config.patch \
        file://set_do_default_low.patch \
        file://nandflash.patch \
        file://uboot_env_v1.0.patch \
        file://modify_bootup_temperature_limit.patch \
        file://remove_fsl_usdhc_and_vedio.patch \
        file://fix_thermal.patch \
    "
    
  • bitbake u-boot-imx -c clean
  • bitbake u-boot-imx
    • 確認新的 patch compile 沒有問題

直接產生一個新的 image 來做實驗

等明天再說吧

目前兩台 旺宏 的挑戰者已經被 morris 冰到冰箱去了

⚠️ **GitHub.com Fallback** ⚠️