0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

APM32F411板的python+pyocd命令行操作

Geehy極海半導(dǎo)體 ? 來(lái)源:Geehy極海半導(dǎo)體 ? 2024-10-18 16:21 ? 次閱讀

1 背景

前段時(shí)間學(xué)習(xí)了一下如何使用pyocd配合APM32F411VCTINY板在命令行下給它進(jìn)行各種騷操作,在使用一段時(shí)間后就想著:pyocd是基于python的,那是不是也可以使用python腳本+pyocd使用起來(lái)呢?

完成我們的一些重復(fù)的操作的自動(dòng)化(因?yàn)槲冶容^懶),嘿嘿。想到就去做。

2 pyocd 的python api

之前有介紹pyocd的時(shí)候發(fā)現(xiàn)遺漏了pyocd的api沒(méi)有看,它還給了利用python+pyocd的一些例子(https://pyocd.io/docs/api_examples.html)。

比如下載bin文件的例子。

wKgaomcSGo6ACHfMAABgDG6E4iw831.jpg

本文檔就對(duì)近段時(shí)間我學(xué)習(xí)到的pyocd+python,基于APM32F411TINY板的一些收獲。由于我也是初學(xué)python,里面的一些不科學(xué)的操作,也請(qǐng)大家指出斧正。此致感謝!

2.1 連接

首先是連接的API:

session_with_chosen_probe()

這個(gè)api主要是控制我們選擇哪個(gè)link去連接目標(biāo)芯片,可以使用link的UID去指定,比如說(shuō)我這里的link UID是:00350054500000144e5448590258(注:可以在CMD命令行用:pyocd list命令查看)。

wKgZoWcSGpmAR7bwAAAovmKq-LA656.jpg

那我這里設(shè)置指定使用我的 Geehy CMSIS-DAP WinUSB的設(shè)置就是:

ConnectHelper.session_with_chosen_probe(unique_id='00350054500000144e5448590258')

2.2 程序控制

讓程序停下

target.halt()

讓程序繼續(xù)運(yùn)行

target.resume()

2.3 數(shù)據(jù)讀取

數(shù)據(jù)的讀取指令可以使用:

target.read32(address)

這個(gè)可以讀取我們MCU的flash、ram、外設(shè)寄存器等內(nèi)容。

我們也可以使用指令:

target.read_core_register("pc")

讀取我們程序的運(yùn)行到的地方。

2.4 數(shù)據(jù)寫(xiě)入

數(shù)據(jù)的寫(xiě)入,我們可以使用:

target.write32(address,data)

這個(gè)可以對(duì)我們MCU的fram、外設(shè)寄存器等可以直接寫(xiě)入內(nèi)容的地址進(jìn)行操作。

Q:為什么不能直接對(duì)Flash進(jìn)行直接寫(xiě)入?

A:因?yàn)閒lash的寫(xiě)入其實(shí)是flash控制器(解鎖、控制、狀態(tài)等寄存器),去進(jìn)行的。我們通過(guò)swd的指令只能通過(guò)操作flash的控制器,從而才能對(duì)Flash進(jìn)行寫(xiě)入。

3 程序設(shè)計(jì)

我這里設(shè)計(jì)了兩個(gè)程序,對(duì)學(xué)習(xí)到的知識(shí)進(jìn)行驗(yàn)證。

3.1 讀取PE5/6的狀態(tài)

這個(gè)程序我設(shè)想的是,我的APM32F411VCTINY板已經(jīng)下載了一個(gè)LED閃爍的程序,我要知道LED當(dāng)前的一個(gè)狀態(tài)。這個(gè)其實(shí)可以類(lèi)比于一個(gè)黑盒子(芯片端),我們?cè)诓婚_(kāi)盒子的情況下去獲取我們想知道的寄存器信息

程序的基本設(shè)計(jì)流程:

1. 連接APM32F411VC,

2. 讀取GPIOE的ODATA寄存器,用于判斷PE5/PE6的高低電平。

3. 輸出寄存器內(nèi)容,PE5/PE6的狀態(tài),以及相應(yīng)的PC的內(nèi)容。

