It is not portable code, but it is illustrative of the power of C and its ability to interface with memory-mapped I/O devices.
The cast
((AT91PS_PMC) 0xFFFFFC00)
means that the memory address 0xFFFFFC00 will be treated as a pointer to a structure of the typeAT91PS_PMC
. Within that structure, there is the Peripheral Clock Enable Register, thePMC_PCER
field, at some suitable offset from the address 0xFFFFFC00.Thus, the assignment arranges to write 1024 (
1 << 10
) to the PMC_PCER register, assuming that the base address 0xFFFFFC00 is correct.This sets the register to a value containing a single set bit. It is not the same as what most people would mean by 'setting a single bit'; that would be done by a line such as:
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_PWMC;
Note that this reads the current value of the PMC_PCER, modifies it, and writes it back. Whether it is safe to read and then write depends on the details of the chip.
There are at least two ways to do that:
AT91C_BASE_PMC->PMC_PCER = 0; AT91C_BASE_PMC->PMC_PCER &= ~(1 << AT91C_ID_PWMC);
The first assumes that only a single bit was set, so setting the value to 0 unsets that single bit. The second reads the current value of the PMC_PCER register, does a bitwise AND with a value that has a 1-bit everywhere except the AT91C_ID_PWMC bit (thus zeroing just that bit), and writes the value back.
Why is it done like this? To collect all the platform-specific details together and to avoid having to write each address manually, and so that the board can be revised later and code just recompiled instead of having to be rewritten.