5
2

More than 3 years have passed since last update.

Seeeduino XIAO 背面パッドをGPIOとして使う

Last updated at Posted at 2020-06-07

Seeeduino XIAO の背面には 6 つのパッドがあり、そのうち SWCLK (PA30)SWDIO (PA31) は GPIO ピンとして使用できます。

TL;DR

ボードライブラリ 1.7.6 時点では pinModedigitalWrite は使えません。
代わりにレジスタを直接設定する必要があります。digitalRead も同様です。

pa30_pa31.ino
void setup() {
  // instead of pinMode(PA30, OUTPUT) and pinMode(PA31, OUTPUT)
  (&(PORT->Group[PORTA]))->PINCFG[30].reg = (uint8_t)(PORT_PINCFG_INEN);
  (&(PORT->Group[PORTA]))->PINCFG[31].reg = (uint8_t)(PORT_PINCFG_INEN);
  (&(PORT->Group[PORTA]))->DIRSET.reg = (1 << 30);
  (&(PORT->Group[PORTA]))->DIRSET.reg = (1 << 31);
}

void loop() {
  // instead of digitalWrite(PA30, HIGH) and digitalWrite(PA31, HIGH)
  (&(PORT->Group[PORTA]))->OUTSET.reg = (1 << 30);
  (&(PORT->Group[PORTA]))->OUTSET.reg = (1 << 31);
  delay(1000);

  // instead of digitalWrite(PA30, LOW) and digitalWrite(PA31, LOW)
  (&(PORT->Group[PORTA]))->OUTCLR.reg = (1 << 30);
  (&(PORT->Group[PORTA]))->OUTCLR.reg = (1 << 31);
  delay(1000);
}

SWCLK/SWDIO パッド

SWD用に用意されたパッドです。Seeeduino XIAO では基板背面に配置されています。上記の XIAO の回路図(該当部分のみ抜粋)からわかるとおり、これらのパッドに繋がっているピンは PA30, PA31 という PORTA の GPIO として利用できます。

他の背面パッドと同様に直接はんだづけしない限りは利用機会は少ないでしょう。しかし、利用できる物理ピン数が限られている XIAO にとって、追加で 2 つも GPIO ピンが使えるメリットは大きいです。

pinMode と digitalWrite

冒頭で示したとおり、残念ながら pinModedigitalWrite は使えません。理想では、Arduino であれば以下のようなスケッチになるはずです。

pa30_pa31_ideal.ino
// 注意: このスケッチは動作しない

void setup() {
  pinMode(PA30, OUTPUT);
  pinMode(PA31, OUTPUT);
}

void loop() {
  digitalWrite(PA30, HIGH);
  digitalWrite(PA31, HIGH);
  delay(1000);

  digitalWrite(PA30, HIGH);
  digitalWrite(PA31, HIGH);
  delay(1000);
}

実際にはどちらの関数も正しく動作しません。原因は variant.cpp にあります。
variant.cpp には Arduino で指定するピン番号と SAMD21G18 のピン番号などの対応表が定義されています。

variant.cpp(抜粋)
const PinDescription g_APinDescription[]=
{
  // 0..10 - Digitabl & Analog pins
  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // ADC/AIN[4]
  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel18, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10 }, 
  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel19, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 }, 

  // ... (snip) ...

  // 14..16 - USB
  // --------------------  
  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE } // USB/DP

} ;

この対応表には PA30, PA31 にあたるエントリがありません。

pinModedigitalWrite はこのエントリをもとに、指定されたピン番号に該当するポート名や属性を参照し適切なレジスタを設定します。PA30, PA31 のエントリがないために適切なレジスタが判明せず動作しません。

レジスタを直接設定

variant.cpp は対応していませんが PA30, PA31 に相当するレジスタは存在します。

pinMode(PA30, OUTPUT) に対応する指定は以下になります。

(&(PORT->Group[PORTA]))->PINCFG[30].reg = (uint8_t)(PORT_PINCFG_INEN);
(&(PORT->Group[PORTA]))->DIRSET.reg = (1 << 30);

digitalWrite(PA30, HIGH) および digitalWrite(PA30, LOW) に対応する指定は以下になります。

(&(PORT->Group[PORTA]))->OUTSET.reg = (1 << 30);  // HIGH
(&(PORT->Group[PORTA]))->OUTCLR.reg = (1 << 30);  // LOW

PA31 も同様です。

これ以外のピンモードや digitalRead については 内部実装 を参照してください。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2