Skip to content

Instantly share code, notes, and snippets.

@safiire
Created June 9, 2015 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save safiire/04e98b2b5cf19fedd065 to your computer and use it in GitHub Desktop.
Save safiire/04e98b2b5cf19fedd065 to your computer and use it in GitHub Desktop.
Manipulation of Memory Mapped Registers using C++ Templates (Technique from Olivier Gillet's Avril AVR Library)
#include <stdio.h>
#include <stdint.h>
//// Create some pretend Memory Mapped Registers
volatile uint64_t memory_mapped_registers[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
#define bit_depth uint64_t
#define mmio_byte(mem_addr) (*(volatile bit_depth *)(mem_addr))
//// Create 8 fake registers
#define R0 mmio_byte(memory_mapped_registers + 0)
#define R1 mmio_byte(memory_mapped_registers + 1)
#define R2 mmio_byte(memory_mapped_registers + 2)
#define R3 mmio_byte(memory_mapped_registers + 3)
#define R4 mmio_byte(memory_mapped_registers + 4)
#define R5 mmio_byte(memory_mapped_registers + 5)
#define R6 mmio_byte(memory_mapped_registers + 6)
#define R7 mmio_byte(memory_mapped_registers + 7)
//// A struct wrapper around a register
#define IORegister(reg) \
struct reg##Register { \
static volatile bit_depth *ptr(){ \
return &reg; \
} \
reg##Register &operator=(const bit_depth &value){ \
*ptr() = value; \
return *this; \
} \
};
IORegister(R0);
IORegister(R1);
IORegister(R2);
IORegister(R3);
IORegister(R4);
IORegister(R5);
IORegister(R6);
IORegister(R7);
////
// Control of one bit in a register
template <typename Register, uint8_t bit>
struct BitInRegister {
static void clear(){
*Register::ptr() &= ~(1 << bit);
}
static void set(){
*Register::ptr() |= (1 << bit);
}
static void toggle(){
*Register::ptr() ^= (1 << bit);
}
static bit_depth value(){
return *Register::ptr() & (1 <<bit) ? 1 : 0;
}
};
////
// A resource that can make us get pizza for dinner, by specifying bits in the registers
template <typename PizzaEnableBit, typename DinnerTimeBit, typename FullOfFoodBit>
struct FoodController {
typedef PizzaEnableBit Pizza;
typedef DinnerTimeBit Dinner;
typedef FullOfFoodBit Full;
static inline void eat_pizza_for_dinner(){
Pizza::set();
Dinner::set();
}
static inline void pizza_done(){
Pizza::clear();
Dinner::clear();
Full::set();
}
};
//// Shorthand type that knows about these specific bits.
typedef FoodController< BitInRegister<R4Register, 5>,
BitInRegister<R1Register, 2>, BitInRegister<R7Register, 7> > PizzaController;
int main(void){
PizzaController::eat_pizza_for_dinner();
for(int i = 0; i < 8; i++){
printf("R%d: %lld\n", i, memory_mapped_registers[i]);
}
PizzaController::pizza_done();
for(int i = 0; i < 8; i++){
printf("R%d: %lld\n", i, memory_mapped_registers[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment