The Juno board implements a set of APB energy meter registers in an IOFPGA. These registers are updated every 100us measuring the instantaneous current consumption, instantaneous voltage supply, instantaneous power consumption, and cumulative energy consumption of the Cortex-A53 cluster, Cortex-A57/A72 cluster, Mali-T624 GPU cluster, and fabric of the Juno SoC.
All versions of `latest-armlt' / `ack-armlt', and `lsk-armlt' from `lsk-4.4-armlt' onwards, implement a standardised `hwmon' driver interface for reading the IOFPGA APB energy meter registers. This interface is exposed through `sysfs' i.e. `/sys/'.
`latest-armlt'
`ack-armlt'
`lsk-armlt'
`lsk-4.4-armlt'
`hwmon'
`sysfs'
`/sys/'
To print each reading:
# cd /sys/class/hwmon/ # grep "" ./hwmon*/*_{label,input} ./hwmon0/curr1_label:BOARD_CURR_SYS ./hwmon0/curr2_label:BOARD_CURR_BIG ./hwmon0/curr3_label:BOARD_CURR_LITTLE ./hwmon0/curr4_label:BOARD_CURR_GPU ./hwmon0/energy1_label:BOARD_ENERGY_SYS ./hwmon0/energy2_label:BOARD_ENERGY_BIG ./hwmon0/energy3_label:BOARD_ENERGY_LITTLE ./hwmon0/energy4_label:BOARD_ENERGY_GPU ./hwmon0/in0_label:SENSOR_VOLT_BIG ./hwmon0/in1_label:SENSOR_VOLT_LITTLE ./hwmon0/in2_label:SENSOR_VOLT_SYS ./hwmon0/in3_label:BOARD_VOLT_SYS ./hwmon0/in4_label:BOARD_VOLT_BIG ./hwmon0/in5_label:BOARD_VOLT_LITTLE ./hwmon0/in6_label:BOARD_VOLT_GPU ./hwmon0/power1_label:BOARD_POWER_SYS ./hwmon0/power2_label:BOARD_POWER_BIG ./hwmon0/power3_label:BOARD_POWER_LITTLE ./hwmon0/power4_label:BOARD_POWER_GPU ./hwmon0/temp1_label:SENSOR_TEMP_PMIC ./hwmon0/temp2_label:SENSOR_TEMP_SOC ./hwmon0/temp3_label:SENSOR_TEMP_BIG ./hwmon0/temp4_label:SENSOR_TEMP_LITTLE ./hwmon0/temp5_label:SENSOR_TEMP_GPU_0 ./hwmon0/temp6_label:SENSOR_TEMP_GPU_1 ./hwmon0/curr1_input:787 ./hwmon0/curr2_input:133 ./hwmon0/curr3_input:10 ./hwmon0/curr4_input:62 ./hwmon0/energy1_input:27697142 ./hwmon0/energy2_input:3956123 ./hwmon0/energy3_input:778037 ./hwmon0/energy4_input:2142136 ./hwmon0/in0_input:820 ./hwmon0/in1_input:0 ./hwmon0/in2_input:908 ./hwmon0/in3_input:905 ./hwmon0/in4_input:824 ./hwmon0/in5_input:825 ./hwmon0/in6_input:824 ./hwmon0/power1_input:707141 ./hwmon0/power2_input:67231 ./hwmon0/power3_input:8675 ./hwmon0/power4_input:52011 ./hwmon0/temp1_input:27850 ./hwmon0/temp2_input:24071 ./hwmon0/temp3_input:24222 ./hwmon0/temp5_input:22846 ./hwmon0/temp6_input:22553
So for example `/hwmon0/power3_input' reads `8675' i.e. 8675 uW and this corresponds to the instantaneous power consumption of the Cortex-A53 cluster (`/hwmon0/power3_label' reads `BOARD_POWER_LITTLE'). You can see the description of the `BOARD_POWER_LITTLE' register here.
`/hwmon0/power3_input'
`8675'
`/hwmon0/power3_label'
`BOARD_POWER_LITTLE'
In a baremetal environment you'll need to directly read the memory-mapped IOFGPA APB energy meter registers. As described in the Juno V2M Technical Reference Manual, these registers begin at address `0x1C010000'.
`0x1C010000'
LDR X0, =0x1C010110 LDR W0, [X0] //; W0 = Lower 32-bits LDR X1, =0x1C010114 LDR W1, [X1] //; X1 = Upper 32-bits LSL X1, X1, #32 ORR X0, X0, X1 LDR X1, =12348030000 UDIV X0, X0, X1 RET
The `12348030000' divisor is specific to the Cortex-A53 cluster as outlined here. Each block of IP in the SoC has different divisor values so be sure to consult the corresponding register description in the V2M TRM linked above, for example the Cortex-A72's divisor on Juno r2 is `6174020000'.
`12348030000'
`6174020000'
The Juno board also implements jumpers on the PCB that allow you to monitor power through an external measurement probe such as a DS-5 Energy Probe. You will need to remove the Juno board's outer casing in order to expose the PCB. There are four jumper connectors:
Figure 1 - External energy measurement jumpers on the Juno PCB