美文网首页工作生活
通过jlink实现不需要下位机的“上位机”开发

通过jlink实现不需要下位机的“上位机”开发

作者: tianxiaoMCU | 来源:发表于2019-07-14 09:37 被阅读0次

平时写上位机,串口、USB或者网口,不论哪种方式都需要下位机的配合。也就是得开发两套程序才能实现完整的功能,无论功能繁简。所以经常是嫌麻烦,连简单的都不想弄。直到xx年xx月xx日,挖到了宝:不用写下位机就能达到同样的效果。但是这种方式也是有局限的,就是需要一个调试器,比如jlink、daplink!!!有时候需要一些简易的小工具,我就直接这样搞了,省事点,反正自己用。

原理

前面有提到如何使用pylink访问SEGGER RTT,就是程序主动的去读写MCU中SEGGER RTT控制块的数据,也就是程序(上位机)主动去操作(读写)RTT的数据(内存)。在ARM中,内存和寄存器是统一编址的,因此也可以直接去读写寄存器,能读写寄存器意味着就能直接控制外设了。而JLinkARM.dll正好提供了读写某个地址的接口,因此pylink配合jlink就可以达到预期的效果。如果使用其他调试器可以尝试使用pyOCD,应该可以达到样的效果,我还没有试过。

读写接口

pylink没有现成封装好的写接口,下面是我封装的。使用的时候添加到pylink\pylink\jlink.py文件的class JLink(object)类中,或者可以到我的仓库下载。
读接口使用pylink提供的memory_read8memory_read16memory_read32即可。

    @connection_required
    def peripheral_write8(self, addr, value):
        """Writes byte to peripheral register of target system.
        Args:
          self (JLink): the ``JLink`` instance
          addr (int): start address to write to
          value (int): the value to write to the register
        Returns:
          The value written to the register.
        Raises:
          JLinkException: on write error.
        """
        res = self._dll.JLINKARM_WriteU8(addr, value)
        if res != 0:
            raise errors.JLinkWriteException('Error writing to %d' % addr)
        return value

    @connection_required
    def peripheral_write16(self, addr, value):
        """Writes half-word to peripheral register of target system.
        Args:
          self (JLink): the ``JLink`` instance
          addr (int): start address to write to
          value (int): the value to write to the register
        Returns:
          The value written to the register.
        Raises:
          JLinkException: on write error.
        """
        res = self._dll.JLINKARM_WriteU16(addr, value)
        if res != 0:
            raise errors.JLinkWriteException('Error writing to %d' % addr)
        return value

    @connection_required
    def peripheral_write32(self, addr, value):
        """Writes word to peripheral register of target system.
        Args:
          self (JLink): the ``JLink`` instance
          addr (int): start address to write to
          value (int): the value to write to the register
        Returns:
          The value written to the register.
        Raises:
          JLinkException: on write error.
        """
        res = self._dll.JLINKARM_WriteU32(addr, value)
        if res != 0:
            raise errors.JLinkWriteException('Error writing to %d' % addr)
        return value

    @connection_required
    def peripheral_write64(self, addr, value):
        """Writes long word to peripheral register of target system.
        Args:
          self (JLink): the ``JLink`` instance
          addr (int): start address to write to
          value (long): the value to write to the register
        Returns:
          The value written to the register.
        Raises:
          JLinkException: on write error.
        """
        # Default type is uint32_t,so specify the parameter type of the C function, otherwise get "ArgumentError"
        self._dll.JLINKARM_WriteU64.argtypes = [ctypes.c_uint32, ctypes.c_uint64]
        res = self._dll.JLINKARM_WriteU64(addr, value)
        if res != 0:
            raise errors.JLinkWriteException('Error writing to %d' % addr)
        return value

例子:点灯大法

像USB转串口、转SPI、转IIC,又或者通过ADC实现桌面示波器这种就不多说了,尽情发挥想象。这里简单的演示一下用法:按键(PA0)按下LED(PB10)亮,松开则灭。MCU使用的是NUC472HI8AE。

import pylink
import time

# GPIO相关的寄存器地址,从手册上可以得到
GPIO_BA = 0x40004000

PA_MODE = GPIO_BA + 0x000
PA_PIN = GPIO_BA + 0x010

PB_MODE = GPIO_BA + 0x040
PB_DOUT = GPIO_BA + 0x048

jlink = pylink.JLink()
jlink.open()
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
jlink.connect('NUC472HI8AE')
jlink.reset(halt=False)

# 配置按键(PA0)为双向IO(带内部上拉),这里偷懒,直接将整组PA口都设为双向IO
jlink.peripheral_write32(PA_MODE, 0xFFFFFFFF)

# 配置LED(PB10)为输出
jlink.peripheral_write32(PB_MODE, 0x01 << 20)

while True:
    # 读取PA引脚的值
    gpio_value = jlink.memory_read32(PA_PIN, 1)
    if gpio_value[0] & 0x01:
        # 关闭LED
        jlink.peripheral_write32(PB_DOUT, 0x01 << 10)
    else:
        # 点亮LED
        jlink.peripheral_write32(PB_DOUT, 0x00 << 10)
    # 10ms 检测一次
    time.sleep(0.01)

jlink.close()
说明

可以看到,这相当于将原本在mcu上写的程序放到了PC上用python来写。例子中并没有初始化时钟这些操作,是因为使用的NUC472HI8AE上电复位后系统时钟、IO的时钟这些都直接可用,为了简化例子就没有再去配置一遍。如果使用别的MCU,比如STM32L4xx这种,上电复位后IO的时钟默认关闭的,还是得先配置好时钟。

相关文章

网友评论

    本文标题:通过jlink实现不需要下位机的“上位机”开发

    本文链接:https://www.haomeiwen.com/subject/rgtrhctx.html