mardi 3 février 2015

Pointer to peripheral hardware as template parameter

I want to access STM32F0 peripheral register through C++ templates. A gpio port for example is defined as follows by vendor:



typedef struct { uint32_t PUPDR; uint32_t ODR; ... } GPIO_TypeDef;
#define GPIOA_BASE 0x1000200030004000 // peripheral memory address
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)


So you can access hardware registers by GPIOA->ODR. I created template output class with port and pin as parameter.



template <uint32_t port, uint32_t pin>
class Output {
public:
static set() {
GPIO_Typedef * castedPort = reinterpret_cast<GPIO_TypeDef *>(port);
// set pin
}
};

Output<GPIOA_BASE, 1>::set();


This compiles with Launchpad g++ (g++ (i686-posix-dwarf-rev3, Built by MinGW-W64 project) 4.8.2).


But I want to use GoogleTest to test my code and so I created a fake register GPIO_TypeDef OutputTestPort;. But of course this fails.



could not convert template argument ‘OutputTestPort’ to ‘unsigned int’ stm32::Gpio::Output<OutputTestPort, 3>::set();


If I cast pointer to uint32_t, than it is no constant expression and for template parameter prohibited.



int32_t const port = reinterpret_cast<int32_t>(&OutputTestPort);
stm32::Gpio::Output<port, 3>::set();

error: the value of ‘port’ is not usable in a constant expression stm32::Gpio::Output<port, 3>::set();


So I tried pointer as parameter directly:



template <GPIO_TypeDef * port, uint32_t pin>
class Output {
/* implementation */
};


This works fine for GoogleTest with g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2 but know Lauchpad compiler fails:



error: '1207961600u' is not a valid template argument for GPIO_TypeDef*' because it is not the address of a variable


So is there any way to make this work, getting valid code for embedded controller and GoogleTest?


Aucun commentaire:

Enregistrer un commentaire