Memory mapped I/O made easy with ANSI C

Ich habe hier mal in einem einzigen Demo-C-Source das geballte Knowhow zusammengefasst, wie man für einen Rechner mit Memorymapped I/O (z.B. ARM oder Motorola 68000/ColdFire) korrekt den Zugriff auf ein Hardwareregister via Pointer realisiert:

/*
 * Memory mapped I/O made easy with ANSI C
 * commented by Matthias Arndt <marndt@asmsoftware.de>
 */
#include <stdint.h>
/* temporary valid location for demonstration purposes */
uint8_t storage;
/* Now the magic declaration pointer to a hw register:
 * We point it to some known storage but ofcourse for pointing
 * to a real I/O hardware register, one would supply a constant
 * register address.
 *
 * a) declare it volatile because hardware I/O locations may change inside
 *    a different context (interrupt and/or hardware event)
 * b) make the pointer address const between register name and the type
 *    definition so that noone may modify the pointer
 * c) adding const before the declaration will declare a read/only register
 */
volatile uint8_t * const HWREG = &storage;
/* to point to real I/O you would use the following syntax: */
/* volatile uint8_t * const HWREG = (uint8_t *)0xF000; */
/* just some demo calls */
void task(void);
uint8_t access(void);
void task()
{
	*HWREG = 0x5a; /* set I/O for demo purpose */
	/* access to alter the pointer is forbidden! Uncomment to try! */
	/* HWREG = (uint8_t *) 0xaaaa; */
}
uint8_t access()
{
	return(*HWREG); /* read I/O */
}

Für 8051 oder andere Plattformen, die ähnlich verquerte Speicherbereiche haben, sollten zusätzliche Angaben  verwendet werden, die den Zugriff auf den richtigen Speicherbereich mappen, etwa XRAM beim 8051.