Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Raspberry Pi Hardware

Scott James Remnant edited this page May 11, 2018 · 1 revision

Prev: Pointers


Picking the correct width type

When looking at the integer types, the majority have a width in bits specified as part of their type name:

  • Int8
  • Int16
  • Int32
  • Int64

Without getting too far ahead of ourselves, when programming the hardware of the Raspberry Pi, we know that we are going to be dealing with hardware registers.

We also those registers will be the word size of the platform, and that on the 32-bit ARM architecture of the Raspberry Pi, that word size will be 32-bits (4 bytes).

This is also true if you choose to use a 64-bit ARM port on the Raspberry Pi 2 or 3, since the architecture does not otherwise change the hardware interface. For this reason, those ports retain the basic word size of 32-bits.

So we might assume that Int32 would be the correct type to pick, and it's certainly a valid choice, however I argue that it's the wrong one.

These types are ideal when portability is a concern, especially when communicating between different system types over a network. But when interacting with the local system, using them feels like "premature porting."

Swift provides us with an integer type that has the same width as the word size of the platform:

  • Int

Picking the correct type

When reading through the Raspberry Pi data sheets, it's pretty clear that all hardware registers are handled as 32-bit words. These words are going to be used as bit fields, structure fields, values, and addresses. But what type should we use to reference them? Swift provides us four:

  • Int
  • UInt
  • Int32
  • UInt32

And we mentioned above, once we pick a type, we cannot arbitrarily convert it between the different types. Now it might be tempting to pick the fixed-width types, and even the unsigned type, but I'm going to argue that the correct type to use is Int.

Fixed width types

Picking a fixed-width type feels like "premature porting." Yes it's true that the registers are 32-bits wide,, but on the ARM microprocessor in the Raspberry Pi, integers and pointers are also 32-bits wide.

We simply don't have a 64-bit Pi to read the datasheet from, but we can make some guesses. That 64-bit processor will be almost certainly using 64-bit memory addresses, which means those registers would need to be 64-bits wide to fit them. But if we premature ported and declared them as Int32 they wouldn't work anymore, while Int might just work fine.

Since on our platform Int is the correct width, we should just use that. Porting can come later, if it ever becomes necessary.

Signed types

The difference between the signed Int type, and the unsigned UInt type is just that; one allows negative numbers, and the other does not. Otherwise they are the same width, and have the same stride and alignment.

This matters when we store numerical values and want to be able to perform mathematical operations on them. The Int type will overflow earlier than the UInt type, and thus won't be able to store as wide range of values.

But when we're not doing that kind of thing, the distinction doesn't matter, since both types can store the same number of distinct values—it's just the mathematical range that differs.

We can still set the 31st bit of an Int, the difference is just that should be use it mathematically, it will be interpreted as a negative number.

Since we're storing addresses, bit fields, structures, etc. and even distinct values, none of these need mathematical operations performed, thus Int will work just as well.

Int as a fallback type

The final argument for why Int is better is simply the following:

let someValue = 1 << 4

With the lack of further typing, Swift will infer this value to be of Int type. Since integer types are not directly compatible, we would then be unable to use that constant without continual casting, re-interpreting, truncating, etc. And that would leave us very prone to bugs.

But just using Int, we can avoid all of these.


Next: Accessing IO Peripherals from Swift

Clone this wiki locally