0
\$\begingroup\$

I'm working with STM32 board which a microcontroller is embedded. This MCU seems to work within 72MHz max. Now if I make a C code, does that mean each simple instructions would be done within 72MHz? What I mean by simple instruction is adding 1 to an integer variable for instance. Each 1/72MHz that variable will get +1?

MCU

source : https://www.st.com/en/microcontrollers-microprocessors/stm32f302r8.html

\$\endgroup\$
4
  • 1
    \$\begingroup\$ In this specific case of the Cortex M4, which has most instructions take 1 clock cycle, yes you would have about 72 M adds per second. Note that many other cores can do fewer (or more) per cycle though, so don't assume that will be true for all devices. You desktop CPU for example can issue many instructions per cycle in parallel. \$\endgroup\$ Commented Sep 29, 2023 at 18:09
  • 1
    \$\begingroup\$ The clock speed only becomes relevant at a very low level of abstraction, where there isn't any such thing as "integer variable". You have CPU registers, memory locations, and memory-mapped peripherals, all of which can be modified by an instruction, but only modification of a CPU register is likely to be performed in a single cycle. \$\endgroup\$
    – Ben Voigt
    Commented Sep 29, 2023 at 19:33
  • \$\begingroup\$ on no system is this an expectation, arm, x86 or other. The average desires to be one instruction per clock but it is a pipeline and we have not been processor dependent in a long time. many of these mcus at the lower speeds the flash is half the speed of the core, so you cant feed instructions that fast not counting loops. with prefetch/etc you may get bursts of one per clock, sure... \$\endgroup\$
    – old_timer
    Commented Oct 2, 2023 at 15:30
  • \$\begingroup\$ it is the system clock, there is a clock tree in the documentation that shows everything and more related to this question. \$\endgroup\$
    – old_timer
    Commented Oct 2, 2023 at 15:31

2 Answers 2

3
\$\begingroup\$

It depends on the microcontroller. Few processors, microcontroller or otherwise, can do all their operations in a single clock cycle; most of them require different numbers of clock cycles for different instructions. It's not C instructions that matter here, either--it's assembly (or machine code) instructions, the native instructions of the processor. One C instruction can expand out into dozens of assembly instructions, and some of those may take tens of clock cycles to complete.

Typically, your most basic instructions are the fastest. Adding two registers, incrementing or decrementing a register, performing logic operations, that sort of thing. Instructions that access memory are slower; loading data from memory into a register, storing a register into memory, and arithmetic operations involving memory data all usually take an extra couple clock cycles. Program flow control instructions, like JMP, are also typically a few cycles slower, and they usually flush the pipeline in pipelined processors.

The slowest instruction on processors that support it is usually division. I've seen architectures where division takes over a hundred clock cycles while addition takes just two or three. Division is complicated.

The STM32 is based on the ARM Cortex-M4 processor architecture, so this instruction set reference can be used to investigate how many cycles each instruction takes. Note that some instructions take variable time; division, for instance, takes between 2 and 12 clock cycles depending on the numbers being divided.

The cortex-M4 is fortunately simple for an ARM processor; more advanced ARM processors, like many modern processors, have very complex dependency chains that determine how long any given instruction takes.

\$\endgroup\$
0
\$\begingroup\$

The clock frequency means how fast you can run the system clock. Each assembler instruction takes a number of clock cycles to carried out, as documented in the assembler manual. And each C expression will in turn boil down to multiple assembler instructions.

Here is an example, where I made everything volatile and disabled optimization, just to ensure that directly corresponding assembler gets generated:

volatile int a=1, b=1;
volatile int c = a + b;

Compiling this with gcc for ARM32 gives me roughly something like this for c = a + b:

ldr     r2, [r7, #12]
ldr     r3, [r7, #8]
add     r3, r3, r2
str     r3, [r7, #4]
movs    r3, #0

Each of these instructions take a certain amount of clock ticks. So we'll have to look up each and every instruction and count the ticks.

But lets for simplicity's sake imagine an example where they all take 3 clock ticks:

  • There is 5 instructions, 5x3 = 15.
  • t=1/f so at 72MHz each clock tick takes 13.88ns.
  • 15 * 13.88*10^-9 and we end up with 208.33ns to execute the code.

In reality this is much more complex, in particular there might be timing overhead when loading code into registers from RAM or flash. To counter that, CPUs implement things like pipelining, which means that it starts to load several instructions at once. From Cortex M4, simpler forms of branch prediction might also be used. Beyond M4, data and/or instruction cache memories that act as a fast access buffer between the CPU and the slower memories.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.