程序如下:

import time

from pyocd.core.helpers import ConnectHelper

# Replace the following string with your target device serial number

TARGET_DEVICE_SERIAL_NUMBER = '00350054500000144e5448590258'

# APM32F411 GPIOE base address and ODATA offset

GPIOE_BASE = 0x40021000

GPIOE_ODATA_OFFSET = 0x14

# Connect to the target device with the specified serial number

with ConnectHelper.session_with_chosen_probe(unique_id=TARGET_DEVICE_SERIAL_NUMBER) as session:

# Get the target object

board = session.board

target = board.target

# ensure the target device in the running state

target.resume()

# Compute the address of the ODATA register

gpioe_odata_address = GPIOE_BASE + GPIOE_ODATA_OFFSET

# Monitor PE5 and PE6 pin status

# Monitor 10 times

for i in range(10):

target.halt()

odata = target.read32(gpioe_odata_address)

pc = target.read_core_register("pc")

target.resume()

pe5 = (odata >> 5) & 0x1

pe6 = (odata >> 6) & 0x1

# Print the contents of the odata read

print("odata: %s " % bin(odata))

print(f'PE5: {"High" if pe5 else "Low"}, PE6: {"High" if pe6 else "Low"}')

# Read some registers.

print("pc: 0x%X" % pc)

print("")

# Wait 0.5 seconds

time.sleep(0.5)

程序運(yùn)行(vscode)起來(lái)得到的結(jié)果如下:

wKgZoWcSGquAfSQbAAByYNcCn20810.jpg

發(fā)現(xiàn)可以讀取回來(lái)PE5/PE6的狀態(tài),且可以明確知道此時(shí)PC的內(nèi)容。

3.2 解除/上鎖APM32F411的讀保護(hù)

由于我們的程序燒錄進(jìn)APM32F411后一般會(huì)對(duì)它進(jìn)行讀保護(hù)的操作,從而使得我們的程序不會(huì)被“有心人”讀取**。

通過(guò)查閱APM32F411的手冊(cè),我們知道對(duì)其進(jìn)行上讀保護(hù)的操作的流程有:

1. 解鎖選項(xiàng)字節(jié)編程區(qū)域;

2. 對(duì)讀保護(hù)進(jìn)行操作;

3. 重載選項(xiàng)字節(jié)。(PS:重載選項(xiàng)字節(jié)會(huì)引起復(fù)位,此時(shí)我們需要重新連接SWD,才能重新讀取內(nèi)容)

下面就根據(jù)這個(gè)流程對(duì)python腳本進(jìn)行設(shè)計(jì)。

import time

from pyocd.core.helpers import ConnectHelper

# Replace the following string with your target device serial number

TARGET_DEVICE_SERIAL_NUMBER = '00350054500000144e5448590258'

# APM32F411 Option Bytes related register addresses and key values

FMC_OPTKEY = 0x40023C08

FMC_OPTCTRL = 0x40023C14

OPTCTRL_BYTE1_ADDRESS = FMC_OPTCTRL + 1 # Points to the second byte of OPTCTRL

FMC_OPT_KEY1 = 0x08192A3B

FMC_OPT_KEY2 = 0x4C5D6E7F

OB_RDP_LEVEL_1 = 0x55 # Level 1 read protection

OB_RDP_LEVEL_0 = 0xAA # No read protection

# Connect to the target MCU

with ConnectHelper.session_with_chosen_probe(unique_id=TARGET_DEVICE_SERIAL_NUMBER) as session:

target = session.board.target

# Read the current value of OPTCTRL

optctrl_value = target.read32(FMC_OPTCTRL)

rdp_level = target.read8(OPTCTRL_BYTE1_ADDRESS) # Read the second byte directly

if rdp_level != OB_RDP_LEVEL_0:

print("Target MCU is already read protected")

else:

print("Target MCU is not read protected, proceeding with read protect operation...")

# Unlock Option Bytes programming

if optctrl_value & (1 << 0):? # Check the OPTLOCK bit

target.write32(FMC_OPTKEY, FMC_OPT_KEY1)

