スキップしてメイン コンテンツに移動

Bluepill用のCMSIS-DAPでCPUIDをプローブのシリアル番号として利用

以前に紹介したBluePill用のファームウェアでは、シリアル番号は固定になっているため、複数のターゲットで作業している場合、一々接続をきりかえなければなりませんし、同時に接続しながら作業することもできません。そこで、CPUID(STM32F1x 24byte)をプローブのシリアル番号として個別に割当てることができないかとやってみたところ、とりあえず動いているようなので、本稿を上げてみました。
なお、参考にしたのはこちらの投稿です。記載されている要領でほぼ動いていますので、大いに感謝しています。Thanks!!
早速以下に作業要点を記述します。作業環境はWindows10/WSL2 Debian10/Busterです。
まず、もとになるBluePill向けのCMSIS-DAPプルーブ化のプロジェクトをgit cloneします。
cd /mnt/c/Users/YourID/Documents
git clone https://github.com/RadioOperator/STM32F103C8T6_CMSIS-DAP_SWO
これにくわえて、CMSIS-5.3.0をKeil_5に追加しておきます。二段目のツールバーの右端に、pack installerがあるのでクリックします。
pack instllerが呼び出され、しばらくしてからcmsis 5.3.0 installをクリックしインストールします。
cmsis-5.3.0のインストールは以上です。 つづいてプロジェクトをひらき、(プロジェクトを右クリックして)Options for target 'STM32F103-BLUEPILL'を開き"C/C++"タブをクリックします。中ほどに"Include Paths"があるので"..."をクリックして、先ほどインストールしたCMSIS-5.3.0をインクルードするようにします。
C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.3.0\CMSIS\Include
C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.3.0\CMSIS\Driver\Include
次に、ファイルをリネームしつつコピーしします。
cd /mnt/c/Users/YourID/Documents/STM32F103C8T6_CMSIS-DAP_SWO/USB
cp /mnt/c/Keil_v5/ARM/RV31/INC/usb_lib.c usb_lib_unique_serial.c
コピーが済んだら、"Add Files to Group 'USB'"で、usb_lib_unique_serial.cをプロジェクトに追加してください。続いてUSB/usb_config.cを2箇所編集します。一つ目の変更箇所はファイルの一番最後のほうです。
変更前
#ifndef  __USB_CONFIG___
#define  __USB_CONFIG__

	#ifndef  __NO_USB_LIB_C
		#include <usb_lib.c>
	#endif

#endif  /* __USB_CONFIG__ */
変更後
#ifndef  __USB_CONFIG___
#define  __USB_CONFIG__

	#ifndef  __NO_USB_LIB_C
		#include "usb_lib_unique_serial.c"
	#endif

