@@ -401,7 +401,6 @@ format, which contains several sections. Let's see them:
401401``` sh
402402$ arm-none-eabi-objdump -h main.o
403403...
404- Sections:
405404Idx Name Size VMA LMA File off Algn
406405 0 .text 00000002 00000000 00000000 00000034 2** 1
407406 CONTENTS, ALLOC, LOAD, READONLY, CODE
@@ -411,10 +410,7 @@ Idx Name Size VMA LMA File off Algn
411410 ALLOC
412411 3 .vectors 000001ac 00000000 00000000 00000038 2** 2
413412 CONTENTS, ALLOC, LOAD, RELOC, DATA
414- 4 .comment 0000004a 00000000 00000000 000001e4 2** 0
415- CONTENTS, READONLY
416- 5 .ARM.attributes 0000002e 00000000 00000000 0000022e 2** 0
417- CONTENTS, READONLY
413+ ...
418414```
419415
420416Note that VMA/LMA addresses for sections are set to 0 - meaning, ` main.o `
@@ -553,7 +549,6 @@ Let's examine sections in firmware.elf:
553549``` sh
554550$ arm-none-eabi-objdump -h firmware.elf
555551...
556- Sections:
557552Idx Name Size VMA LMA File off Algn
558553 0 .vectors 000001ac 08000000 08000000 00010000 2** 2
559554 CONTENTS, ALLOC, LOAD, DATA
@@ -898,28 +893,27 @@ void delay(unsigned ms) { // This function waits "ms" milliseconds
898893` ` `
899894
900895Now let' s compile this code with, and without `volatile` specifier for `s_ticks`
901- and compare generated assembly code:
896+ and compare generated machine code:
902897
903898```
904- // NO VOLATILE: | // WITH VOLATILE:
905- // uint32_t s_ticks; | // volatile uint32_t s_ticks;
906-
907- ldr r3, [pc, #8] <-- cache s_ticks | ldr r2, [pc, #12]
908- ldr r3, [r3, #0] <-- in r3 | ldr r3, [r2, #0] <-- r3 = s_ticks
909- adds r0, r3, r0 <-- r0 = r3 + ms | adds r3, r3, r0 <-- r3 = r3 + ms
910- | ldr r1, [r2, #0] <-- reload! r1 = s_ticks
911- cmp r3, r0 <-- compare | cmp r1, r3 <-- compare
899+ // NO VOLATILE: uint32_t s_ticks; | // VOLATILE: volatile uint32_t s_ticks;
900+ |
901+ ldr r3, [pc, #8] // cache s_ticks | ldr r2, [pc, #12]
902+ ldr r3, [r3, #0] // in r3 | ldr r3, [r2, #0] // r3 = s_ticks
903+ adds r0, r3, r0 // r0 = r3 + ms | adds r3, r3, r0 // r3 = r3 + ms
904+ | ldr r1, [r2, #0] // RELOAD: r1 = s_ticks
905+ cmp r3, r0 // compare | cmp r1, r3 // compare
912906 bcc.n 200000d2 <delay+0x6> | bcc.n 200000d2 <delay+0x6>
913907 bx lr | bx lr
914908```
915909
916- Long story short: if there is no `volalile`, the `delay()` function will loop
917- forever and never return. Because it caches (optimises) the value of `s_ticks`
918- in a register and never updates it. A compiler does that because it doesn' t
919- know that ` s_ticks` can be updated elsewhere - by the interrupt handler! The
910+ If there is no `volalile`, the `delay()` function will loop forever and never
911+ return. That is because it caches (optimises) the value of `s_ticks` in a
912+ register and never updates it. A compiler does that because it doesn' t know
913+ that ` s_ticks` can be updated elsewhere - by the interrupt handler! The
920914generated code with ` volatile` , on the other hand, loads ` s_ticks` value on
921- each iteration. So, the rule of thumb: ** those values in memory that get updated
922- by interrupt handlers, or by the hardware, declare as ` volatile` ** .
915+ each iteration. So, the rule of thumb: ** those values in memory that get
916+ updated by interrupt handlers, or by the hardware, declare as ` volatile` ** .
923917
924918Now we should add ` SysTick_Handler()` interrupt handler to the vector table:
925919
0 commit comments