玩转 pyocd
(一) pyocd
(1) 什么是pyocd
pyocd 是 arm 开发的一个 python 包(python package),该软件包可以使用多种USB调试器对 arm cortex-M 微控制器进行调试、编程(烧录程序)。该软件包还是跨平台的,支持Linux、Mac、Windows。
也就是说,可以通过 pyocd 使用一些调试器来调试、擦除、烧录基于 arm cortex-M(M0/M3/M4/M7/M23/M33) 内核的单片机。目前支持 Daplink、ST-Link、jlink。
目前从 pyocd github 上看到的,pyocd 内部(默认)支持70多个常用的单片机,但是通过使用 CMSIS-Packs 几乎支持所有基于 comtex-m 内核的单片机。
这里不关注 pyocd 调试功能,只关注把 pyocd 用作上位机来操作 MCU 的功能,可以通过两种方式使用 pyocd:
- pyocd 提供了命令行工具,使用这工具可以用来调试、烧录、擦除 MCU
- pyocd 提供了python API,可是使用这些API来实现控制 MCU(读取MCU寄存器、暂停、运行、复位MCU等)
(2) 安装
pyocd 支持的系统: windows、linux、Mac
由于 pyocd 是基于 python,所以需要先安装 python,pyocd 支持的 python 版本为:Python 3.6.0 or later.
安装方法有:
- 下载 pyocd 的源码安装
从 GitHub 获取源码:
git clone https://github.com/mbedmicro/pyOCD.git
进入pyOCD目录,使用如下命令安装:
python setup.py install
- 通过pip安装
pip install -U pyocd
python3 -mpip install --pre -U git+https://github.com/pyocd/pyOCD.git@develop
参考:https://pypi.org/project/pyocd/
(3) Libusb
daplink V1 使用的是 HID 协议,只要安装pyocd是可以用的,如果使用 daplink V2、ST-Link、j-link 的话,需要安装 libusb,pyocd 里面的文档给出了安装方法。
我的做法是把 libusb.dll 复制到 python 安装目录:
(二)如何使用pyocd命令行工具
首先打开命令行,windows 中可以是命令提示符或者 powershell,如下:
如果安装了 git,也可以使用 git bash,如下:
pyocd 的使用方法是在命令行中输入:
pyocd + 子命令 + 参数
在命令行中输入 pyocd 或者 pyocd -h 回车,如下图,就会输出 pyocd 的使用方法及 pyocd 的子命令:
根据上面说明,看下我安装的版本:
从上图中可以看到 0.30.2 版本有 9 个子命令,但其中 commander 跟 cmd、gdbserver 跟 gdb 是相同功能的。所以,总的来说有 9 个功能不同的子命令。分别是:
- commander跟cmd: 可交互的终端,
- erase: 擦除命令
- flash:烧录命令
- reset:复位设备
- gdbserver跟gdb:用于gdb调试的
- json:以json格式输出信息
- list:可以列出dap-link、目标IC、特定板子的信息
- pack:用于管理CMSIS-Pack
- server
如果想知道上述命令的用法可以使用 pyocd + 上述中的一个命令 + -h/--help,如下:
这些命令各有什么用呢?什么情况下要用什么命令?这些命令怎么配合使用?
比如,使用 j-link 给 MCU 下载固件,一般会使用上位机 j-flash 通过 jlink 下载,首先 上位机 j-flash 能找到 j-link,然后需要选择所下载的 MCU,然后选择所要下载的固件,这 3 步都设置好后,就可以下载程序了,
根据这些,依次介绍 pyocd 的命令:
- list or json:查看能够使用的调试器、支持的 MCU
- pack:管理支持的 MCU
- flash & erase : 对 MCU 进行编程、擦除
(1)pyocd list 命令
从 pyocd 帮助信息来看:
list List information about probes, targets, or boards.
可以知道 list 命令使用来查看 调试器、目标芯片、板子的信息,
- pyocd list / pyocd list -p
列出连接到电脑上的 dap link 或者 ST link,当没接如任何pyocd所支持的设备时,如下:
接入了一个 daplink 跟 jlink 后如下:
(1.1) pyocd list -t/--target
列出所支持的IC,可以是内置的,也可以是通过安装pack获得支持的,
上面图片展示了列出了 pyocd 内置的一部分 MCU。
我的电脑中已近安装了 GD32F350 的pack,上图中,GD32F350 系列后面就显示了 pack
(1.2) pyocd list -b/--board
列出所支持的板子,如下:
(2)pyocd json 命令
json Output information as JSON.
以 json 格式输出信息,输出什么信息呢? 看下 json 命令帮助:
从上图可以看到 pyocd json 一共可以输出4中信息:probes、targets、boards、features。分别看下这4中会输出什么。
(2.1)pyocd list -p
当电脑没有接入任何 pyocd 支持的设备时:
可以看到输出了所安装的 pyocd 版本信息,接了一块ST的开发板后,如下:
可以看到,输出的除了 pyocd 版本信息外,还有所接板子的信息:板子上调试器的ID、板的名字等。
再试一下,接一块没有连接目标 MCU 的 Daplink,输出的信息如下:
(2.2) pyocd json -t
从帮助信息来看,是输出所有已知的 target,先试下pyocd json -t
命令,如下:
输出一大堆数据,除了有pyocd 版本信息外,就是一些MCU的信息,有MCU的厂商、型号,还有该信息是内置的还是来自pack。
试下能不能输出指定 MCU 的信息:
从上述结果来看,好像是不行。
pyocd list 跟 pyocd json 功能应该是差不多的,都是输出一些信息,如接入了电脑的调试器信息,系统所支持的单片机等,只不过输出方式不同,pyocd list 是直接输出相关信息,pyocd json 是以 json 格式输出相关信息。
(3)pyocd pack 命令
pyocd 通过两种方法支持 MCU,一个是内置的(builtin),这个数量有限,还有一个是通过 pack 来支持,需要用pyocd 操作什么 MCU,安装对应的 pack , 类似 keil5 ,新安装的 Keil5 不支持任何单片机,如果要使用新安装的keil 支持某类型号单片机,需要安装对应的软件包。
pyocd 提供了一个内置的子命令来对pack进行管理,安装、查找、删除等,来看下 pyocd pack 命令的帮助信息:
送上图来看,有5个功能选项:
- -c:清楚保存在电脑上的pack信息
- -u:更新pack索引
- -s:显示已安装的pack
- -f:查找某个IC对应的pack
- -i:安装指定的pack
pyocd 使用的 pack 有个默认的存放路劲,我电脑上为:
C:\Users\Administrator\AppData\Local\cmsis-pack-manager\cmsis-pack-manager
pyocd pack 命令就是对该目录的文件进行管理。
(3.1)pyocd pack -U
使用方法为:
pyocd pack -u
或者
pyocd pack --update
第一次使用该命令的时候,会在pyocd存放pack文件的默认路劲下下载不同厂商不同系列 MCU 的 pack 的描述文件(pdsc文件)和 index.json、aliases.json 文件。执行过一次之后,会从网络上更新相应的文件。下图是一个执行pyocd pack -u的结果,有出现错误。
下图是执行了pyocd pack -u 后,pack 所在文件夹多了很多文件:
(3.2)pyocd pack -f
使用方法为:
pyocd pack -f partnumber
该命令会显示出对应型号 MCU 的 pack 的信息,如下图,显示了 stm32f042 所对应 pack 的信息
(3.3)pyocd pack -i
使用方法为:
pyocd pack -i partnumber
该命令安装指定型号MCU的pack,如下图:
不过,由于网络的问题,一般很难下载完成,跟keil下载pack一样,非常慢,经常下载失败,可以手动下载所需的pack,然后放到对应目录。
(3.4)pyocd pack -s
使用方法为:
pyocd pack -s
列出所安装的pack,如果还未安装任何pack,该命令执行结果为:
安装有pack后,执行结果为:
(4)pyocd flash 命令
测试硬件是 Daplink+STM32F042F4 最小系统,Daplink 我自己用 STM32F042F4做的,如下:
STM32F042F42 的测试程序是用 Cube MX 创建工程,由于板子上没有其他外设,但是 Daplink 有 USB 转 TTL,实现了个 STM32F042 Uart 输出的测试程序,主要程序如下:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("STM32F042:%d\r\n",i);
i++;
HAL_Delay(1000);
}
/* USER CODE END 3 */
正常跑起来是这样:
第一次测试,首先执行 pyocd list
查看是否成功识别到设备,确认能够找到 daplink 后。
pyocd flash -h
输出的帮助信息看不出来 pyocd flash 应该怎么用:
非常多选项,这里只关注烧录的功能,通过查阅 pyocd 的文档,了解到可以使用如下命令来给MCU烧录程序:
pyocd flash -t mcu_partnumber firmware
我的 MCU 是 stm32f042f4,测试固件是 pyocd_test.hex
,尝试使用命令 :
pyocd flash --t stm32f042f4 ./pyocd_test.hex
来烧录程序,结果如下:
结果显示不支持 stm32f042f4,使用 list 查看下目前环境下支不支持 042:
下载 stm32f042 的 pack:
可以找到 STM32F042 了,重新试下烧录:
从这结果看是烧录成功了,看了下板子,也成功跑起来了:
(5)pyocd erase 命令
pyocd 帮助信息中对该指令的描述是:
erase Erase entire device flash or specified sectors.
也就是说可以使用该指令对 设备 进行全擦或者指定扇区,pyocd earse帮助信息如下:
我尝试使用了如下命令:
(5.1) 整片擦除:-c/--chip
看了下板子已经没有输出了,
(5.2) 擦除扇区:-s/--sector
该命令需要加一个扇区地址,如果没加的话,会不成功,如下是没加地址的:
对于目标芯片,如果添加的地址不对,也会操作不成功:
添加正确的地址结果如下:
(5)使用 pyocd 操作 STM32F051
试下安装 STM32051 的 pack,看下能不能通过安装 STM32f051 的 pack 来使 pyocd 支持 STM32f051,首先查看已安装的 pack,查询结果如下,
PS D:\project\USB\Daplink\my_dap\doc> pyocd pack -s
Vendor Pack Version
---------------------------
从上述结果来看,尚未安装任何 pack,然后尝试下载 stm32f051 pack:
PS D:\project\USB\Daplink\my_dap\doc> pyocd pack -i STM32F051C8Tx
Downloading packs (press Control-C to cancel):
Keil::STM32F0xx_DFP::2.0.0
等了很久,执行完上述命令后,尝试烧录,结果如下:
PS D:\project> pyocd flash -t stm32f051r8 .\stm32051_test.hex
0001009:CRITICAL:__main__:Failed to open CMSIS-Pack 'C:\Users\dell\AppData\Local\cmsis-pack-manager\cmsis-pack-manager\Keil\STM32F0xx_DFP\2.0.0.pack': File is not a zip file
Traceback (most recent call last):
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\target\pack\cmsis_pack.py", line 88, in __init__
self._pack_file = zipfile.ZipFile(file_or_path, 'r')
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\zipfile.py", line 1200, in __init__
self._RealGetContents()
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\zipfile.py", line 1267, in _RealGetContents
raise BadZipFile("File is not a zip file")
zipfile.BadZipFile: File is not a zip file
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\__main__.py", line 343, in run
self._COMMANDS[self._args.cmd](self)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\__main__.py", line 470, in do_flash
options=convert_session_options(self._args.options))
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\core\helpers.py", line 241, in session_with_chosen_probe
return Session(probe, auto_open=auto_open, options=options, **kwargs)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\core\session.py", line 175, in __init__
or Board(self, self.options.get('target_override'))
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\board\board.py", line 48, in __init__
pack_target.ManagedPacks.populate_target(target)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\target\pack\pack_target.py", line 84, in populate_target
targets = ManagedPacks.get_installed_targets()
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\target\pack\pack_target.py", line 71, in get_installed_targets
pack = CmsisPack(pack_path)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pyocd-0.23.1.dev12-py3.7.egg\pyocd\target\pack\cmsis_pack.py", line 91, in __init__
file_or_path, err)), err)
File "<string>", line 3, in raise_from
pyocd.target.pack.cmsis_pack.MalformedCmsisPackError: Failed to open CMSIS-Pack 'C:\Users\dell\AppData\Local\cmsis-pack-manager\cmsis-pack-manager\Keil\STM32F0xx_DFP\2.0.0.pack': File is not a zip file
还是不能成功下载,从上述信息来看应该是解析stm32f0的pack失败,到目录C:\Users\dell\AppData\Local\cmsis-pack-manager\cmsis-pack-manager\Keil\STM32F0xx_DFP\
看了下,有文件2.0.0.pack,20多兆。
手动从https://www.keil.com/dd2/Pack/#/eula-container
下载了Keil.STM32F0xx_DFP.2.0.0.pack
,有60多兆,对比下,问题是使用pyocd pack -i安装的stm32f051的pack有问题。把自己下载的Keil.STM32F0xx_DFP.2.0.0.pack
重命名为2.0.0.pack
,放到目录C:\Users\dell\AppData\Local\cmsis-pack-manager\cmsis-pack-manager\Keil\STM32F0xx_DFP\
,然后重新烧录:
PS D:\project\USB\Daplink\my_dap\doc> pyocd flash -t stm32f051r8 .\stm32051_test.hex
[====================] 100%
0001733:INFO:loader:Erased 3072 bytes (3 sectors), programmed 3072 bytes (3 pages), skipped 0 bytes (0 pages) at 7.12 kB/s
板子运行起来了,下载成功。
还做了实验,还是使用STM32F051板子,跑一个很简单的程序,控制一个LED闪烁,试了下指定芯片跟不指定芯片有什么区别,效果怎样,如下:
从上面结果来看,如果没指定芯片,虽然说从结果来看,是执行了擦除操作,可是板子还在运行,LED还在闪烁,指定了芯片后,执行完任务后,LED不再闪烁了。
(三)使用 pyocd python api
这里尝试下使用pyocd python api来操作单片机。
环境是:
PC: windows10
python
硬件
调试器:一块跑Daplink V1的STM32F042最小系统
目标板:一个STM32F042最小系统
如下:
首先导入库:
from pyocd.probe.aggregator import DebugProbeAggregator
from pyocd.board.board import Board
from pyocd.core.helpers import ConnectHelper
from pyocd.core.target import Target
import logging
from pyocd.core.memory_map import MemoryType
from pyocd.core.coresight_target import CoreSightTarget
from pyocd.coresight.cortex_m import CortexM
按照 pyocd 的文档,首先是创建一个 Session
,如下:
session = ConnectHelper.session_with_chosen_probe(None, None)
session.open()
然后可以获取到当前 session 中的 board,如下:
board = session.board
print("Board MSG:")
print("Board's name:%s" % board.name)
print("Board's description:%s" % board.description)
print("Board's target_type:%s" % board.target_type)
print("Board's unique_id:%s" % board.unique_id)
print("Board's test_binary:%s" % board.test_binary)
print("Unique ID: %s" % board.unique_id)
上述程序执行结果如下:
从上述信息来看,是可以成功是别到我的调试器,但是没有正确显示目标芯片,除了我要输出的信息外,还有一段内容,说的是当前目标类芯片类型型是 cortex_m,选这类型可以进行调试但不能烧录,可以通过 --target 或者 target_override 选项来指定目标芯片。
修改代码如下,通过 target_override 指定了我的目标芯片:
session = ConnectHelper.session_with_chosen_probe(target_override="stm32f042f4")
session.open()
board = session.board
print("Board MSG:")
print("Board's name:%s" % board.name)
print("Board's description:%s" % board.description)
print("Board's target_type:%s" % board.target_type)
print("Board's unique_id:%s" % board.unique_id)
print("Board's test_binary:%s" % board.test_binary)
print("Unique ID: %s" % board.unique_id)
运行结果为:
这回显示了我的目标芯片。
成功了获取到了调试器的信息,现在来试下获取当前环境下目标芯片的信息,代码如下:
target = board.target
print("Part number:%s" % target.part_number)
memory_map = target.get_memory_map()
ram_region = memory_map.get_default_region_of_type(MemoryType.RAM)
rom_region = memory_map.get_boot_memory()
print("menory map:")
print(memory_map)
print("ram_region:")
print(ram_region)
print("rom_region:")
print(rom_region)
运行结果为:
从上述结果来看,是可以成功获取到目标芯片的 part number、Flash 跟 RAM 信息。
通过查看 pyocd 的源码,target 实例有个 irq_table 属性,看下这个属性会输出什么信息:
print("Irq:")
print(target.irq_table)
输出如下:
试下读取单片机一些寄存器:
print("pc reg: 0x%X" % target.read_core_register('pc'))
print("CPUID:0x%x" % target.read32(CortexM.CPUID))
print("device id:0x%x" % target.read32(0x40015800))
print("flash size:%x KB" % target.read32(0x1FFFF7CC))
运行结果如下:
第一个读取 PC 寄存器的值
这个读出来的值究竟对不对,没去查看,不过从这个值的大小来看(在0x8000000到8004000之前),应该是对的。
第二个,读取CPUID的值
RM0091 Reference manual (stm32f0x2 参考手册) 中关于CPU ID 部分如下:
stm32f042是arm M0 ,根据上述内容,该芯片的CPU ID为:
ARM V0 ARMv6-M M0 Revision
0x41 0 c c20 0
也就是0x140cc200,跟读取到的结果对的上,
第三个读取设备ID
RM0091 Reference manual (stm32f0x2 参考手册) 中也有 设备 ID 的内容,如下:
从文档来看,读取出来的值也是对的,
- 第四个,读取Flash大小
目标 IC 是 STM32F042F4,Flash 实际大小是 16K,读出来的也是 16K
完整代码为:
from pyocd.probe.aggregator import DebugProbeAggregator
from pyocd.board.board import Board
from pyocd.core.helpers import ConnectHelper
from pyocd.core.target import Target
import logging
from pyocd.core.memory_map import MemoryType
from pyocd.core.coresight_target import CoreSightTarget
from pyocd.coresight.cortex_m import CortexM
session = ConnectHelper.session_with_chosen_probe(target_override="stm32f042f4")
session.open()
board = session.board
print("Board MSG:")
print("Board's name:%s" % board.name)
print("Board's description:%s" % board.description)
print("Board's target_type:%s" % board.target_type)
print("Board's unique_id:%s" % board.unique_id)
print("Board's test_binary:%s" % board.test_binary)
print("Unique ID: %s" % board.unique_id)
target = board.target
print("Part number:%s" % target.part_number)
memory_map = target.get_memory_map()
ram_region = memory_map.get_default_region_of_type(MemoryType.RAM)
rom_region = memory_map.get_boot_memory()
print("menory map:")
print(memory_map)
print("ram_region:")
print(ram_region)
print("rom_region:")
print(rom_region)
print("Irq:")
print(target.irq_table)
print("pc reg: 0x%X" % target.read_core_register('pc'))
print("CPUID:0x%x" % target.read32(CortexM.CPUID))
print("device id:0x%x" % target.read32(0x40015800))
print("flash size:%d KB" % (target.read32(0x1FFFF7CC) & 0x0000ffff))
对于这段代码,我试着在创建 session 的时候,把指定目标芯片的型号跟实际使用的芯片型号设置成不一样,
第一次看到跑的结果的时候,有点懵逼,不过想了下,合理。
参考:
api_examples:pyOCD\docs\api_examples.md,即pyocd源码目录下docs/api_examples.md
architecture:pyOCD\pyOCD-0.25.0\docs\architecture.md
(四)可以用 pyocd 用来做什么
还是只关注 pyocd 烧录的功能,在这个点上面,可以怎么使用 pyocd 呢?
对于 pyocd 命令,当然是直接用来烧录了,pyocd 是跨平台的,不管使用的是 ST-Link、J-link、Daplink,由于一般情况下使用的都是固定的几种 MCU,把 pyocd 命令 做成脚本文件,如 windows 的 bat、Linux Shell 脚本,很方面使用。
对于使用 pyocd python api,可以使用 python 做个烧录的上位机,对于使用 ST-Link 烧录 ST MCU、J-link 有个j-flash 来说好像是多次一举,不过对于一些使用场景,如对于不是做单片机开发的,如硬件工程师、做上位机开发的纯软件工程师、或者其他不懂这方面的人来说,使用 j-flash 设置选项比较多可能一时用不起来,如果使用 pyocd python api 做个上位机一键烧录,就可以解决这问题。
还有对于使用 daplink 的人来说,把 daplink 用于调试是非常方便的,不用担心什么时候被识别为盗版的导致用不了而耽误工作,由于 daplink 没有对应的上位机,要使用 daplink 烧录的话就不方便了,pyocd python api 做个上位机就可以解决这问题,如下是我用 pyocd + PyQT 做的一个上位机给一个软件工程师用,只能烧录 STM32F103C8,直接把软件给过去就可以用起来,不用教这软件的使用方法,这还可以做的跟简单,一键烧录。
还有一些场景,如,如果机器给到了客户,要更新固件的话,直接把固件给客户,怕客户拿到了固件,另外找个便宜点的供应商做个硬件,不再跟你买了,岂不亏大了,如果自己做个烧录上位机,对给过去的固件做些加密什么的,客户就无法用其他烧录软件烧录这固件了,还可以加个数量限制,就不怕客户直接用这个来生成烧录了,或者直接把固件放到一个服务器里,只给个烧录上位机就可以烧录,原理上这也是可以实现的。
玩转 pyocd的更多相关文章
- 玩转spring boot——快速开始
开发环境: IED环境:Eclipse JDK版本:1.8 maven版本:3.3.9 一.创建一个spring boot的mcv web应用程序 打开Eclipse,新建Maven项目 选择quic ...
- [C#] 软硬结合第二篇——酷我音乐盒的逆天玩法
1.灵感来源: LZ是纯宅男,一天从早上8:00起一直要呆在电脑旁到晚上12:00左右吧~平时也没人来闲聊几句,刷空间暑假也没啥动态,听音乐吧...~有些确实不好听,于是就不得不打断手头的工作去点击下 ...
- [C#] 了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数
了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数 目录 简介 特点 方法的参数 方法的返回值 与批处理交互的一个示例 简介 我们知道,新建一个控制台应用程序的时候,IDE 会同时创建 ...
- 玩转spring boot——开篇
很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...
- 玩转spring boot——结合redis
一.准备工作 下载redis的windows版zip包:https://github.com/MSOpenTech/redis/releases 运行redis-server.exe程序 出现黑色窗口 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- 玩转spring boot——结合JPA入门
参考官方例子:https://spring.io/guides/gs/accessing-data-jpa/ 接着上篇内容 一.小试牛刀 创建maven项目后,修改pom.xml文件 <proj ...
- 玩转spring boot——结合JPA事务
接着上篇 一.准备工作 修改pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...
- 玩转spring boot——结合AngularJs和JDBC
参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...
随机推荐
- angular小记
declarations:包装组件或指令等 providers:依赖注入 imports:导入其他模块 bootstrap:设置根组件 exports:导出组件或指令等 app.component.t ...
- HelloWord!
HelloWorld 1.新建一个文件夹,存放代码 2.新建一个java文件后缀为.java Hello.java (注意后缀 如系统没打开显示后缀需要打开) 3.编写HelloWorld代码 (建议 ...
- 【LeetCode】66. 加一
66. 加一 知识点:数组: 题目描述 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字. 你可以假设除了整数 0 ...
- Requests方法 -- Blog流程类进行关联
1.接口封装关联 1.有些接口经常会用到比如登录的接口,这时候我们可以每个接口都封装成一个方法,如:登录.保存草稿.发帖.删帖,这四个接口就可以写成四个方法2.接口封装好了后,后面我们写用例那就直接调 ...
- 微信小程序云开发-添加数据
一.数据的添加 使用add方法添加数据 添加完成后,在数据库中查询,可以看到数据库中添加了1条数据,此时添加的数据系统自动添加了_openid 将[添加]功能写到对应的方法中 wxml页面中,点击[添 ...
- 【排序+模拟】魔法照片 luogu-1583
题目描述 一共有n(n≤20000)个人(以1--n编号)向佳佳要照片,而佳佳只能把照片给其中的k个人.佳佳按照与他们的关系好坏的程度给每个人赋予了一个初始权值W[i].然后将初始权值从大到小进行排序 ...
- JAVA web环境搭建(使用Tomcat8整合httpd)
说明:这里是Linux服务综合搭建文章的一部分,本文可以作为单独搭建Tomcat并整合httpd的参考. 注意:这里所有的标题都是根据主要的文章(Linux基础服务搭建综合)的顺序来做的. 如果需要查 ...
- Mysql用户、权限、密码管理
一.用户管理 默认:用户root 创建用户: use mysql; create user 'alex'@'192.168.193.200' identified by '123456'; 创建了al ...
- Adaptive AUTOSAR 学习笔记 10 - 执行管理
本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本 AUTOSAR_EXP_PlatformDesign.pdf 缩写 EM:Execution Ma ...
- 看视频学SignalR—在微软虚拟学院学习SignalR
SignalR把实时Web功能变得异常简单. 如果您希望在几个小时内对SignalR有一个直观的了解,观看微软虚拟学院(MVA)的视频教学Lighting Up Real-Time Web Commu ...