ラベル BlackPill の投稿を表示しています。 すべての投稿を表示
ラベル BlackPill の投稿を表示しています。 すべての投稿を表示

2024年5月3日金曜日

BlackpillというSTM32 board(8)4chオシロスコープ設計資料

中華STM32基板のBlackpillを味見しています.

4chオシロを作ったので設計データを公開します.コピろうが改変しようが好きにしてください.でもわたしは責任は取りません.免責、免責、Let's 免責だーんす!!

こんなのです.PCの画面です.
STM32でADCしたサンプリングデータをUSB COMでPCへ送信し、PC上のpythonで画面表示しています.

仕様:
・4ch BNCコネクタ
・ACカップリングのみ(DCカップリングできない)
・v/div VRで可変するので融通無碍
・入力Z 100kΩ
・サンプリング周波数 最大50kHz~最小100Hz
・トリガ機能なし
・電源 USB給電
・USB-C
・PC側アプリ 自作グラフ描きアプリ(python)
・ケース 3Dプリンタ
・外形 106x106x41mm

内部仕様:
・STM32F401(Blackpill)
・基板サイズ100x100mm
・RTOSは使わなかった
・firmwareの開発ツール STM32CubeIDE
・USB protocol Virtual COM port
・python3

外観:

基板:

回路図:

firmware source変更点:
CubeMXで生成したsourceに追記したところはそんなに多くないです.
"hirasaka"でsearchすると次の3fileがヒットします.その界隈です.
 main.c
 stm32f4xx_it.c
 usbd_cdc_if.c

使い方:
USB-CでPCと接続します.デバマネでCOM番号を目視確認してください.
PCのpowershellで起動します.
 python STM32_oscillo_rev1.py
COM番号を問うダイアログが表示されますので、選んでSETをポチッとする.
あとはグラフが表示されるはずです.

初回は以下のpython moduleのインストが必要になるでしょう.じゃないとerrorで停まります.
 pip install matplotlib
 pip install animation
 pip install pyserial
 pip install numpy

設計資料のdownload:
こちらのリンクが詰め合わせzipです.
中身は、
 ・回路図
 ・PCB gerber
 ・STM32cubeIDE firmware project
 ・python source
 ・ケースの3DP印刷用CAD fileなど (rsdocx,stl,3mf)(DegignSpark Mechanical)
 ・写真など
なにか変だったらコメントください.

ケースの構造はこうゆう2枚貝です.(CAD画面)
詰め合わせには、このような耳付きも入っています.3DPのベッド剥がれを防止するための耳です.

つぎはグラフ描きをスマホにやらせたいものです.


かしこ

2024年4月21日日曜日

BlackpillというSTM32 board(7)freeRTOS初体験

中華STM32基板のBlackpillを味見しています.

STM32CubeIDEでfreeRTOSを使えます.

具体的には、STM32CubeMXを操作するとthreadをポコポコ生成できます.右画面でthreadの様々なparameterを設定できますが、何の意味なのかぜんぜん分かりません.なにせ初体験なもので.→参考サイト

お試しで3つのthreadを生成させるように設定したら、、、main.cに3つのloop()が出現しました.こんな風に.

void orange(void const * argument){
  for(;;)  {
    osDelay(*((uint32_t*)argument));
  }
}

void blue(void const * argument){
  for(;;)  {
    osDelay(1);
  }
}

void red(void const * argument){
  for(;;)  {
    osDelay(1);
  }
}

ふ~ん、便利でいい.

RTOS抜きのprogrammingだと単一のloop()内で、
・データ処理
・push SWをチェック
・host commandをチェック
・LED indicatorを点滅
などの数多くの仕事を1箇所でやるのでアタマを使います.

でもloop()の複数併存が許されるのでしたら、個々の仕事は個々のloop()でやらしとけばいいので脳みそがらくちんです.

世の中がRTOSいう理由がわかりました.

こないだprogramしたSTM32オシロもRTOSで作り直そうかな.

6へ    8へ

かしこ

2024年4月19日金曜日

BlackpillというSTM32 board(6)4chオシロ基板

中華STM32基板のBlackpillを味見しています.

前回で2ch 20kHzサンプル出来たので、4chプリント基板を発注しました.自分の机でオシロとして使うため.

