0
\$\begingroup\$

Can I use variable types such as:

float x;

int x;

or should I use

int16_t x;

int32_t x;

I am using STM32F401RE. And how to decide whether to use int16_t or int32_t or int/float.

\$\endgroup\$

4 Answers 4

0
\$\begingroup\$

You can use any types you have available to make the job done. All those types are available and nothing limits you from using any of them.

Use integers if you don't need float, and use float when you need it. The other thing is, some people might choose differently what to use in which situation so it's really opinion-based what you want to use and when. It's not that different from writing software for PC.

\$\endgroup\$
9
  • \$\begingroup\$ This isn't opinion-based at all - there are plenty of de facto engineering standards which engineers should fall in line with. And there's quite a few microcontroller-specific aspects here as well. To say that int vs uint32_t is opinion-based (from my software engineer point of view) is like saying that picking a LM317 vs switched buck regulator is opinion-based and either is fine for a generic PCB. \$\endgroup\$
    – Lundin
    Commented Oct 23, 2023 at 14:40
  • \$\begingroup\$ @Lundin Without context LM317 or buck regulator are both fine. On STM32, int32_t is a long int, but both int and long int are 32-bit on STM32. Now which one you pick according to some de facto engineering standards? \$\endgroup\$
    – Justme
    Commented Oct 23, 2023 at 15:48
  • \$\begingroup\$ This is correct, but I'd just add that floating point is necessary in embedded operations much less than many people seem to believe. \$\endgroup\$ Commented Oct 23, 2023 at 17:16
  • \$\begingroup\$ @ScottSeidman Why would you avoid floating point when you've explicitly picked an MCU with FPU on board? That's utter nonsense. For the general case of microcontrollers, that's another story nobody asked about, advise about that here. \$\endgroup\$
    – Lundin
    Commented Oct 24, 2023 at 6:46
  • \$\begingroup\$ GREAT treatment about this sort of stuff in Elicia White's book, but the way. People can certainly use floats on microcontrollers, but the precision people think they get isn't real. When you think you need decimal precision of thousandths, just multiply your numbers by 1000 (well, 1024 if more efficient), and now your integer calcs give you units of thousandths. (or 1/1024 if you need the clock ticks) \$\endgroup\$ Commented Oct 24, 2023 at 12:55
2
\$\begingroup\$

Just to note - the STM32F401 is an arm Cortex M4 core with single precision hardware floating point unit. With the arm, the native type is a 32 bit integer. If you wish to use 8 or 16 bit integers, then there maybe a cost in terms of code size. Nevertheless it is a tradeoff of ram usage for storage vs flash usage for code. For the most part, just write the code to use what is required. You can optimise later if necessary ( normally not necessary). Refer to the arm Cortex M4 architecture documents to better understand the tradeoffs.

As for float vs int. Floating point isn’t quite the magic bullet you’d like to think it is. The further the value moves away from zero, the less precision it has. As well, it is unwise to do equal to comparisons with floating point as there can be inherent rounding errors. So I’d suggest for the most part you use integer variables and only use float when needed.

Whilst the STM32F401 has a hardware floating point unit, using this vs software based floating point might mean you need to consider whether to save/restore the FPU state for interrupts. Enabling this means the entry/exit to the interrupt service routines are slower and more stack memory is consumed.

For an example, if you wanted a loop counter, you’d probably choose a 32bit int variable. Integer so that there are no rounding errors and 32bit as that is the native arm CM4 type.

For the most part the choice of variable types is much the same if you were writing code for an x86.

\$\endgroup\$
2
  • \$\begingroup\$ ARM (Thumb-2) Instruction set used on CM4 can work with 8-bit and 16-bit numbers without any code size penalty in most cases (maybe all cases?). \$\endgroup\$
    – Misaz
    Commented Oct 22, 2023 at 12:20
  • \$\begingroup\$ RAM units and clock ticks. \$\endgroup\$ Commented Oct 23, 2023 at 17:17