target.write32(FMC_OPTKEY, FMC_OPT_KEY2)

optctrl_value = target.read32(FMC_OPTCTRL)

print("optctrl_value: 0x%X" % optctrl_value)

# Set the read protection level (only modify the second byte)

target.write8(OPTCTRL_BYTE1_ADDRESS, OB_RDP_LEVEL_1)

# Start the Option Bytes programming

optctrl_value = target.read32(FMC_OPTCTRL)

optctrl_value |= (1 << 1)? # Set the OPTSTRT bit

print("optctrl_value: 0x%X" % optctrl_value)

target.write32(FMC_OPTCTRL, optctrl_value)

# Wait for programming to complete and trigger a reset

while True:

optctrl_value = target.read32(FMC_OPTCTRL)

if not (optctrl_value & (1 << 1)):? # Wait for the OPTSTRT bit to be cleared

break

# Perform a hardware reset of the target MCU

session.probe.reset()

# Wait 0.5 seconds

time.sleep(0.5)

# Re-establish the connection after the reset

with ConnectHelper.session_with_chosen_probe(unique_id=TARGET_DEVICE_SERIAL_NUMBER) as new_session:

new_target = new_session.board.target

# Verify if read protection has been successfully set

new_optctrl_value = new_target.read32(FMC_OPTCTRL)

new_rdp_level = (new_optctrl_value >> 8) & 0xFF

if new_rdp_level == OB_RDP_LEVEL_1:

print("Read protect operation successful")

else:

print("Read protect operation failed")

腳本運(yùn)行結(jié)果如下:

wKgZoWcSGryAG-j5AACFnI2d_IQ977.jpg

當(dāng)然我也給大家準(zhǔn)備了解鎖的操作的腳本,腳本運(yùn)行結(jié)果如下:

wKgaoWcSGseAQAfYAAB1Sp8JObI517.jpg

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4756

    瀏覽量

    84283
  • 命令行
    +關(guān)注

    關(guān)注

    0

    文章

    77

    瀏覽量

    10369
  • 腳本
    +關(guān)注

    關(guān)注

    1

    文章

    383

    瀏覽量

    14791

原文標(biāo)題:APM32芯得 EP.34 | 還可以這樣玩?APM32F411與pyocd的火花

