この記事は、DAPLinkデバッグアダプタとCortex-MターゲットボードをpyOCDから使う手順を説明します。
事前準備
使用するハードウェア
- AE-LPC11U35-MB(DAPLinkデバッグアダプタ)
- AE-LPC11U35-MB(ターゲットボード)
ファームウェアのインストールと接続
こちらの記事を参照してください。
https://qiita.com/toyowata/items/a57ee1dfa884b29c298d
ソフトウェアの準備
以下の手順でpyOCDをインストールします。
# pyocdのインストール
pip install pyocd
# CMSIS-DAPデバイスを認識するための依存パッケージ
pip install pyusb libusb
制御用テストコードの作成と実行
以下のコードでpyOCDを使用してターゲットデバイスの制御します(コードは、ほぼGeminiにお任せしました)。
pyocd_test.py
import time
from pyocd.core.helpers import ConnectHelper
from pyocd.core.target import Target
def dump_all_registers(target):
print("\n=== 全汎用レジスタダンプ ===")
# Cortex-M0の主要なレジスタリスト
# R0-R12, SP(R13), LR(R14), PC(R15), xPSR, MSP, PSP
reg_list = [
'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7',
'r8', 'r9', 'r10', 'r11', 'r12', 'sp', 'lr', 'pc',
'xpsr', 'msp', 'psp'
]
# レジスタ値を一括読み出し
vals = target.read_core_registers_raw(reg_list)
# 2列で見やすく表示
for i in range(0, len(reg_list), 2):
reg1 = reg_list[i]
val1 = vals[i]
line = f"{reg1.upper():>4}: 0x{val1:08X}"
if i + 1 < len(reg_list):
reg2 = reg_list[i+1]
val2 = vals[i+1]
line += f" {reg2.upper():>4}: 0x{val2:08X}"
print(line)
# 1. セッションの開始設定
# ターゲットに "cortex_m" を指定することで、一般的なCortex-Mシリーズとして扱えます。
# 特定のマイコン(例: nrf51, lpc11xx等)が分かっている場合は、その型番を指定するとより正確です。
options = {
'target_override': 'cortex_m',
'frequency': 1000000 # クロック周波数 (1MHz)
}
print("DAPLinkアダプタを探しています...")
session = ConnectHelper.session_with_chosen_probe(options=options)
if session is None:
print("デバッグアダプタが見つかりませんでした。")
exit()
with session:
board = session.board
target = board.target
print("マイコンに接続中...")
target.resume() # 必要に応じて実行状態にする
target.halt() # レジスタやメモリを安全に読み書きするために一時停止
dump_all_registers(target)
print(f"ターゲット状態: {target.get_state().name}")
try:
# --- [A] レジスタのRead/Write ---
print("\n--- レジスタ操作 ---")
# 汎用レジスタ R0 の値を読み出す
r0_val = target.read_core_register('r0')
print(f"元の R0 の値: 0x{r0_val:08X}")
# R0 に新しい値を書き込む
target.write_core_register('r0', 0x12345678)
print("R0 に 0x12345678 を書き込みました。")
# 再度読み出して確認
r0_val_new = target.read_core_register('r0')
print(f"変更後の R0 の値: 0x{r0_val_new:08X}")
# --- [B] メモリのRead/Write (RAM領域) ---
print("\n--- メモリ操作 ---")
# ⚠️注意: アドレスは使用するCortex-M0マイコンのRAM領域に合わせて変更してください
target_address = 0x10000000
# 32bit(ワード)単位での読み書き
original_mem = target.read32(target_address)
print(f"アドレス 0x{target_address:08X} の元の値: 0x{original_mem:08X}")
target.write32(target_address, 0xDEADBEEF)
print(f"アドレス 0x{target_address:08X} に 0xDEADBEEF を書き込みました。")
new_mem = target.read32(target_address)
print(f"アドレス 0x{target_address:08X} の変更後の値: 0x{new_mem:08X}")
# 複数バイトの一括読み書き (ブロック転送)
data_to_write = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
target.write_memory_block8(target_address + 0x10, data_to_write)
print(f"アドレス 0x{target_address + 0x10:08X} に 8バイト書き込みました。")
read_data = target.read_memory_block8(target_address + 0x10, 8)
print(f"読み出しデータ: {[hex(b) for b in read_data]}")
finally:
# 4. 処理が終わったらマイコンの実行を再開して終了
print("\nマイコンの実行を再開します。")
target.resume()
実行結果は以下です。
$ python3 ./pyocd_test.py
DAPLinkアダプタを探しています...
マイコンに接続中...
=== 全汎用レジスタダンプ ===
R0: 0x00000000 R1: 0x00000004
R2: 0xE000ED00 R3: 0x00000000
R4: 0x10001FA8 R5: 0x00000000
R6: 0x00000000 R7: 0x00000000
R8: 0x62304924 R9: 0x2800CC04
R10: 0x0FFF2000 R11: 0x00000000
R12: 0x00000000 SP: 0x10001F88
LR: 0x00001D85 PC: 0x0000095E
XPSR: 0x61000000 MSP: 0x10001F88
PSP: 0x0DC054B8
ターゲット状態: HALTED
--- レジスタ操作 ---
元の R0 の値: 0x00000000
R0 に 0x12345678 を書き込みました。
変更後の R0 の値: 0x12345678
--- メモリ操作 ---
アドレス 0x10000000 の元の値: 0x10002000
アドレス 0x10000000 に 0xDEADBEEF を書き込みました。
アドレス 0x10000000 の変更後の値: 0xDEADBEEF
アドレス 0x10000010 に 8バイト書き込みました。
読み出しデータ: ['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7', '0x8']
マイコンの実行を再開します。
以上です。