UIAPduinoのシームレススイッチ


UIAPduinoを書き込みモードにするには,RSTスイッチを押したままUSBに接続する必要がある. マイコンのプログラムを作るときには,何度も書き換える必要があることが多く,その度にUSBを抜き挿しするのは面倒である. UIAPduinoの公式ページには,RSTスイッチで書き込みモードと実行モードを切り換える方法が,SeamlessSwitch.inoとして以下のようなコードと共に示されている.

void setup() {
  if (FLASH->STATR & (1<<14)) NVIC_SystemReset();
  SystemReset_StartMode(Start_Mode_BOOT);
  pinMode(PD4, OUTPUT);
  // ...
}

しかし,私が構築した環境はch32funを使っており,SystemReset_StartModeという関数が無い. そこで,同等の関数を以下のように定義してみた.

void SystemReset_StartMode(uint32_t Mode)
{
  FLASH->KEYR = FLASH_KEY1;
  FLASH->KEYR = FLASH_KEY2;
  FLASH->BOOT_MODEKEYR = FLASH_KEY1;
  FLASH->BOOT_MODEKEYR = FLASH_KEY2;
  FLASH->STATR &= ~(1<<14);
  if(Mode == Start_Mode_BOOT){
    FLASH->STATR |= (1<<14);
  }
  FLASH->CTLR |= CR_LOCK_Set;
}

そして,指定したコードを実行してみたのだが,期待する挙動とならない. かなりの試行錯誤を経て,ようやくその原因が分った. ch32funでは,PD4は0x34=52という数値が割り当てられている. 一方,UIAPduinoではこのピンには14という番号がつけられており,私の環境ではその番号でピンを指定するようにしたので,PD4ではなく14をOUTPUTにする必要があったのである. このコードをmain.cppに組み込んでみたところ,無事にスイッチで書込と実行のモード切り替えできるようになった.

当たり前のことなのだが,USB serialなどを使っている場合には,USBがPD4を使うので,このPINを使うことが出来無い. そのため,スイッチによるモード切り替えも動作しない. その場合には,bootloaderに入るけどもUSBの初期化が出来無くなるのかなと思っていたが,実際にはリセット後で実行モードが立上がる. この理由が分らないが,bootloaderがUSBを認識できなかったら,実行モードに切り替わるのかな. いずれにせよ,USBを使っている場合には,やはり抜き挿しが必要となる.

2026/3/18追記 main.cppの中でUSBを組込む直前に,USBのD-に使われている14ピンを少しの間だけLOWにするようにしたら,書き込み後に自動でUSBを認識するようになった. bootloaderにもUSBの認識前に14ピンをLOWにするコードを入れられたら,USBを使っている場合でも,RSTでモード切り替えができるかもしれない. しかし,bootloaderのサイズはかつかつらしいので,難しいかも.