文章出處:【微信號(hào):geehysemi,微信公眾號(hào):Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    玩轉(zhuǎn)SQLite2:SQLite命令行基本操作

    本篇介紹SQLite的命令行基本操作
    的頭像 發(fā)表于 09-23 08:59 ?2103次閱讀
    玩轉(zhuǎn)SQLite2:SQLite<b class='flag-5'>命令行</b>基本<b class='flag-5'>操作</b>

    TinyMaix框架的內(nèi)存需求超過(guò)了APM32F411的可用內(nèi)存,導(dǎo)致運(yùn)行失敗,怎么能成功優(yōu)化?

    TinyMaix框架的內(nèi)存需求超過(guò)了APM32F411的可用內(nèi)存,導(dǎo)致運(yùn)行失敗。怎么能成功優(yōu)化?
    發(fā)表于 09-27 09:44

    cmd網(wǎng)絡(luò)經(jīng)典命令行

    cmd網(wǎng)絡(luò)經(jīng)典命令行:
    發(fā)表于 06-11 15:17 ?36次下載
    cmd網(wǎng)絡(luò)經(jīng)典<b class='flag-5'>命令行</b>

    caxa命令行中的應(yīng)用

    caxa命令行中的應(yīng)用 命令行對(duì)于大多用戶(hù)來(lái)說(shuō)往往只是輸入數(shù)據(jù)的作用,但是其中的奧妙還有很多,下面就給大家
    發(fā)表于 10-18 18:18 ?2266次閱讀

    博達(dá)環(huán)網(wǎng)配置命令行

    博達(dá)工業(yè)交換要環(huán)網(wǎng)配置命令行
    發(fā)表于 12-27 16:24 ?0次下載

    CMD的命令行高級(jí)教程

    CMD的命令行高級(jí)教程
    發(fā)表于 10-24 08:31 ?30次下載
    CMD的<b class='flag-5'>命令行</b>高級(jí)教程

    Linux命令行與shell腳本編寫(xiě)

    Linux命令行與shell腳本編寫(xiě)
    發(fā)表于 01-11 16:50 ?4次下載

    如何在Linux命令行中運(yùn)行Python腳本

    Python 是一種高級(jí)編程語(yǔ)言,被廣泛應(yīng)用于數(shù)據(jù)科學(xué)、機(jī)器學(xué)習(xí)、Web 開(kāi)發(fā)等領(lǐng)域。在 Linux 操作系統(tǒng)中,Python 是一個(gè)默認(rèn)安裝的解釋器,用戶(hù)可以通過(guò)命令行界面(CLI)
    的頭像 發(fā)表于 05-12 14:49 ?1615次閱讀

    linux命令行與shell編程實(shí)戰(zhàn)

    Linux命令行與Shell編程實(shí)戰(zhàn)主要涉及以下內(nèi)容: Linux命令行基礎(chǔ):學(xué)習(xí)Linux命令行的基本操作,如文件管理、進(jìn)程管理、網(wǎng)絡(luò)配置等。熟悉使用
    的頭像 發(fā)表于 11-08 10:57 ?676次閱讀

    linux虛擬機(jī)怎么調(diào)出命令行

    快捷鍵組合Ctrl+Alt+F1 6來(lái)切換到命令行界面。如果系統(tǒng)在虛擬機(jī)中,則可以使用Ctrl+Alt+shift+F1 6組合鍵來(lái)切換到命令行界面。在
    的頭像 發(fā)表于 11-08 11:28 ?2781次閱讀

    linux切換到命令行模式

    在Linux中,可以通過(guò)以下步驟切換到命令行模式: 打開(kāi)終端。可以在應(yīng)用菜單中找到終端或命令行終端。 在終端中輸入命令“exit”或“l(fā)ogout”,然后按回車(chē)鍵。 系統(tǒng)會(huì)提示您輸入管理員密碼。輸入
    的頭像 發(fā)表于 11-13 16:47 ?1600次閱讀

    linux虛擬機(jī)命令行界面如何操作

    Linux虛擬機(jī)的命令行界面可以分為四個(gè)方面進(jìn)行詳盡的說(shuō)明:登錄、基本操作、文件管理和系統(tǒng)管理。 第一部分:登錄 首先,您需要啟動(dòng)虛擬機(jī)并打開(kāi)終端。在啟動(dòng)過(guò)程中,您可以按下一些鍵(如F12、Del或ESC,具體取決于虛擬化軟件)
    的頭像 發(fā)表于 11-17 09:57 ?1553次閱讀

    pycharm命令行終端運(yùn)行代碼

    Python是一種非常流行的編程語(yǔ)言,許多開(kāi)發(fā)者使用它來(lái)編寫(xiě)各種應(yīng)用程序和腳本。為了方便開(kāi)發(fā)者編寫(xiě)和測(cè)試代碼,PyCharm是一種集成開(kāi)發(fā)環(huán)境(IDE),它提供了許多功能和工具,其中包括命令行終端
    的頭像 發(fā)表于 11-22 11:20 ?3861次閱讀

    eclipse怎么使用命令行

    命令行中使用Eclipse來(lái)完成一些特定的任務(wù)。本文將詳細(xì)介紹如何在命令行中使用Eclipse。 首先,我們需要確保已經(jīng)正確安裝了JDK(Java Development Kit)和Eclipse
    的頭像 發(fā)表于 12-06 11:26 ?2195次閱讀

    idea如何輸入命令行參數(shù)

    在許多軟件開(kāi)發(fā)和系統(tǒng)管理的任務(wù)中,我們經(jīng)常需要向應(yīng)用程序傳遞命令行參數(shù)。命令行參數(shù)是在運(yùn)行時(shí)傳遞給程序的值,用于指定程序的行為和配置選項(xiàng)。本文將詳細(xì)介紹如何在不同的編程語(yǔ)言和操作系統(tǒng)中輸入命令
    的頭像 發(fā)表于 12-06 15:01 ?932次閱讀