基板はいつものJLCPCB.現在は深圳宝安空港のコンテナで出荷待ちしてます.

気まぐれで紫色のレジストを選択してしまったため、こんなキモい色の基板になります.紫でも値段は変わりませんが、基板製作日数が緑レジストよりも1日遅くなります.
予想SPEC:
・ACカップリングのみ(DCカップリングできない)
・入力Z 100kΩ
・電源 USB給電
・USB-C
・STM32F401
・サンプリング周波数 最大50kHzぐらい(可変)
・4ch BNC
・v/div 未定 というかVRで可変するので融通無碍
・基板サイズ100x100mm
・PC側アプリ 自作グラフ描きアプリ(python)
・ケース 3Dプリンタ

Rail-to-Rail opampを買いに秋月へ行かなくちゃいけない.

#千石のネジ屋が開店しました.記念のクリアフォルダを配布してたみたいですけど、アニメじゃないのでそんなに欲しくないと思っちゃった.

5へ     7へ

かしこ

2024年4月14日日曜日

BlackpillというSTM32 board(5)(ADC 2ch運用&高速化 20kHzサンプル)

中華STM32基板のBlackpillを味見しています.

前回は、ADCを2ch運用しましたが、サンプル周波数は500Hzと遅かったです.
今回は、サンプル周波数を20kHzまで上げます.

無理矢理で40kHzまで行けるかな?って感触ですが、20kで止めておきました.律速は割り込みroutineでbuffer copyとかする部分ですので高速化の余地はありそうですが、さりとて100kHzまで上げられる気はしません.

なお、CPU STM32F401のADC性能では1MHz近いサンプルが可能のようです.

ーーーー
やったことのリスト

・サンプリング周波数は20kHz
・連続する1000ptsをメモリにストア
・同1000ptsをCDC(USB COM)でPCへ送信する
・サンプリング周期はTIM3の出力する50uSecで決める (つまりhardware自走)
・ADC入力はIN1とIN9の2本 (2ch scan)
・ADCは1トリガで2サンプル (2ch scan)
・DMAを使う
・DMAはIN1サンプル→DMA→IN9サンプル→DMAという動作をする
・すなわち、TIM3→ADC(IN1)→DMA→ADC(IN9)→DMAがhardwareで自走する
・ADC完了をIRQで知る
・同IRQで1000pts x 2ch分のbufferに積む
・同IRQでbuffer fullになったらUSB送信を起動
・USB転送終了をIRQで知る
・USB busyの最中はADC IRQでbufferに積まない (buffer衝突防止)
・ADCは12bitなので、1サンプルあたりASCIIの3bytesをbufferに積む
・ゆえに1USB送信あたり1000x2x3=6000bytes
・USB FULL SPEED(12Mbps)で6000bytes送信するのにover head込みで50mSecぐらいかかっている(実測)

ーーーー
前回も触れましたが、いろんな疑問点について

Q:STM32CubeIDEとArduinoIDEのどちらを使う?
A:STM32CubeIDE
ArduinoIDEだとUSB関連のexampleが見当たらず使いませんでした.
STMCubeIDEのCDC exampleを雛形にして改造しました.

Q:TIM3+ADC+DMAを起動するやりかた
A:HAL_Delay(3000);
  HAL_TIM_Base_Start_IT(&htim3);
  HAL_ADC_Start_DMA(&hadc1, &buffer[0], 2);
main()の最初の方の各種Initの後で1回だけこれをやると、あとはhardwareが自走してくれます.詳細は前回を参照.
HAL_Delay(3000)は必須です.USB接続の直後は不安定なので3秒待ちます.

Q:ADC終了割り込みはどれを使えばいいんだ?
A:HAL_ADC_ConvCpltCallback()
事情は前回を参照.

Q:USB終了割り込みはどれを使えばいいんだ?
A:CDC_TransmitCplt_FS()
USB COMのUSBの転送終了を知るにはこれが良いようです.
USB転送終了までbufferへのADC dataの上書きを禁止するためにこの割り込みを使います.

Q:DMAのdata widthは8/16/32bitのどれにしようか?
A:32bitにした
事情は前回を参照.