#endif  /* __USB_CONFIG__ */
USB/usb_config.cのもう一か所の変更は以下の通りです。(122行目あたり)
変更前
#define USBD_STRDESC_SER            L"0001A0000000"
変更後
#define USBD_STRDESC_SER            L"0001A10000000002B2000000"
続いてリネーム・コピーした、USB/usb_lib_unique_serial.cを編集します。編集はファイルの一番最後のほう(2100行目あたり)で、structの宣言からconstを削除します。
変更前
#define USBD_STR_VAL(n)                  \
 { sizeof(USBD_##n), USB_STRING_DESCRIPTOR_TYPE, USBD_##n }

__weak \
const struct {
  struct {
    U8  len;
    U8  type;
    U16 langid;
  } desc_langid;
  USBD_STR_DEF(STRDESC_MAN);
変更後
#define USBD_STR_VAL(n)                  \
 { sizeof(USBD_##n), USB_STRING_DESCRIPTOR_TYPE, USBD_##n }

__weak \
struct {
  struct {
    U8  len;
    U8  type;
    U16 langid;
  } desc_langid;
  USBD_STR_DEF(STRDESC_MAN);
次に、usb_config.cはmain.cからよびだしているので、プロジェクトからUSB/usb_config.cを除外します。プロジェクトツリーのUSB/usb_config.cを右クリックして"Remove File usb_config.c"をクリックすると除外できます。
続いて User/main.cの編集です。こちらはdiff形式ですが、以下の様にしてみました。(追記:2021/02/21: dap_ser_wrdを wchar_t[]からuint16_t[]へ変更しました。)
$ diff -urN main.c.orig main.c
--- main.c.orig 2021-02-18 06:00:42.823726700 +0900
+++ main.c      2021-02-21 06:54:07.724053700 +0900
@@ -6,12 +6,14 @@
 //=====================================

 #include <stdio.h>
+#include <string.h>
+#include <stdlib.h>

 #include <RTL.h>
 #include <rl_usb.h>
 #include <stm32f10x.h>

-#define  __NO_USB_LIB_C
+//#define  __NO_USB_LIB_C
 #include "usb_config.c"

 #include "DAP_config.h"
@@ -37,6 +39,7 @@
 void BoardInit(void);
 uint8_t usbd_hid_process(void);
 void Delayms(uint32_t delay);
+void get_serial_num(void);

 extern void PIN_nRESET_OUT(uint8_t bit);

@@ -51,7 +54,14 @@
 #define LED_FLASH_ON()    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk  //turn-on SysTick, LED in flashing mode.
 #define LED_FLASH_OFF()   SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk //turn-off SysTick

-#if defined ( BLUEPILL ) //Bluepill Board
+#define ID1 (*(unsigned long *)0x1FFFF7E8)
+#define ID2 (*(unsigned long *)0x1FFFF7EC)
+#define ID3 (*(unsigned long *)0x1FFFF7F0)
+
+#define UNIQUE_SER_LEN 24
+uint16_t  dap_ser_wrd[UNIQUE_SER_LEN];
+
+#if defined ( BLUEPILL ) || defined ( BLUEPILL_V2B ) //Bluepill Board

 void LedConnectedOn(void)     { LED_CONNECTED_PORT->BRR  = LED_CONNECTED_MASK;  } //Low active
 void LedConnectedOff(void)    { LED_CONNECTED_PORT->BSRR = LED_CONNECTED_MASK;  }
@@ -184,6 +194,25 @@
   DAP_TransferAbort = 1;
 }

+void get_serial_num(void)
+{
+  char id1_str[8], id2_str[8], id3_str[8];
+  char dap_ser_num[UNIQUE_SER_LEN];
+
+  sprintf (id1_str, "%08lX", ID1);
+  sprintf (id2_str, "%08lX", ID2);
+  sprintf (id3_str, "%08lX", ID3);
+
+  strcat (dap_ser_num, id1_str);
+  strcat (dap_ser_num, id2_str);
+  strcat (dap_ser_num, id3_str);
+
+  for (int i = 0; i < UNIQUE_SER_LEN; i++)
+  {
+    dap_ser_wrd[i] = (uint16_t)dap_ser_num[i];
+  }
+}
+
 UserAppDescriptor_t * pUserAppDescriptor = NULL;
 UserAppDescriptor_t UserAppDescriptor = {
   &UserAppInit,
@@ -210,6 +239,11 @@

   // USB Device Initialization and connect
   usbd_init();
+
+  get_serial_num();
+  USBD_StringDescriptor.descSTRDESC_SER.len = UNIQUE_SER_LEN * 2 + 2;
+  memcpy(USBD_StringDescriptor.descSTRDESC_SER.str, dap_ser_wrd, UNIQUE_SER_LEN * 2);
+
   usbd_connect(__TRUE);

   while (!usbd_configured())  // Wait for USB Device to configure
@@ -470,7 +504,7 @@
   LEDS_SETUP();
 }

-void USBD_Error_Event(void)
+void USBD_Error_Event(U32 error)
 {
   LedConnectedOn();
   LedRunningOn();
追記:BLUEPILL_V2Bターゲットを追加しました。User/main.cに加えCMSIS-DAP/DAP_config.hの変更は以下の通りです。
$ diff -urN DAP_config.h.orig DAP_config.h
--- DAP_config.h.orig   2021-02-23 10:06:20.146890900 +0900
+++ DAP_config.h        2021-02-23 15:43:01.928204500 +0900
@@ -394,7 +394,7 @@
 #endif

 // Debug Unit LEDs
-#if defined ( BLUEPILL )
+#if defined ( BLUEPILL ) || defined ( BLUEPILL_V2B )

 #define LED_CONNECTED_RCC   RCC_APB2ENR_IOPCEN //PC13 - Bluepill
 #define LED_CONNECTED_PORT  GPIOC
@@ -419,7 +419,8 @@

 #elif defined ( STLINK_V20 ) \
   ||  defined ( STLINK_V2A ) \
-  ||  defined ( STLINK_V2B )
+  ||  defined ( STLINK_V2B ) \
+  && !defined ( BLUEPILL_V2B )

 #define LED_CONNECTED_RCC   RCC_APB2ENR_IOPAEN
 #define LED_RUNNING_RCC     RCC_APB2ENR_IOPAEN
ターゲットのdefine は 
USE_STDPERIPH_DRIVER STM32F10X_MD STLINK_V2B BLUEPILL_V2B SWO_PA10
です。ターゲットの追加削除はProject->Manage->Project Items...で行い、ターゲットのdefineなどはProject->Options for Target"ターゲット名"で設定します。
また新しいターゲット用にバイナリー名を変更しておいてください。
編集は以上です。あとはコンパイルして、BluePillに出来上がったファームウェアを書き込んでください。(結線・ピンアウト等の資料はdocフォルダーにあります。)
linuxで正常に動作していると以下のようになります。
$ sudo dmesg
(snip)
[43880.791175] usb 1-2.2: new full-speed USB device number 50 using ehci-pci
[43881.021438] usb 1-2.2: New USB device found, idVendor=0483, idProduct=572a, bcdDevice= 1.00
[43881.021451] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[43881.021457] usb 1-2.2: Product: CMSIS-DAP
[43881.021463] usb 1-2.2: Manufacturer: CMSIS-DAP by ARM
[43881.021469] usb 1-2.2: SerialNumber: 0671FF5051538771XXXXXXXX
[43881.023225] cdc_acm 1-2.2:1.0: ttyACM0: USB ACM device
[43881.032238] hid-generic 0003:0483:572A.0033: hiddev0,hidraw0: USB HID v1.00 Device [CMSIS-DAP by ARM CMSIS-DAP] on usb-0000:00:12.2-2.2/input2

$ /usr/bin/openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_serial 0671FF5051538771XXXXXXXX" -f target/stm32f1x.cfg
Open On-Chip Debugger 0.11.0-rc2
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter driver' not 'interface'
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
DEPRECATED! use 'adapter speed' not 'adapter_khz'
DEPRECATED! use 'adapter srst delay' not 'adapter_nsrst_delay'
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
windows上でもserial番号を指定して接続できるかどうかたしかめてみます。
$ openocd.exe -f interface/cmsis-dap.cfg -c "cmsis_dap_serial 0671FF5051538771XXXXXXXX" -f target/stm32f1x.cfg
Open On-Chip Debugger 0.11.0-rc2+dev-00009-gba0f38213-dirty (2021-02-15-03:46)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Keil5では以下の様になります。

なお、SWD接続は動作するのですが、jtag接続はターゲットの"BLUEPILL-SWD_PB8PB9"と"BLUEPILL-SWD_REMAP"では確認できていません。ターゲット側が何らかの理由で電圧不足あるいは電源不良の場合、接続できないので、ターゲット側の電源を確保することでJTAG接続も確認できました。"STLINK_V2B-SWO_PA10"または"BLUEPILL_V2B-SWO_PA10"ではBluePillの3.3vをそのままでswd接続に加えjtag接続も確認できていましたが、前述と同じで、ターゲット側の電源が確保されていないとjtag接続も安定しません。
なお追加したV2B-SWO_PA10のピンアウトは以下の通りです。
PB13    JTCK/SWCLK
PB14    JTMS/SWDIO
PA10    JTDO/SWO
PB6     RST
PB8     JTDI
PA2     TX
PA3     RX
参考までにKeil5-liteでビルドはできず、Keil5の評価版をつかいました。Keil5-liteで(SWD_REMAPを除き)ビルドできました。詳細はこちらからどうぞ。
追記:hexファイルは下記からダウンロードできるようにしました。(ご使用は自己責任でお願いします。使用にあたり、当方は一切責任を負いません。)
追記:BLUEPILL_V2Bを追加しました。
F103-DAP-SWO-CDC-BLUEPILL-SWD_PB8PB9.hex
F103-DAP-SWO-CDC-BLUEPILL-SWD_REMAP.hex
F103-DAP-SWO-CDC-STLINK_V2B-SWO_PA10.hex
F103-DAP-SWO-CDC-BLUEPILL_V2B-SWO_PA10.hex
なお、wsl/linux上でhexファイルを.binファイルに変換するには以下の方法があります。
objcopy --input-target=ihex --output-target=binary \
F103-DAP-SWO-CDC-BLUEPILL-SWD_REMAP.hex F103-DAP-SWO-CDC-BLUEPILL-SWD_REMAP.bin
一例としてopenocdをつかってbin fileをstm32f1xターゲットに書き込むには以下の様にします。
openocd.exe -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt" \
-c "flash write_image erase F103-DAP-SWO-CDC-BLUEPILL_V2B-SWO_PA10.bin 0x08000000"
今回は以上です。それでは。

コメント

このブログの人気の投稿

Hyper-V Server2019にワークグループ環境下でWindows10(1809)から接続

Hyper-V server 2019に、ワークグループ環境にてWindows10(1809)から接続してみました。Windows10にHyper-V管理ツールがインストールされていることと、Hyper-V Serverをインストール済であることが前提です。以下、Hyper-V serverは名前がHyperVSV、アドレスは192.168.1.110としています。 まず、Hyper-V server上で、powershellを起動し、以下のコマンドを入力します。 Enable-WSManCredSSP -Role Server -Force 続いて、クライアントのWindows10のpowershell で以下のコマンドを入力します。 winrm quickconfig -Force Enable-WSManCredSSP -Role Client -DelegateComputer * -Force さらに、クライアントマシンで、gpedit(グループポリシーエディタ)を起動し、以下の要領でポリシーを設定します。 a. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLMのみのサーバー認証で新しい資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「WSMAN/*」を追加 b. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLM のみのサーバー認証で保存された資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「*」を追加 また、名前解決できるように、(notepadを管理者権限で実行し)C:\Windows\System32\Drivers\etc\hostsにサーバ名とIPアドレスの対を追加。 192.168.1.110 HyperVSV 最後に、Hyper-Vマネージャーを起動し、Windows10からHyper-V サーバに接続します。手順は以下の通りです。 「サーバーに接続」->コンピュータの選択->別のコンピューターに[HyperVSV]と入力し、[別のユーザーとして接続する

wsdd を使ってSamba サーバをネットワークに表示

Windows 10のアップデートで、セキュリティー対応のため、smbv1がデフォルトではインストールされなくなり、Samba serverがエクスプローラーのネットワークに表示されなくなってしまいました。そこで、いくつか方法を調べたのですが、linuxでwsdの実装がないか探したところ、 https://github.com/christgau/wsdd が、見つかりましたので、さっそくインストールしてみました。まだパッケージにはないようですが、インストール自身は簡単です。wsdd自体は以下のように取得し、linkを張っておきます。 cd /usr/local/bin/ sudo wget https://raw.githubusercontent.com/christgau/wsdd/master/src/wsdd.py sudo chmod 755 wsdd.py sudo ln -sf wsdd.py wsdd こちらのsambaサーバはDebianなので、/etc/systemd/system/wsdd.serviceは以下のようにしました。 [Unit] Description=Web Services Dynamic Discovery host daemon Requires=network-online.target After=network.target network-online.target multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/wsdd -d MYDOMAIN [Install] WantedBy=multi-user.target wsdd -d MYDOMAINのところを、環境にあわせて書き換えてください。 次に、systemdに登録・起動テストを行います。 systemctl enable wsdd systemctl start wsdd 起動に成功すると、エクスプローラーのネットワークに表示されます。  なおこのwsddはpython3が必要です。一度試してみてください。SMBv1/CIFSを停止していても、大丈夫です。 cで書かれたほかのwsddの実装もあるようなので、いずれパッケージになるかもしれませ

フレッツ光クロス:MAP-E ROUTER by Debian Box (iptables)

フレッツ光クロスがようやく開通したので、Debianにてrouterを構成し接続してみました。なお、プロバイダーを選ぶにあたっては、IPoE方式がそれぞれ異なるため検討したところ、IPoEでは、MAP-Eでもv6plusとocnバーチャルコネクトがあり、前者がポート数240なのに対し、後者は約4倍のポート数が使えるようなネットの情報をみて、OCNバーチャルコネクトを選択しました。(プロバイダーとしてはぷららです。なおDS-LiteはCE側でのNATではないので今回は見送りました。)そこで、OCN バーチャルコネクトをDebian(iptables)で実現するとどうなるかと思い、ネットの情報を頼りにしつつ、設定した次第です。 実際に試した結果、とりあえず通信できていますが、MAP-Eは本来マッピングルールをマップサーバから取得するはずなので、今回のやり方が正解とはいえませんし、仕様変更されると通信できなくなる可能性があります。あくまでも参考程度ですが、本稿をUPしてみました。 2023/03/16追記: こちら にゲームコンソールNAT越え(Nintendo Switch ナットタイプ A判定)対応版を投稿しました。 2023/03/28追記:※1の記述および3行無効化によりNAT越え(Nintendo Switch ナットタイプ B判定)できるようになりました。 構成は以下の通りです。 ルーターがDebianで回線がOCNバーチャルコネクトであること以外はなにも特別なところはない構成です。 さて、いきなり設定ですが、まず、割り当てられたプレフィックスを確認します。 確認は、 dhclient -6 -d -P enp2s0 とします。出力の中に 前略 RCV: | | X-- IAPREFIX 2400:4050:5c71:af00::/56 後略 このようにプレフィックスが表示されるので、その確認したプレフィックスを書き留めておきます。これを こちらで 入力します。すると、 CE: 2400:4050:5c71:af00:99:f171:c600:2f00 IPv4 アドレス: 153.241.113.198 ポート番号:(1776-1791 2800-2815 3824-3839) 4848-4863 5872-5887 6896-