Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

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 については 内部実装 を参照してください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away