Q:USB転送終了calbackでやること
A:busy flugを下げる
USB転送が終わると自動的にこの関数がcallされます.
CDC_TransmitCplt_FS(){
  uint8_t result = USBD_OK;
  UNUSED(Buf);
  UNUSED(Len);
  UNUSED(epnum);
  usb_busy = 0;   ←これを追加
  return result;
}

Q:HAL_ADC_ConvCpltCallback()で何をやる?
A:改造の中心部がここ、main()の上の辺りにでも追加、weak宣言されてる
#define PTS 1000   連続サンプル数1000
#define CH 2   ADC 2ch scan
#define BUFSIZE (3*PTS*CH)  USB bufferサイズ6000bytes
int usb_busy = 0;  USB busyフラグ
static uint32_t buffer[4];  ADC dataを都度格納する場所
static uint8_t usbbuf[BUFSIZE+100];   USB buffer確保
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
  static int N = 0;
  if(usb_busy==0){
    char c[15];
    sprintf(c,"%03X",buffer[0]);  IN1 ASCII変換
    usbbuf[N++] = c[0]; strcat()は遅いので使うのやめた
    usbbuf[N++] = c[1];
    usbbuf[N++] = c[2];
    sprintf(c,"%03X",buffer[1]);  IN9 ASCII変換
    usbbuf[N++] = c[0];
    usbbuf[N++] = c[1];
    usbbuf[N++] = c[2];
  }
  if(N>=BUFSIZE){ 6000bytes積んだらUSB起動
    usbbuf[BUFSIZE] = '\n';
    N=0;
    usb_busy=1; USB転送はmain()で起動する
  }
}

追記:sprintf()も遅いので自作のitoa()に変えたら50kHzサンプルで動きました.

Q:main()でUSB転送を起動するには?
A:while()でCDC_Transmit_FS()をcallする
while (1)  {
  if(usb_busy==1) CDC_Transmit_FS(&usbbuf[0],BUFSIZE+1);
}

ーーーー
STM32CubeMXの設定について.

ADCの設定
DMAの設定
TIM3の設定
clk=84MHzなので、84M÷84÷50=20kHz

BlackPillを味見するのはここまでにしとうございます.

簡易オシロを作ろうかな.ESP32のほうがいろいろと高速かもしれない.

4へ    6へ

かしこ

2024年4月11日木曜日

BlackpillというSTM32 board(4)(ADC 2ch運用)

中華STM32基板のBlackpillを味見しています.

前回に続きまして、今回もADCを動かします.前回は1chでしたが、今回は2chに拡張します.clock系とかNVICとかUSBとかTIM3の設定は前回を読んでください.以下ではADC+DMAにfocusします.

ADCを動かすと言ってもいろんな動かし方の作法があるわけでして、、、ここでやったのは次の仕組みです.
・サンプリング周波数は500Hz
・連続する500ptsをメモリにストア (1秒分)
・同500ptsをCDC(USB COM)でPCへ送信する
・サンプリング周期はTIM3の出力する2mSecで決める (つまりhardware自走)
・ADC入力はIN1とIN9の2本 (2ch scan)
・ADCは1トリガで2サンプル (2ch scan)
・DMAを使う
・DMAはIN1サンプル→DMA→IN9サンプル→DMAという動作をする
・すなわち、TIM3→ADC(IN1)→DMA→ADC(IN9)→DMAがhardwareで自走する
・ADC完了をIRQで知る
・同IRQで500pts x 2ch分のbufferに積む
・同IRQでbuffer fullになったらUSB送信を起動 (USB送信はブロックモード)
・ADCは12bitなので、1サンプルあたりASCIIの3bytesをbufferに積む
・ゆえに1USB送信あたり500x2x3=3000bytes
・USB FULL SPEED(12Mbps)で3000bytes送信するのにover head込みで20mSecぐらいかかるのでその間はADC変換動作は滞るが気にしない

ポエム的な表現では、こんなイメージ.
1)ADC変換のTRIGはTIM3にやらせる (2mSec毎)
2)2ch scanのAD dataはDMAでmemoryにコピーさせる
3)2が終わったら割り込みで知らせてもらう
4)1へもどる
5)1234をhardwareで自走させる
6)3の割り込みでUSB buffer(3000bytes)に積むのとUSB転送はprogramで面倒をみる

ーーーー
だがしかし、いろいろな疑問があります.

