BLE NanoのSerialクラスのバグ回避

BLE Nanoをmbedで使う場合、シリアルポート(TXD=D1, RXD=D0)を使うとD2とD3のポートが機能しなくなるという不具合があります。たとえば、D3にLEDをとりつけて下記のプログラムを実行するとLEDが点滅するはずですが、実際には点滅してくれません。

#include "mbed.h"

Serial pc(USBTX, USBRX); // USBTX == D1, USBRX == D0
DigitalOut led(D3);

int main(void)
{
    pc.baud(115200);
    led = 0;
     
    while (true) {
        pc.printf("hoge\r\n");
        led = 1 - led;
        wait(1);
    }
}

これは、Serial pc(USBTX, USBRX) を宣言した時点で、D2がCTS、D3がRTSに割り当たってしまうためです。そこでフロー制御を無効にする下記のコードを加えてみましたが、「そんなメソッド無いです」という趣旨のコンパイルエラーが出ました。

    pc.set_flow_control(Serial::Disabled);

ライブラリのバグっぽいので、ライブラリを修正すべくソースを追ってみましたが、泥沼にはまってしまいました。結局、バッドノウハウになってしまいますが、下記のようにすれば解決しました。

// (1) #include "mbed.h" の前にこの定数を定義する
#define DEVICE_SERIAL_FC 1
#include "mbed.h"

// (2) Serial::set_flow_controlを実装する
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) {
    FlowControl flow_type = (FlowControl)type;
    switch(type) {
        case RTS:
            serial_set_flow_control(&_serial, flow_type, flow1, NC);
            break;

        case CTS:
            serial_set_flow_control(&_serial, flow_type, NC, flow1);
            break;

        case RTSCTS:
        case Disabled:
            serial_set_flow_control(&_serial, flow_type, flow1, flow2);
            break;

        default:
            break;
    }
}

Serial pc(USBTX, USBRX);
DigitalOut led(P0_8);

int main(void)
{
    // (3) フロー制御を無効にする
    pc.set_flow_control(Serial::Disabled);
    
    pc.baud(115200);
    led = 0;
     
    while (true) {
        pc.printf("hoge\r\n");
        led = 1 - led;
        wait(1);
    }
}