chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

gdbの操作をpythonで自動化

背景:これまではgdbのxコマンドを使ってSTM32C0のレジスタを手動で参照、設定していた
課題:毎回手動だとアドレスを忘れるし、何が正しかったか分からなくなる
対策:gdbではpythonスクリプトが動かせるので、手作業だったレジスタ操作を自動化できる
結果:自動化した。さらに、for文でUARTの送受信レジスタを読み書きすることで、UARTの送受信プログラムもPythonで書けてしまう
詳細:

以下がUSARTを初期化して、テスト用にASCIIコードをUARTから送信しつづけるプログラム。ハンドアセンブルと叫んでいたのに、これではPythonマイコン動かしているのではないか?これはチートでは?とも自問自答するが、最終的には全部機械語に置き換えるので、導入段階はPythonに助けてもらう。

#
# python script for GDB
#
import sys
import time
sys.path.append('.')

import  gdb
from reg_defs import *
from mylib import *

inferior = gdb.inferiors()[0]


def setup_uart_regs(inferior):

    # disable USART
    addr = USART_BASE + USART_CR1
    val = bytes(reversed((0,0,0,0)))
    inferior.write_memory(addr, val)

    # clear and set default protocol
    addr = USART_BASE + USART_CR1
    val = bytes(reversed((0,0,0,0)))
    inferior.write_memory(addr,  val)

    # clear and set default stop bit
    addr = USART_BASE + USART_CR2
    val = bytes(reversed((0,0,0,0)))
    inferior.write_memory(addr,  val)

    # set baudrate
    addr = USART_BASE + USART_BRR
    val = bytes(reversed((0,0,0,0xd0)))
    inferior.write_memory(addr,  val)

    # enable FIFO
    addr = USART_BASE + USART_CR1
    val = bytes(reversed((0x20,0,0,0)))
    inferior.write_memory(addr,  val)

    # enable USART
    addr = USART_BASE + USART_CR1
    val = bytes(reversed((0x20,0,0,0x0d)))
    inferior.write_memory(addr,  val)

def send_char(inferior, char):
    # write
    addr = USART_BASE + USART_TDR
    val = bytes(reversed((0,0,0,char)))
    inferior.write_memory(addr,  val)


dump_uart_regs(inferior)
setup_uart_regs(inferior)
dump_uart_regs(inferior)

while True:
   for ch in range(0x20, 0x7f):
       send_char(inferior, ch)
       time.sleep(0.5)

USBシリアル経由で送信されたASCIIコードを受信

イケてないけど開発環境

■追記
以下のように、UARTでASCIIコードを受信するコードもPythonで書けてしまう

import sys
import time
sys.path.append('.')

from reg_defs import *
from mylib import *

inferior = gdb.inferiors()[0]

def receive_char(inferior):
    addr = USART_BASE + USART_RDR
    size = 4
    val = inferior.read_memory(addr, size)
    return val.tobytes()[0]

while True:
   reg = read_uart_ISR(inferior)
   if reg[3] & 0b0010_0000:    # check RXFNE bit is set
       char = receive_char(inferior)
       if char >= 0x20 and char < 0x7f:
           print(f'{chr(char)}({char:02x})', end=' ')
       else:
           print(f'{char:02x}', end=' ')
       if char == 0x0d:
           print()