Q:ADC終了割り込みはどれを使えばいいんだ?
A:HAL_ADC_ConvCpltCallback()

ADC_IRQHandler()
ADC割り込み.これはお役御免でしょう.なぜかというと、ADC→DMAと自走するのでADC変換終了割り込みの意味がない.

DMA2_Stream0_IRQHandler()
DMA割り込み.変換終了をDMA割り込みで受領するのは合理的なのですが、、、うまく動かない.
2ch scanする時を考えると、2ch scan終了でDMA割り込みしてもらいたいが、実際の挙動は1ch目変換→DMA割り込み→2ch目変換→DMA割り込みと2度割り込んでくる.これは困る.DMAのflugをチェックすれば回避できるのだろうが、使い心地が悪い.
追記:後日この2度割り込みが再現しなくなって戸惑っています

HAL_ADC_ConvCpltCallback()
これは期待通りの割り込みをしてくれる.(2ch scan→割り込みということ)
weak宣言されているので、同名でmain()の近所に宣言して上書きして使う.


Q:DMAのdata widthは8/16/32bitのどれにしようか?
A:32bitにした

まず背景を書くと、
・ADCは12bitであるが、DR registerは32bitであり、右詰めで納まる
・DMAは8/16/32bitの選択が可能
・DMA起動関数の第2引数が格納bufferであり32bitで定義されている
  HAL_ADC_Start_DMA(&hadc, uint32_t* pData, Length)

この背景から32bit=wordで統一しました.
netの事例では16bit=half wordで実装しているケースもありますが.


Q:多ch scan時のADC出力形態はどうなっている?
A:DRレジスタは1つしかないのでDMA推奨

ADCは最大16chをscanできる仕様です.つまり、TRIG1発で16chをシーケンシャルに変換0変換1・・・変換16まで全自動で行えます.
ならば16ch ADC dataはDR0,DR1,DR2,,,,DR15へパラレル出力されるのでしょうか?
datasheetによるとSTM32のDRはそうなっていません.DRは1つだけです.(32bit幅)
これは何を意味するのかというと、いくら全自動16ch変換できるとはいえ、ADC dataは各ch毎に逐次採取しないとどんどん上書きされちゃうという、片手落ちな仕様であります.いちいちprogramでそんなものを面倒見ていたら他の仕事ができなくなってしまいます.
そんな悩みを解決してくれるのがADC+DMAの組み合わせです.DMAに16個のbufferを割り当てて、ADC dataをbufferに自動転送させます.そして、16個の変換が終わったら割り込みが発生します.
(ただし此処で実装するのは2ch scanですので)


Q:TIM3+ADC+DMAを起動するやりかた
A:HAL_TIM_Base_Start_IT(&htim3);
  HAL_ADC_Start_DMA(&hadc1, &buffer[0], 2);

main()の最初の方で1回だけこれをやると、あとはhardwareが自走してくれます.(あらかじめの設定は必要、後述)

DMAの最後の引数2は「buffer2つを埋めろ」の意味です.2ch scanなので、
TIM3→ADC(IN1)→DMA→ADC(IN9)→DMA→割り込み
が実行されます.

これを4にしたらどうなるか?
「buffer4つを埋めろ」なので、
TIM3→ADC(IN1)→DMA→ADC(IN9)→DMA
TIM3→ADC(IN1)→DMA→ADC(IN9)→DMA→割り込み
という動作になりました.ゆえに8とか16とかも出来るのでしょう.便利よね.


Q:TIM3とADCとDMAをバインドするにはどうするの?
A:STM32CubeMXをつかう

下記の設定にする.
Data Alignment:32bit DRの下12bitにADC dataを格納する.

Scan Conversion Mode:2ch scanする.

DMA Continuous Requests:DMAが一仕事終わったら、自動的に次の仕事待ち.

End of Conversion Sel.:2ch scanが終わったら割り込み.

Number of Conversion:2chだから2にする.

External Trigger Conversion Source:ADCがTIM3でTRIGされる.

Channel:ch1とch9を設定する.

Sampling Time:この用途にはdon't careかもしれない.よく判ってない.

ADCのDMA設定.Mode:Circularにするのは必須.Wordは上述したbit幅が理由.

ーーーー
STM32CubeMXのCDC雛形source codeへ追加するもの.