0
\$\begingroup\$

Check out this: https://stackoverflow.com/a/77105610/584518. The conclusion from that is that in a professional context:

  • You should almost certainly never use int, since it is non-portable. Signed numbers in general are also quite rare on embedded systems, compared to PC programming. They should only be used when you actually need them.
  • There are only a few special uses for unsigned int.
  • What you should be using most of the time is intn_t/uintn_t from stdint.h. Or in some cases the uint_fastn_t.

The next question is what "n" you should be picking, i.e uint16_t, uint32_t etc. That's not a trivial question either.

  • Generally microcontrollers generate efficient code when you use the smaller types, both in terms of execution speed and in terms of data/code size.
  • In case of Cortex M there shouldn't be any execution speed drops for using the smaller types (but you can use uint_fast8_t in case you are worried).
  • However, 32-bitters in general perform best when using uint32_t.
  • uint32_t on a 32 bitter also have the great benefit that you don't have to worry much about Implicit type promotion rules, so it is overall a safer type to use, particularly so for beginner- to intermediately experienced C programmers.

Regarding float numbers, we may note that your specific Cortex M4 comes with a single precision FPU. This is one of the few cases where float vs double might matter. Because as long as you stick to float and 1.0f floating point constants, use the dedicated single precision float functions, i.e sqrtf not sqrt, sinf not sin, then the appropriate and fast hardware FPU instructions will be generated.

But if you mix in double or 1.0 constants or call double-typed library functions like sqrt, then the compiler might decide to instead of the FPU utilize software floating point libs, which are way more inefficient. Your specific compiler could either be reasonable or unreasonable here, so read up on the compiler docs regarding how to deal with floating point if you plan to use it.

So that's quite different from PC programming where the general best practice is pretty much to always use double and never float.

No matter system, it is considered good practice to avoid mixing float, double and/or integer types in the same expression. Again because of implicit promotion pitfalls, but also because you might get very inefficient code just by accident.

\$\endgroup\$
2
  • \$\begingroup\$ I may or may not be representative, but I disagree about avoiding ints for many embedded applications. When you're working with low-resource 8-bit processors, where memory and clock ticks matter, and engineers laugh when you talk about "portability", floats are almost certainly best avoided. \$\endgroup\$ Commented Oct 23, 2023 at 17:23
  • \$\begingroup\$ @ScottSeidman "I disagree about avoiding ints for many embedded applications" Because you say so or because of an actual argument? Also this question is about types used on a STM32 Cortex M4 with FPU, nobody asked about 8-bitters. But yeah, float should not be used on 8 bitters and 8 bitters should very likely not be used in the first place, since it's year 2023. \$\endgroup\$
    – Lundin
    Commented Oct 24, 2023 at 6:44
0
\$\begingroup\$

The default types such as int and long can vary in size depending on the CPU architecture and compiler, leading to potential issues when transitioning between platforms. The 'stdint.h' library provides a solution by offering fixed-size integer types, ensuring clarity on the number of bits in a variable. This not only enhances code readability but also promotes portability across different platforms and CPU architectures.

Using the stdint library becomes especially beneficial in scenarios like programming for an ESP32 or Arduino, where the default int size differs (32 bits for ESP32 and 16 bits for Arduino), minimizing the risk of unnoticed discrepancies and improving overall code robustness.

\$\endgroup\$
2
  • \$\begingroup\$ Arduino covers so many MCUs that I don't believe all Arduino platforms have integers as 16 bits. If you only mean 8-bit AVRs, then yes, they do have 16 bit integers. \$\endgroup\$
    – Justme
    Commented Oct 23, 2023 at 17:03
  • 1
    \$\begingroup\$ True, I meant the OG arduino as in the atmega328p. But this verifies my point, when using int you never know what will break when porting to another device. \$\endgroup\$ Commented Oct 24, 2023 at 6:02

Your Answer

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