20170525_jeffrey - silenceuncrio/diary GitHub Wiki
今天先 base on release/v1.5 這個 branch 來做 Modbus WEB UI
Modbus web page 搞定
來關心一下 openvpn p12 的 上傳 跟 下載
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度
搞定 openvpn p12 的 上傳 跟 下載
零下 30 度的華邦 1 號開了三次都挑戰成功... 順便改 bootdelay 為 3
- -33 度 ok
- -29 度 ok
- -27 度 ok
華邦 2 號第一次挑戰失敗 U-Boot 顯示的溫度 -31
- -31 度 fail
- -29 度 ok
- -29 度 ok
再度調整 chamber 成 -35 度 下午繼續挑戰
- 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 號有表現比較好一些
華邦 二人組 -35 度 挑戰 失敗
調整 恆濕恆溫機 成 零下 25 度
待會再來看看 華邦 二人組 的表現
華邦 二人組 -25 度 挑戰 成功
不過讓他們關機個 30 分鐘再試試看
試著讓 uboot 零下溫度顯示正常
參考 thermal: imx_thermal: fix busywait if IMX6 temp <0C
看來不是這個
參考 Temperature monitor of IMX6UL doesn't work as expected
就是這個 issue 啦
我已經請官網也 mail 個 patch 給我... 就先等等吧
已經收到 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.patchtometa-proscend/recipes-bsp/u-boot/files/ - modify
meta-proscend\recipes-bsp\u-boot\u-boot-imx_2015.04.bbappendFILESEXTRAPATHS_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 冰到冰箱去了