main()の上とかにADC変換完了callbackを記す.
uint32_t buffer[4];
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
  HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
  static N = 0;
  static uint8_t usbbuf[3*500*2+100];  3byte x 500pts x 2ch
  if(N==0) usbbuf[0]=0;
  char c[15];
  sprintf(c,"%03X",buffer[0]); IN1
  strcat(usbbuf,c); 
  sprintf(c,"%03X",buffer[1]); IN9
  strcat(usbbuf,c);
  if(N++>=499){
    int l = strlen(usbbuf);
    usbbuf[l] = '\n';
    CDC_Transmit_FS(&usbbuf[0],l+1);
    N=0;
  }
}

追記:strcat()は文字数が増えると遅くなるので使わない方がいいです.usbbuf[i]=c[k]みたく自分で積んだ方がはるかに速いです.

main()のInitの下に追加.TIM3とADCとDMAを起動する.以降はhardwareが自走する.やっぱhardware orientedは気持ちいい.
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim3);
  HAL_ADC_Start_DMA(&hadc1, &buffer[0], 2);
  /* USER CODE END 2 */

ーーーー
以上により、USB COMにこのような文字列が3000文字+CRだけ毎秒送信されます.
"50F7FB5077F15197FF.......62B2281EB0D81DADC8\n"

USB COMを受信したPCではこれを3文字づつに切り分け、さらに偶数番目と奇数番目で分けてHEX→DEC変換するとこのような2chグラフを描けます.
50F,507,519 → 1295,1287,1305
7FB,7F1,7FF → 2043,2033,2047

次回予告:サンプル周波数をどこまで上げられるか?

3へ   5へ

かしこ

2024年4月9日火曜日

BlackpillというSTM32 board(3)(ADC)

中華STM32基板のBlackpillを味見しています.

今回はADCを動かします.

ADCを動かすと言ってもいろんな動かし方の作法があるわけでして、、、ここでやったのは次の仕組みです.
・サンプリング周波数は500Hz
・連続する500ptsをメモリにストア (1秒分)
・同500ptsをCDC(USB COM)でPCへ送信する
・サンプリング周期はTIM3の出力する2mSecで決める (つまりhardware自走)
・ADC入力はIN9の1本だけ (多入力scanも出来るが使わない)
・ADCは1トリガ1サンプル (自動16サンプルまで出来るが使わない)
・DMAは使わない
・ADC完了をIRQで知る
・同IRQで500pts分のbufferに積む
・同IRQでbuffer fullになったらUSB送信を起動 (USB送信はブロックモード)
・ADCは12bitなので、1サンプルあたりASCIIの3bytesをbufferに積む
・ゆえに1USB送信あたり1500bytes
・USB FULL SPEED(12Mbps)で1500bytes送信するのにover head込みで10mSecぐらいかかるのでその間はADC変換動作は滞るが気にしない

ADC dataをPCでグラフに描いたもの.もっとノイジーかと思ってたけれどそんなに悪くない.

ーーーー
ArduinoIDEと違ってSTM32CubeIDEのsourceは大量なので全部を網羅した説明はできません.かいつまんで説明します.

↓まずはclock設定から.STM32F401CCの最高clockにする.

↓TIM3に2mSec毎にTRIG出力させる設定.赤いところはキモ.
84MHz÷8400÷20=500Hz=2mSec

↓ADCをTIM3 TRIGで起動し、12bitで1発変換、そんな感じにする設定.

↓USB deviceに設定.IOはPA11とPA12で固定です.
↓USBのCDC/VCP/USB COMの雛形sourceを生成させる.赤字のところだけでいい.他は変えてません.

↓最後に割り込み設定.ADC,TIM,USBの割り込み有りに設定する.
IRQハンドラを生成させる.

設定は以上でだいたいおしまい.

以下はsource.

main()の追加点.
Init()の下に2行追加.TIM3を起動する.ADCを起動する.
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  MX_TIM11_Init();
  MX_USB_DEVICE_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim3);
  HAL_ADC_Start_IT(&hadc1);
  /* USER CODE END 2 */

ADC割り込みハンドラにいろいろ追加.
やってることは、
 ①AD dataをもってくる
 ②ASCII変換する
 ③bufferに積む
 ④500 dataを積んだらUSB送信
