stm32plusを使う - STM32
GPIO †
解説 †
stm32plusでは,各ペリフェラルに対してFeature(特徴)をオプションとして渡して初期化することで,コード量の省略と実行時処理の削減を実現している.
GpioPortクラス †
GpioPort<uint32_t TPortAddress,class... Features> : public GpioPortBase,public Features...
|
引数 | デフォルト値 | 説明 |
uint32_t TPortAddress
| - | GPIOxのベースアドレス GPIOA_BASE,GPIOB_BASE,GPIOC_BASE,... |
class... Features
| - | 使用するFeature(複数可) DigitalInputFeature,DigitalOutputFeature,AnalogInputFeature,AlternateFunctionFeatureとそのDefault |
GpioX †
GpioC<DefaultDigitalOutputFeature<8> > pc;
このコードでは,GpioCのテンプレートにDefaultDigitalOutputFeature<8>というFeatureを渡してGpioCの実体pcを生成している.
GpioPorts.hによると,
template<class... Features> using GpioC=GpioPort<GPIOC_BASE,Features...>;
とあり,GpioCはGpioPortを特殊化したものであるということがわかる.
Feature †
Default*Featureは,それぞれのFeatureのデフォルト値を入れたテンプレートになっている.
AlternateFunctionFeature †
- F1
AlternateFunctionFeature<GPIOSpeed_TypeDef TSpeed,GpioOutputType TOutputType,uint8_t... TPins> : public Gpio
|
引数 | デフォルト値 | 説明 |
GPIOSpeed_TypeDef TSpeed
| GPIO_Speed_50MHz
| GPIOのスピード GPIO_Speed_50MHz,GPIO_Speed_100MHz |
Gpio::GpioOutputType TOutputType
| Gpio::PUSH_PULL
| GPIOのアウトプットタイプ Gpio::PUSH_PULL,Gpio::OPEN_DRAIN |
uint8_t... TPins
| - | 設定するピンの番号(複数可) 数値 0〜15 |
複数のAFIOが割り当たっているピンの機能の選択は,StdPeriphLib同様にリマップ関数を使うはず(要検証).
- F4
AlternateFunctionFeature<uint8_t TAfSelection,GPIOSpeed_TypeDef TSpeed,GpioOutputType TOutputType,GpioPullUpDownType TPullUpDownType,uint8_t... TPins> : public Gpio
|
引数 | デフォルト値 | 説明 |
uint8_t... TAfSelection
| - | 設定するAFIOの種類 GPIO_AF_TIM1〜5,GPIO_AF_TIM8〜14,GPIO_AF_I2C1〜3,GPIO_AF_SPI1〜3,GPIO_AF_USART1〜3,GPIO_AF_UART4〜5,GPIO_AF_USART6,GPIO_AF_FSMC,GPIO_AF_SDIO |
GPIOSpeed_TypeDef TSpeed
| GPIO_Speed_50MHz
| GPIOのスピード GPIO_Speed_50MHz,GPIO_Speed_100MHz |
Gpio::GpioOutputType TOutputType
| Gpio::PUSH_PULL
| GPIOのアウトプットタイプ Gpio::PUSH_PULL,Gpio::OPEN_DRAIN |
Gpio::GpioPullUpDownType TPullUpDownType
| Gpio::PUPD_NONE
| プルアップ/ダウンの設定 Gpio::PUPD_NONE,Gpio::PUPD_UP,Gpio::PUPD_DOWN |
uint8_t... TPins
| - | 設定するピンの番号(複数可) 数値 0〜15 |
AnalogInputFeature †
AnalogInputFeature<uint8_t... TPins> : public Gpio
|
引数 | デフォルト値 | 説明 |
uint8_t... TPins
| - | 設定するピンの番号(複数可) 数値 0〜15 |
DigitalInputFeature †
DigitalInputFeature<GPIOSpeed_TypeDef TSpeed,GpioPullUpDownType TPullUpDownType,uint8_t... TPins> : public Gpio
|
引数 | デフォルト値 | 説明 |
GPIOSpeed_TypeDef TSpeed
| GPIO_Speed_50MHz
| GPIOのスピード GPIO_Speed_50MHz,GPIO_Speed_100MHz |
Gpio::GpioPullUpDownType TPullUpDownType
| Gpio::PUPD_NONE
| プルアップ/ダウンの設定 Gpio::PUPD_NONE,Gpio::PUPD_UP,Gpio::PUPD_DOWN |
uint8_t... TPins
| - | 設定するピンの番号(複数可) 数値 0〜15 |
DigitalOutputFeature †
DigitalOutputFeature<GPIOSpeed_TypeDef TSpeed,GpioOutputType TOutputType,GpioPullUpDownType TPullUpDownType,uint8_t... TPins> : public Gpio
|
引数 | デフォルト値 | 説明 |
GPIOSpeed_TypeDef TSpeed
| GPIO_Speed_50MHz
| GPIOのスピード GPIO_Speed_50MHz,GPIO_Speed_100MHz |
Gpio::GpioOutputType TOutputType
| Gpio::PUSH_PULL
| GPIOのアウトプットタイプ Gpio::PUSH_PULL,Gpio::OPEN_DRAIN |
Gpio::GpioPullUpDownType TPullUpDownType
| Gpio::PUPD_NONE
| プルアップ/ダウンの設定 Gpio::PUPD_NONE,Gpio::PUPD_UP,Gpio::PUPD_DOWN |
uint8_t... TPins
| - | 設定するピンの番号(複数可) 数値 0〜15 |
細かいお話 †
Featureの全てに共通する
uint8_t... TPins
だが,stm32plusを使う - STM32#ld75c0c1でも述べたように,複数のピンをカンマ区切りで指定して,例えば
GpioC<DefaultDigitalOutputFeature<0,2,3> > pc;
のように扱うことができる.
これは,可変長の引数をコンパイル時に再帰的に処理するというテンプレートメタプログラミング(TMP)の,稀に見る実用例である.
例えば,最も単純なAnalogInputFeatureを例にとってコンストラクタを見ると,
AnalogInputFeature(GpioPortBase& port) : Gpio(port) {
uint32_t pins;
// recurse to get the pin mask
pins=0;
GpioPinMerge<TPins...>(pins);
// do the initialisation
initialise(pins);
}
となっており,更に親クラスであるGpioのコードをたどるためにGpio.hを読むと,
namespace {
template<uint8_t TPin>
void GpioPinMerge(uint32_t& pins) {
pins|=1 << TPin;
}
template<uint8_t First,uint8_t Next,uint8_t... Rest>
void GpioPinMerge(uint32_t& pins) {
pins|=1 << First;
GpioPinMerge<Next,Rest...>(pins);
}
}
というコードが見つかる.
この,GpioPinMergeなるテンプレート関数がコンパイル時に再帰的に処理され,ピン番号の列を16bitのバイナリ列に変換しているのである.
例えば,TPinsとして0,2,3が渡されたとすると,まず最初に
void GpioPinMerge<0,2,3>(uint32_t &pins)
が呼ばれるため,実際の処理内容としては,後の方のテンプレート関数が呼ばれ
となる.次には
void GpioPinMerge<2,3>(pins)
が呼ばれ,同様に
最終的に
void GpioPinMerge<3>(pins)
すなわち前の方のテンプレート関数が呼ばれ,
となる.
ただし,この旨みは指定するピン番号等がコンパイル時に定数であることが必要なので,このへんを動的にいじるヘンタイさんには別途用意されているGpioPinInitialiser::initialise関数を呼ぶ必要がある.