🛠 Surveiller la thermique et les fréquences big.LITTLE
Objectives
Set up serious monitoring for the S922X big.LITTLE (4× Cortex-A73 + 2× Cortex-A53): real frequencies per core, thermal zone temperatures, and throttling detection. Context: the N2 (Rev-B, 1.8 GHz) throttled under sustained load; the N2+ (Rev-C) holds 2.4 GHz without a fan at 35 °C ambient, with the fan activating around 65 °C. Armbian maintainers recommend the "performance" governor to avoid random freezes after 24+ hours (cpufreq/OPP instability).
Hardware
- ODROID-N2/N2+ running Armbian, with heatsink installed (the SoC is under the board!)
stress-ngfor load:sudo apt install stress-ng- Optional 2-pin fan (kit-dependent) >
Complete code
#!/usr/bin/env python3
"""thermal_watch.py — fréquences + températures S922X, alerte throttling."""
import glob, time, subprocess
CPU = "/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq" # kHz
MAXF = "/sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq"
ZONE = "/sys/class/thermal/thermal_zone*/temp" # milli-°C
# Ordonné : cpu0-3 = A73 (max 2400 MHz N2+ / 1800 N2), cpu4-5 = A53 (2016/1900)
def read(path): return int(open(path).read.strip)
while True:
freqs = [read(p) // 1000 for p in sorted(CPU and glob.glob(CPU),
key=lambda s: int(s.split("cpu")[1].split("/")[0]))]
maxs = [read(p) // 1000 for p in sorted(glob.glob(MAXF),
key=lambda s: int(s.split("cpu")[1].split("/")[0]))]
temps = [read(p) / 1000 for p in glob.glob(ZONE)]
hot = [t for t in temps if t > 75]
throttled = any(f < m * 0.9 for f, m in zip(freqs, maxs))
print(f"{time.strftime('%H:%M:%S')} MHz={freqs} "
f"°C={[round(t,1) for t in temps]} "
f"{'THROTTLING!' if throttled else ''}{' HOT!' if hot else ''}")
time.sleep(2)
# Lancer en parallèle : stress-ng --cpu 6 --cpu-method matrixprod
Expected verification
lscpu -e confirms 6 CPUs (the A53 cpu4/cpu5 must be online — vendor 4.9 images left them offline). At idle: 1.6–1.8 W and low frequencies (ondemand governor) or max (performance). Under matrixprod stress: N2 ≈ 5.2 W, N2+ ≈ 6 W; the script should show the A73 capped at 1800 MHz (N2) or 2400 MHz (N2+) without sustained drops under a proper heatsink (≤ 74–80 °C measured by CNX). cat /sys/class/thermal/thermal_zone*/type names the zones (soc_thermal, etc.).
Common mistakes
- Reading scaling_cur_freq from a single core and drawing conclusions: big.LITTLE migrates tasks; monitor all 6 cores.
- Using powersave/conservative governors and assuming a defect: switch to
performance(cpupower frequency-set -g performance), recommended by Armbian against freezes > 24 h. - Ignoring thermal zones: not all thermal_zone* are the SoC; check
typebefore raising alerts. - Monitoring by touch: the heatsink is UNDER the board, tactile sensation is misleading and burning.
- Forgetting the N2/N2+ difference: different OPP caps (1800/1900 vs 2400/2016 MHz), do not diagnose false throttling.
- >
Other tutorials for this board
Code examples for this board
clignotante.pyPythonbouton-gpio.pyPythoncapteur-i2c.shBashsurveillance-temperature.shBashcapteur-dht11.pyPythonservo-pwm-sysfs.shBash