RISC-V 使ってみたら、USART使うとツールとの接続が切れる

MCU

 秋月電子で、安いCPUを探していたところ、RISC-VのCH32V003J4M6が見つかった。
物は試しで、早速購入し書き込みツールである、WCH-LinkEエミュレーターと共に購入し、早速動作確認を始めたところ、デフォルトのプロジェクトで躓いたので記載しておく。

 MounRiver Studioを早速インストールして、チップの選択を行うと、デフォルトのプロジェクトでは、USARTからの入力されたものをbit反転したものを送り出すという非常にシンプルなものが作成される。
 見た目にもシンプルなので簡単に動きそうだと思ったのだが、2つの壁が存在していた。

 1つ目は、ツールの設定で、デフォルトがARMのデバッガとして認識されているらしく、これをRISC-Vの物と認識させる必要があった。
 ①Flash→Configurationにて、ツールの設定を行う。
 ②Target Modeの欄のところで、QueryをクリックしてWCH-LinkRVとなるようにする。
 ③Erase Code Flashの欄のところで、By Power offを選択後、Applyを押下し、Erase処理を行う。
 ④下部の表示でEraseがSuccessしていることを確認する。

 2つ目は、デバッグを開始し、Main関数のところにBreakを張ってRunさせると、そこまでは正常に動作しているのだが、順にStep実行していくと、USART関係の初期化をしている部分を通過する部分で、デバッガとの通信がおかしくなりStep動作が完了しない。
 原因は、SWIO端子がUSARTのTX端子となってしまうことから、SWIO端子がなくなる結果となり上記事象が発生していた。
 色々と調査したが、SWIO端子を生かしたままUSARTのTX,RXを両方使うのは無理との結論に至った。(端子数が少なすぎるからしょうがない。)今回の目標は、単純にUSARTからのPrintfデバッグが行えるかを確認するレベルであったので、RX端子の使用をあきらめ、TX端子のみ使用する方向とした。
 デフォルトのコードを下記のように修正した。

main.c

void USARTx_CFG(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    USART_InitTypeDef USART_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1, ENABLE);


    /* Original USART1 TX-->D.5   RX-->D.6 */
    /* Change   USART1 TX-->D.6   RX-->None */
    GPIO_PinRemapConfig(GPIO_PartialRemap2_USART1, ENABLE);

//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
//    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//    GPIO_Init(GPIOD, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 //   USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;

    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    USARTx_CFG();

    while(1)
    {
#if 0
        while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
        {
            /* waiting for receiving finish */
        }
        val = (USART_ReceiveData(USART1));
        USART_SendData(USART1, ~val);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
        {
            /* waiting for sending finish */
        }
#endif
        printf("HelloUart!\n");
        Delay_Ms(500);
    }
}

debug.c

void USART_Printf_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1, ENABLE);

    GPIO_PinRemapConfig(GPIO_PartialRemap2_USART1, ENABLE);

//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;

    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

 エミュレーターをつないだままでの確認しかしていないから、エミュレーターを取り外せばきちん想定通りに動作できたかもしれない。

 しかし、こんなの初めからどこかに書いておけよと思ったら、秋月電子のよくある質問にその旨記載されていた。

コメント

タイトルとURLをコピーしました