Cortex-M3デバイスのビットバンド機能を管理するクラスを作成します。知らない人のために:プロセッサは、特定の領域内のすべてのビットを単語全体にマッピングします。これにより、特定ビットのアトミックセット操作が可能になります。クラス自体はstd :: uintptr_tで動作します。コンストラクタの場合、私はそれが何を指しているか気にしないので任意のポインタを許可したいと思います。これは、デバイスヘッダーで定義された構造体です。C++で入力引数として任意のポインタを取ることはできますか?
私の現在の実装では、とのコンストラクタを与える:
Bitband(uintptr_t address, uint32_t bitNumber);
Bitband(void * ptr, uint32_t bitNumber);
私のアプリケーションは、このようなコンストラクタを呼び出す:私はままにすると、彼は私が「uintptr_tを」に対する既知の変換を取得していないreinterpret_castは
Bitband foo(reinterpret_cast<uintptr_t>(&gpioPort->IDR), pin);
と'void *'。 すべての呼び出しに対してreinterpret_castを削除し、任意のポインタをコンストラクタの引数として取る明確な方法はありますか?
編集:ここでははクラスビットバンドとLEDのオンとオフをチューリングのための私の使用のために私の現在のコードです:
bitband.hpp
#pragma once
#include <stdint.h>
class Bitband
{
public:
Bitband(uintptr_t address, uint32_t bitNumber);
Bitband(void * address, uint32_t bitNumber);
inline void Set(bool val) const
{
uint32_t * const pData = reinterpret_cast<uint32_t *>(this->bbAddress);
*pData = val;
}
inline bool Get() const
{
uint32_t * const pData = reinterpret_cast<uint32_t *>(this->bbAddress);
return *pData;
}
private:
static uintptr_t GetBitBandAddress(uintptr_t address, uint32_t bit);
static bool IsSramAddress(uintptr_t address);
static bool IsPeripheralAddress(uintptr_t address);
uintptr_t const bbAddress;
/* Constants for bit band calculation for SRAM */
static uintptr_t const sramStartAddress = 0x20000000;
static uintptr_t const sramEndAddress = 0x200FFFFF;
static uintptr_t const sramBbBaseAddress = 0x22000000;
/* Constants for bit band calculation for Peripherals */
static uintptr_t const peripheralsStartAddress = 0x40000000;
static uintptr_t const peripheralsEndAddress = 0x400FFFFF;
static uintptr_t const peripheralsBbBaseAddress = 0x42000000;
};
bitband.cpp
#include "bitband.hpp"
#include <cassert>
Bitband::Bitband(uintptr_t address, uint32_t bitNumber) :
bbAddress(GetBitBandAddress(address, bitNumber)) {}
Bitband::Bitband(void * address, uint32_t bitNumber) :
bbAddress(GetBitBandAddress(reinterpret_cast<uintptr_t>(address), bitNumber)) {}
uintptr_t Bitband::GetBitBandAddress(uintptr_t const address,
uint32_t const bitNumber)
{
uintptr_t bbBase;
uintptr_t regionStartAddress;
assert(Bitband::IsPeripheralAddress(address)
|| Bitband::IsSramAddress(address));
/* Set the parameters depending on wether we are in peripherals region or sram
region. */
if(Bitband::IsSramAddress(address))
{
bbBase = Bitband::sramBbBaseAddress;
regionStartAddress = Bitband::sramStartAddress;
}
else if(Bitband::IsPeripheralAddress(address))
{
bbBase = Bitband::peripheralsBbBaseAddress;
regionStartAddress = Bitband::peripheralsStartAddress;
}
else
{
/* Invalid parameter */
__breakpoint(0);
}
uintptr_t byteOffset = address - regionStartAddress;
auto bitWordOffset = (byteOffset * 32) + (bitNumber * sizeof(uint32_t));
auto bitWordAddr = bbBase + bitWordOffset;
return bitWordAddr;
}
bool Bitband::IsSramAddress(uintptr_t address)
{
return (address >= Bitband::sramStartAddress)
&& (address <= Bitband::sramEndAddress);
}
bool Bitband::IsPeripheralAddress(uintptr_t address)
{
return (address >= Bitband::peripheralsStartAddress)
&& (address <= Bitband::peripheralsEndAddress);
}
私のクラスで使用されています私はちょうど/いくつかのLEDをオン・オフSTS)
led.hpp
#pragma once
#include <stdint.h>
#include "stm32l1xx.h" // Keil::Device:Startup
#include "bitband.hpp"
class Led
{
public:
Led(GPIO_TypeDef * const ledPort, uint16_t ledPin);
inline void Set(bool newState) { this->ledOutputBitBand.Set(!newState); }
private:
Bitband ledOutputBitBand;
};
led.cpp
#include <led.hpp>
#include <cassert>
Led::Led(GPIO_TypeDef * const port, uint16_t const pin) :
ledOutputBitBand(reinterpret_cast<uintptr_t>(&port->ODR), pin)
{
assert(pin < 16);
/* Set port mode to push pull */
port->MODER |= 1 << (2 * pin);
}
メインアプリケーション内使用
Led greenLed(GPIOD, 0);
greenLed.Set(true);
私は次のメッセージを取得reinterpret_castは取り残さ場合
は:
Src/led.cpp(5): error: no matching constructor for initialization of 'Bitband'
ledOutputBitBand(&port->ODR, pin)
^ ~~~~~~~~~~~~~~~
./Inc/bitband.hpp(9): note: candidate constructor not viable: no known conversion from 'volatile uint16_t *' (aka 'volatile unsigned short *') to 'uintptr_t' (aka 'unsigned int') for 1st argument; remove &
Bitband(uintptr_t address, uint32_t bitNumber);
^
./Inc/bitband.hpp(10): note: candidate constructor not viable: no known conversion from 'volatile uint16_t *' (aka 'volatile unsigned short *') to 'void *' for 1st argument
Bitband(void * address, uint32_t bitNumber);
^
./Inc/bitband.hpp(6): note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
class Bitband
^
./Inc/bitband.hpp(6): note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
1 error generated.
をだから私は、私は別のコンテキストではクラスビットバンドを使用したい場合、私は再びreinterpret_castはを使用する必要があるだろうと仮定しますか?
'&gpioPort-> IDR'を' void * 'に変換しても問題ありません(' IDR'が 'const'でない限り)。エラーメッセージ全体とその原因となるコードをコピーして貼り付けてください。 – molbdnilo
私はこれを試しませんでしたが、コンストラクタをテンプレート型へのポインタを受け取り、コンストラクタ自体の内部で再解析キャストを行うテンプレートを作成するとどうなりますか?異なるポインタ型を持つコンストラクタを実際に実際に呼び出すと、コードが大きくなることがあります(最適化されていない場合)が、あなたの呼び出しをきれいに見せるかもしれません。あるいは、再解釈キャストの語彙を短縮するためにマクロを使用することを検討することもできます。 –