void ADC_IRQHandler(void){
  /* USER CODE BEGIN ADC_IRQn 0 */
  uint32_t adc = HAL_ADC_GetValue(&hadc1); ①
  static N = 0;
  static uint8_t usbbuf[3*500+100]; // 3byte x 500pts
  if(N==0) usbbuf[0]=0;
  char c[15];
  sprintf(c,"%03X",adc); ②
  strcat(usbbuf,c); ③
  if(N++>=499){
    int l = strlen(usbbuf);
    usbbuf[l] = '\n';
    CDC_Transmit_FS(&usbbuf[0],l+1); ④
    N=0;
  }
  /* USER CODE END ADC_IRQn 0 */
  HAL_ADC_IRQHandler(&hadc1);
}

source変更は以上です.

ADC関係がやけに簡単に見えますが、ADC起動~ADCサンプル完了まではhardwareで自走してくれるのでprogramでやることはありません.

2へ   4へ

かしこ

2024年4月8日月曜日

BlackpillというSTM32 board(2)(USB2.0で1Mbps)

中華STM32基板のBlackpillを味見しています.初体験はこちら

USB転送レートがどのくらい出るかを知りたい.

背景情報をいろいろ記しますと、、、

BlackpillのCPUはSTM32F401CCです.
このCPUにはUSB2.0が載っているのですが、HIGH SPEED(480Mbps)は出ません.FULL SPEED(12Mbps)です.12Mはいまいち遅いのだけど、USBのいろいろなoverheadのせいで12Mは望むべくも無く、実力はもっと遅いはずです.それを確かめたい.

BlackpillをUSB deviceで動かします.

ArduinoIDEで開発したかったけれど、USB libraryが見つからなかったので断念しました.STM32CubeIDEで開発しました.

STM32CubeIDEは、雛形sourceとして、USB COM classを吐き出してくれます.(virtual COM port/Communications Device Classなど呼び名はいろいろ)

Blackpillのclockは最速(84MHz)に設定します.

USB接続する相手はPCです.corei7の4000番台なので古いマシンです.

PCのアプリはTeratermです.Teratermで受信したdata量とtimeで転送レートを求めます.

USB COMではなくバルク転送でレート測定したらもっと高速なのかもしれませんが、今回はバルク転送はやってませーん.

ーーーー
STM32CubeIDEが吐き出すUSB COM classの雛形をどのように動かすのか?

STM32からの送信はこの関数に尽きます.これを呼び出せば送信します.
 CDC_Transmit_FS( buf, num );
DMAはありません.
callしてもbusyだったら無視されるみたいです.つまりブロックされます.

CDC_Transmit_FS()の送信サイズは1024bytesにしました.packet分割は自動でやってくれます.USB FULL SPEEDでは64bytes/packetです.

1mSec タイマー割り込みでCDC_Transmit_FS()をcallします.1ms毎にcallしたって過剰ですからbusyで無視されます.ゆえに、むりくり最高速度を叩き出している様になります.

ーーーー
以上の仕掛けで得られた転送レートは、、、1Mbpsでした.これは反吐が出るほど遅い(笑)

12Mが1Mに落ちるなよ.
STM32帰責でない事は確認できてます.まさかPCってことも無いだろうし.ゆえに律速はUSBでしょう.

ちなみに別件で試したHIGH SPEEDでは理論480Mbpsに対し実効120Mbpsぐらい出せたことがあります.
つまりFULL SPEEDはover headが大きいわけですが、packet sizeが原因じゃないかな?
 FULL SPEED 64bytes/packet
 HIGH SPEED 1024bytes/packet
となっています.

なんかいまいち.

1へ    3へ

かしこ

2024年4月6日土曜日

BlackpillというSTM32 board(1)(初体験は地雷でした)

中華通販でこういう基板が多く出回っています.¥400ぐらいですかね.WEACTという中華の人がやっています.openなのかどうかは知りませんが技術情報は公開されています.
CPU:STM32F401CCU6  回路図
STMではよく目にするCPUですね.でも使ったことはないんで初体験なんです.

基板にUSB-C端子がありますが、物理的にUSB-Cコネクタなだけであって、protocol的にはUSB2.0の12Mbpsの接続しか出来ないはずです.480Mbpsは出ません.それでもUARTよりは速いだろうから試してみます.6Mbpsぐらい出たらいいな.

