This post was flagged by the community and is temporarily hidden.
If you keep the serial put in there, you get a bunch of serial noise in the power trace after the part you care about. Probably not a huge deal regarding keeping it in vs. removing it.
Yeah, capture_trace()
expects a serial response in the get_pt()
function. Again, not a huge deal, so long as your power traces are okay, you can safely ignore that.
It needs to be after trigger_high()
in get_pt()
, as that’s the start point of the power trace capture. Directly after is preferable.
Alex
Thank you Alex. I have a few additional questions. I performed these measurements as instructed by the http://localhost:8889/notebooks/jupyter/courses/sca101/Lab%202_1A%20-%20Instruction%20Power%20Differences%20(MAIN).ipynb lab:
1. Power trace without any instructions
uint8_t get_pt(uint8_t* pt, uint8_t len)
{
trigger_high();
trigger_low();
return 0x00;
}
I can go to Godbolt and select ARM GCC 12.2.0, which seems to be the same as I’m running in my environment:
# arm-none-eabi-gcc --version
arm-none-eabi-gcc (Arm GNU Toolchain 12.2.Rel1 (Build arm-12.24)) 12.2.1 20221205
Assembly for above function is:
get_pt(unsigned char*, unsigned char):
push {r7, lr}
sub sp, sp, #8
add r7, sp, #0
str r0, [r7, #4]
mov r3, r1
strb r3, [r7, #3]
bl trigger_high()
bl trigger_low()
movs r3, #0
mov r0, r3
adds r7, r7, #8
mov sp, r7
pop {r7, pc}
2. Power trace with single instructions
uint8_t get_pt(uint8_t* pt, uint8_t len)
{
trigger_high();
volatile long int A = 0x2BAA;
A *= 2;
A *= 2;
A *= 2;
A *= 2;
A *= 2;A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2; A *= 2;
trigger_low();
return 0x00;
}
Assembly instructions are:
get_pt(unsigned char*, unsigned char):
push {r7, lr}
sub sp, sp, #16
add r7, sp, #0
str r0, [r7, #4]
mov r3, r1
strb r3, [r7, #3]
bl trigger_high()
movw r3, #11178
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
bl trigger_low()
movs r3, #0
mov r0, r3
adds r7, r7, #16
mov sp, r7
pop {r7, pc}
3. Power trace with loop:
uint8_t get_pt(uint8_t* pt, uint8_t len)
{
trigger_high();
volatile long int A = 0x2BAA;
for(volatile int i = 0; i < 20; i++) {
A *= 2;
}
trigger_low();
return 0x00;
}
Assembly instructions are:
get_pt(unsigned char*, unsigned char):
push {r7, lr}
sub sp, sp, #16
add r7, sp, #0
str r0, [r7, #4]
mov r3, r1
strb r3, [r7, #3]
bl trigger_high()
movw r3, #11178
str r3, [r7, #12]
movs r3, #0
str r3, [r7, #8]
b .L4
.L5:
ldr r3, [r7, #12]
lsls r3, r3, #1
str r3, [r7, #12]
ldr r3, [r7, #8]
adds r3, r3, #1
str r3, [r7, #8]
.L4:
ldr r3, [r7, #8]
cmp r3, #19
ite le
movle r3, #1
movgt r3, #0
uxtb r3, r3
cmp r3, #0
bne .L5
bl trigger_low()
movs r3, #0
mov r0, r3
adds r7, r7, #16
mov sp, r7
pop {r7, pc}
Analysis:
Then I compared first with second and got this - there’s some difference in the green circle, is that what I’m looking for?
I have these questions:
- Is what is on the pictures what I’m supposed to be seeing?
- If I need to choose the instructions that consume more power, which are those: push, add, mov ?