编程ARM微控制器的标准(低成本)方法是使用Eclipse,并在其中插入复杂的工具链.Eclipse肯定有它的优点,但我想要独立于这个IDE.我想发现当我构建(编译 - 链接 - 闪存)我的软件以及运行调试会话时幕后发生的事情.为了更深入地理解,从命令行运行整个过程会很棒.
注意:我使用的是64位Windows 10.但这里解释的大部分内容也适用于Linux系统.请使用管理员权限打开所有命令终端.这可以为您节省很多问题.
1.构建软件
第一个"使命"完成了.我现在能够通过命令行编译和链接我的软件到二进制文件.bin和.elf图像.成功的关键是找出Eclipse为特定项目提供make文件的位置.一旦你知道它们在哪里,你所要做的就是打开一个命令终端,然后输入GNU make命令.
你不再需要Eclipse了!特别是如果您可以阅读(并理解)makefile并在项目进展时根据您的需要进行调整.
请注意,在安装SW4STM32(System Workbench for STM32)之后,我在以下文件夹中找到了GNU工具(编译器,链接器,make实用程序,GDB,...):
C:\Ac6\SystemWorkbench\plugins\fr.ac6.mcu.externaltools.arm-none.win32_1.7.0.201602121829\tools\compiler\
Run Code Online (Sandbox Code Playgroud)
接下来,我在硬盘上创建了一个新文件夹,并将所有这些GNU工具复制到其中:
C:\Apps\AC6GCC
|-> arm-none-eabi
|-> bin
'-> lib
Run Code Online (Sandbox Code Playgroud)
我将这些条目添加到"环境路径变量":
- C:\Apps\AC6GCC\bin
- C:\Apps\AC6GCC\lib\gcc\arm-none-eabi\5.2.1
Run Code Online (Sandbox Code Playgroud)
Huray,现在我已经在我的系统上启动并运行了所有GNU工具!我将以下build.bat文件放在与以下文件夹相同的文件夹中makefile:
@echo off
echo.
echo."--------------------------------"
echo."- BUILD -"
echo."--------------------------------"
echo.
make -j8 -f makefile all
echo.
Run Code Online (Sandbox Code Playgroud)
运行这个bat文件应该可以胜任!如果一切顺利,您将获得一个.bin和一个.elf二进制文件作为编译的结果.
2.闪烁和调试固件
自然的后续步骤是将固件刷新到芯片并启动调试会话.在Eclipse中,只需"点击一个按钮" - 至少如果为您的微控制器正确配置了Eclipse.但是幕后会发生什么?我从Dominic Rath(OpenOCD的开发者)那里阅读(部分)硕士论文.你可以在这里找到它:http://openocd.net/.这是我学到的:
单击"调试"图标时,Eclipse将启动OpenOCD软件.Eclipse还为OpenOCD提供了一些配置文件 - 这样OpenOCD就知道如何连接到微控制器."如何连接"并非易事.OpenOCD需要找到合适的USB驱动程序来连接JTAG适配器(例如STLink).JTAG适配器及其USB驱动器通常由您的芯片制造商提供(例如STMicroelectronics).Eclipse还将配置文件移交给OpenOCD,该文件描述了微控制器的规格.一旦OpenOCD知道所有这些事情,它就可以与目标设备建立可靠的JTAG连接.
OpenOCD启动两个服务器.第一个是TCP端口4444上的Telnet服务器.它可以访问OpenOCD CLI(命令行界面).Telnet客户端可以连接并向OpenOCD发送命令.这些命令可以是简单的"停止","运行","设置断点",......
这些命令可能足以调试你的微控制器,但很多人已经熟悉Gnu调试器(GDB).这就是为什么OpenOCD还在TCP端口3333上启动GDB服务器.GDB客户端可以连接到该端口,并开始调试微控制器!
Gnu调试器是一个命令行软件.很多人更喜欢可视化界面.这正是Eclipse所做的.Eclipse启动了一个连接到OpenOCD的GDB客户端 - 但这对用户来说都是隐藏的.Eclipse提供了一个图形界面,可以在幕后与GDB客户端进行交互.
我已经做了一个数字来解释所有这些事情:
>>启动OpenOCD …
设置
我用Python编写了一个相当复杂的软件(在Windows PC上).我的软件基本上启动了两个Python解释器shell.双击main.py文件时,第一个shell启动(我猜).在该shell中,其他线程以下列方式启动:
# Start TCP_thread
TCP_thread = threading.Thread(name = 'TCP_loop', target = TCP_loop, args = (TCPsock,))
TCP_thread.start()
# Start UDP_thread
UDP_thread = threading.Thread(name = 'UDP_loop', target = UDP_loop, args = (UDPsock,))
TCP_thread.start()
Run Code Online (Sandbox Code Playgroud)
在Main_thread启动TCP_thread和UDP_thread.虽然这些是单独的线程,但它们都在一个单独的Python shell中运行.
这Main_thread也启动了一个子进程.这是通过以下方式完成的:
p = subprocess.Popen(['python', mySubprocessPath], shell=True)
Run Code Online (Sandbox Code Playgroud)
从Python文档中,我了解到这个子进程在一个单独的Python解释器会话/ shell中同时运行(!).在Main_thread这个子完全是献给我的GUI.GUI TCP_thread为其所有通信启动a .
我知道事情变得有点复杂.因此,我总结了这个图中的整个设置:
关于这个设置,我有几个问题.我会在这里列出它们:
问题1 [已解决 ]
Python解释器一次只使用一个CPU核心来运行所有线程,这是真的吗?换句话说,Python interpreter session 1(从图中)是否会在一个CPU核心上运行所有3个线程(Main_thread,TCP_thread和UDP_thread)? …
这篇文章是关于从源代码构建整个Eclipse IDE的 - 更具体地说,是如何指定要为其构建可执行文件的目标OS.
我找到了以下教程来指导我完成构建过程:http://www.vogella.com/tutorials/EclipsePlatformDevelopment/article.html
特别是该教程的第13章很有帮助.我将在这里逐一描述需要采取的步骤 - 因此您无需阅读vogella教程.
需要的软件:
显然,您需要在(Windows)计算机上安装以下软件:
现在你已准备好开始:
步骤1 :
在C:\磁盘中创建一个新文件夹.我们来命名吧C:\myEclipse.这将是我们在其中提取最新Eclipse版本的Git存储库的文件夹.
第2步 :
cmd使用管理员权限打开Windows shell(cmd如果您在桌面上创建了一个图标,请右键单击图标,然后选择open with admin rights).通过命令转到该文件夹cd C:\myEclipse.现在输入以下命令:git config --system core.longpaths true.这通知Git存储库中可能出现长名称.忘记此命令,稍后将导致错误.
第3步:
克隆Git存储库:
git clone -b master --recursive git://git.eclipse.org/gitroot/platform/eclipse.platform.releng.aggregator.git
Run Code Online (Sandbox Code Playgroud)
现在您应该耐心地将所有源代码复制到本地文件夹.
第4步 :
最后是时候开始构建了.构建过程将花费数小时,因此跳过单元测试是明智的.因此不要忘记添加-DskipTests参数.这是启动构建的命令:
mvn clean verify -DskipTests
Run Code Online (Sandbox Code Playgroud)
几个小时后,应该完成构建.
第5步:
构建的结果现在应该在以下文件夹中:
C:\myEclipse\eclipse.platform.releng.aggregator\eclipse.platform.releng.tychoeclipsebuilder\sdk\target\products
请注意,Eclipse IDE是为所有可能的目标计算机构建的.32位Windows,64位Windows,Macintosh,Linux,......难怪需要几个小时!我想只为一个目标构建 - 例如我的64位Windows机器.这有望显着缩短构建时间,并允许我更快地验证代码更改.
有谁知道如何实现这一目标?
编辑:
我已将参数添加-Dnative=win32.win32.x86_64到build命令中.不幸的是,我在15到20分钟后出错了.这一次,我也添加了参数 …
我正在尝试在 Python 中使用类型注释。大多数情况都非常清楚,除了那些将另一个函数作为参数的函数。
考虑以下示例:
from __future__ import annotations
def func_a(p:int) -> int:
return p*5
def func_b(func) -> int: # How annotate this?
return func(3)
if __name__ == "__main__":
print(func_b(func_a))
Run Code Online (Sandbox Code Playgroud)
输出只是打印15.
我应该如何注释 中的func参数func_b( )?
回答
谢谢@Alex 提供答案。该typing模块提供Callable注释(请参阅:python 文档)。对于我的示例,这给出了:
from __future__ import annotations
from typing import Callable
def func_a(p:int) -> int:
return p*5
def func_b(func: Callable[[int], int]) -> int:
return func(3)
if __name__ == "__main__":
print(func_b(func_a))
Run Code Online (Sandbox Code Playgroud)
如您所见,Callable注释本身也被注释,遵循以下方案:
Callable[[Arg1Type, …Run Code Online (Sandbox Code Playgroud) 我目前正在学习如何编写makefile.我有以下makefile(它是为一个应该在ARM芯片上运行的C项目自动生成的),我正在尝试理解它:
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include FreeRTOS/Supp_Components/subdir.mk
-include FreeRTOS/MemMang/subdir.mk
-...
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(S_UPPER_DEPS)),)
-include $(S_UPPER_DEPS)
endif
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: FreeRTOS_T02.elf
# Tool invocations
FreeRTOS_T02.elf: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: MCU GCC Linker'
arm-none-eabi-gcc -mcpu=cortex-m7 …Run Code Online (Sandbox Code Playgroud) 我想用GNU make工具为我的微控制器构建一个C项目.我想以一种干净的方式做到这一点,这样我的源代码在构建之后就不会被目标文件和其他东西弄得乱七八糟.所以想象一下,我有一个名为"myProject"的项目文件夹,里面有两个文件夹:
- myProject
|
|---+ source
|
'---+ build
Run Code Online (Sandbox Code Playgroud)
build文件夹只包含一个makefile.下图显示了运行GNU make工具时应该发生的事情:
所以GNU make应该为它可以在源文件夹中找到的每个.c源文件创建一个目标文件.目标文件应该在与源文件夹中的结构类似的目录树中构建.
GNU make还应为每个.c源文件创建一个.d依赖文件(事实上,依赖文件是某种makefile本身).GNU make手册第4.14节"自动生成先决条件"中描述了依赖项文件:
对于每个源文件name.c,都有一个makefile name.d,它列出了目标文件name.o所依赖的文件.
从下面的问题#1 关于GNU使相关文件*.D,我了解到,增加的选项-MMD,并-MP给CFLAGS了GNU gcc编译器可以帮助自动执行.
所以现在问题就出现了.有没有人有一个样本makefile执行这样的源外构建?或者有关如何入门的一些好建议?
我很确定大多数编写过这样一个makefile的人都是Linux用户.但是微控制器项目也应该在Windows机器上构建.无论如何,即使你的makefile只是Linux,它提供了一个很好的起点;-)
PS:我想避免使用像CMake,Autotools或任何与IDE有关的任何工具.只是纯粹的GNU make.
我会很感激 :-)
更新依赖项文件
请看一下这个问题:当GNU更新.d文件时,确切的事件链是什么?
我正在使用STMicroelectronics的STM32F746NG微控制器.该器件基于ARM Cortex-M7架构.我花了很多时间来理解示例项目中的linkerscript.我想出了基础知识,但我仍然无法掌握它的大部分内容.请帮我理解这些部分.
linkerscript开头如下:
/* Entry Point */
ENTRY(Reset_Handler) /* The function named 'Reset_Handler' is defined */
/* in the 'startup.s' assembly file. */
/* Highest address of the user mode stack */
/* Remember: the stack points downwards */
_estack = 0x20050000; /* End of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* Required amount of heap */
_Min_Stack_Size = 0x400; /* Required amount of stack */ …Run Code Online (Sandbox Code Playgroud) 我把问题放在下图中:
编辑 旁边的问题是:
如何让script_A1从script_B2导入一个函数?
之前曾提出过类似的问题.但大多数答案都建议将模块/脚本/包(无论如何)添加到PATH变量中.例如:
sys.path.append('...')
Run Code Online (Sandbox Code Playgroud)
但是将模块添加到PATH变量只是觉得错误.我不想以任何方式改变我的系统.当我的应用程序关闭时,我希望我的Python环境干净且"不受影响".我担心在我的系统上添加不受控制的模块到PATH变量会导致后来的麻烦.
谢谢你帮助我:-)
DIRECT-VS COPY-INITIALIZATION
通过这个问题(它是直接初始化还是复制初始化?)我学到了直接初始化和复制初始化之间的区别:
Run Code Online (Sandbox Code Playgroud)direct-initialization copy-initialization ----------------------- --------------------- obj s("value"); obj s = obj("value"); obj s = "value"; obj s{"value"}; obj s = {"value"}; obj s = obj{"value"};
为了完整起见,我在这里提到它.我对此页面的实际问题列在下一段>>
直接初始化与直接列表初始化
答案显示,在直接初始化的范畴内,可以在直接初始化和直接列表初始化之间产生差异.
Run Code Online (Sandbox Code Playgroud)obj s("value"); // direct-initialization obj s{"value"}; // direct-list-initialization
我知道列表初始化不允许缩小,这样初始化int x{3.5};就不会编译.但除此之外,我还有几个问题:
(1)
obj s("value");和之间的编译器输出有什么不同obj s{"value"};吗?
让我们考虑一个没有任何优化的编译器.我想知道任何可能的技术差异:-)
(2)也许我应该问一个多变量初始化完全相同的问题,例如:
obj s("val1", "val2");和obj s{"val1", "val2"};
(3)我注意到列表初始化有时可以调用不同的构造函数,如:
vector<int> a{10,20}; //Curly braces -> fills the …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 PyQt5 中的基本语法突出显示、代码完成和可点击的函数和变量来制作一个简单的文本编辑器。我最大的希望是使用 PyQt5 的 QScintilla 端口
。
我在 Eli Bendersky 网站 ( http://eli.thegreenplace.net/2011/04/01/sample-using-qscintilla-with-pyqt )上找到了以下基于 QScintilla 的文本编辑器示例,Victor S. 已将其改编为 PyQt5 )。我认为这个例子是一个很好的起点:
#-------------------------------------------------------------------------
# qsci_simple_pythoneditor.pyw
#
# QScintilla sample with PyQt
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------
import sys
import sip
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import QsciScintilla, QsciLexerPython
class SimplePythonEditor(QsciScintilla):
ARROW_MARKER_NUM = 8
def __init__(self, parent=None):
super(SimplePythonEditor, self).__init__(parent)
# Set the default …Run Code Online (Sandbox Code Playgroud)