開発環境は、STM32CubeIDEでもよいですが、ArduinoIDEで焼けるらしいので試してみます.ArduinoIDEの方がライブラリが簡単ポンなので楽ちんです.

ーーーー
買った基板をいきなりPCにUSB接続しますと、何が起きたか?
USB入力デバイスが1つ増えました.VIDはSTMでした.LEDが点滅しています.ヒューマンなんちゃらクラスのtest programが工場で焼かれているようです.とっとと上書きしちゃおう.

次に、reprogramming時に使うと思われるBOOT SWを押しながらRESETしてみますと、デバマネにSTM Device in DFU modeというもの出てきます.これにIDEがアクセスするのでしょう.DFUの仕様は知りませんが、こちらに少し書かれています.

ちょっちカーナピーナにカレーを食べに行くので中座します.

ーーーー
帰宅しましたー

ArduinoIDEのboard magerにSTM32を追加します.このページの前半が参考.
キモの部分はこれです.いつものジェイソンです.
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json

↓ArduinoIDEのboard managerで「STM32」で検索して出てくるこれをインスト.

↓board managerでGeneric STM32F4 seriesを選べるようになりました.

↓Toolsの下のmenuがやたらと増えてる.BlackPill F401CCというそのものがあるので選択しといた方がよさそう.

↓まだあるぜ、これもイカにもやっとけ的なものがよ.STM32CubeProgrammer(DFU)にしておく.

BOOT SWを押しながらRESETするのを忘れずに、焼いてみます.
きゃーーっ、エラーよ.program toolがないと言ってます.

やはりこれをインストしなくちゃいけないみたいです.
STM32CubeProgrammerが必要のようです.(IDEインストしてるからそれで足りると期待したんだがね)
素直にインストして、焼けるようになりました.Lチカ動いてる.

ーーーー
ぎゃーーっトラブル!
一度焼いたら、USBの認識がSTM32CubeProgrammer(DFU)じゃなくてSTM32 BOOT LOADERに変わってしまいました.
混迷の度は深まる・・・・

これねぇ、いくつかの地雷回避が必要みたいです.
1)焼き操作に先んじて基板をUSB接続し、BOOT SWを押しながらRESETする
2)デバマネに「STM32 BOOT LOADER」が表示されているのを確認
3)STM32 BOOT LOADERになっちゃったこと自体は無視してかまわない
4)STM32CubeProgrammer(DFU)を選択する(上述)
5)dfu ports 1-5を選択する

ここで地雷なのは、dfu portの選択肢を出すために1234の順に操作しないとダメ、ということです.
もちろん、一度決めればArduinoIDEが記憶してくれますけど、別のboardを使ってBlackPillに戻した時には12345の地雷回避を実施しないとダメです.

ちなみに執筆時のArduinoIDE version2.3.2です.

初体験は地雷でした...地雷はいや

↓焼き操作のmessageはこんなです.

Sketch uses 11356 bytes (4%) of program storage space. Maximum is 262144 bytes.
Global variables use 1156 bytes (1%) of dynamic memory, leaving 64380 bytes for local variables. Maximum is 65536 bytes.
-------------------------------------------------------------------
     STM32CubeProgrammer v2.15.0
-------------------------------------------------------------------
USB speed   : Full Speed (12MBit/s)
Manuf. ID   : STMicroelectronics
Product ID  : STM32  BOOTLOADER
SN          : 388436893135
DFU protocol: 1.1
Board       : --
Device ID   : 0x0423
Device name : STM32F401xB/C
Flash size  : 256 KBytes (default)
Device type : MCU
Revision ID : --  
Device CPU  : Cortex-M4

Memory Programming ...
Opening and parsing file: Blink.ino.bin
  File          : Blink.ino.bin
  Size          : 11.52 KB 
  Address       : 0x08000000 

Erasing memory corresponding to segment 0:
Erasing internal memory sector 0
erasing sector 0000 @: 0x08000000 done
Download in Progress:

File download complete
Time elapsed during download operation: 00:00:00.870

RUNNING Program ... 
  Address:      : 0x8000000
Start operation achieved successfully


かしこ