如何从“基本”微控制器过渡到ARM Cortex?


22

我在使用来自多家制造商的8位内核(即8051,PIC和AVR)方面有多年的经验,现在我有了一个Cortex M0。具体来说这一个,但我希望我们能比这更普遍。

事实证明,这要超出我的讨价还价了,有多个文档以不同的详细程度描述了系统的不同部分,但实际上我还没有看到将它们连接在一起的事实。相比之下,只有一份数据手册可以解释所有内容。我了解首先需要记录的内容还很多,但是格式的变化使我陷入困境。

上面的网站有一个文档,它很好地概述了每个子系统和外围设备,另一个文档则详细描述了每个寄存器,我拥有其SDK的所有源代码,包括头文件和一些复杂的示例,但是我仍然看到没有描述它如何连接在一起的东西。

是否有Cortex架构的简要介绍,解释了小型控制器所不具备的功能(例如从CPU到外设的多层总线,每个总线都有自己的看门狗定时器),以及它们如何连接在一起?


从您的描述中我无法确定您是否从制造商那里获得了处理器的实际数据表/用户手册。那应该给您一个良好的整体印象和细节。从您链接的站点上的一张图片中,它看起来像一个NXP处理器。查看制造商的零件编号,并在其站点上搜索处理器的说明文件。还有ARM的站点arm.com/products/processors/cortex-m/cortex-m0.php
DigitalNinja

抱歉,延迟返回此;我一直在忙其他项目。感谢@Adam的心声。
AaronD 2015年

还要感谢@Richard给出了有关如何思考的概述以及有关打印引脚配置的注意事项。我支持你们俩。
AaronD 2015年

除非找到一些极端的价格要求,否则您永远都不会回去。即使那样,您也会被吸引,因为有很多便宜的Cortex-M。
RonanPaixão16年

Answers:


40

我曾经研究过AVR和基于ARM Cortex-M3 / M4 / R4的MCU。我想我可以提供一些一般性建议。这将假定您使用C而不是汇编进行编程。

CPU实际上是最简单的部分。基本的C数据类型将具有不同的大小,但是无论如何您都在使用uint8 / 16 / 32_t,对吗?:-)现在,所有整数类型都应该相当快,其中32位(int)是最快的。您可能没有FPU,因此请继续避免浮动和加倍。

首先,努力了解系统级体系结构。这意味着IO,时钟,存储器,复位和中断。同样,您需要习惯于内存映射外设的想法。在AVR上,您可以避免考虑这一点,因为寄存器具有唯一的名称,并为其定义了唯一的全局变量。在更复杂的系统上,通常通过基地址和偏移量来引用寄存器。一切归结为指针运算。如果您对指针不满意,请立即开始学习。

对于IO,请弄清楚如何处理外围设备复用。是否有中央多路复用器控件来选择哪些引脚是外设信号以及哪些是GPIO?还是使用外设寄存器将引脚设置为外设模式?当然,您将需要知道如何将GPIO配置为输入和输出,并启用漏极开路模式和上拉/下拉功能。外部中断通常也属于此类。GPIO非常通用,因此您的经验将在这里为您服务。

时钟归结为几件事。您从时钟源开始,通常是晶体或内部RC振荡器。这用于创建一个或多个系统级时钟域。高速芯片将使用PLL,您可以将其视为倍频器。在各个点上还将有时钟分频器。他们要考虑的关键因素是您的CPU时钟频率应该是多少,以及通信外围设备所需的比特率。通常这是非常灵活的。当您变得更高级时,您可以了解诸如低功耗模式之类的东西,这些通常基于时钟门控。

内存表示闪存和RAM。如果您有足够的RAM,那么在早期开发期间将程序保存在其中通常会更快,因此您不必一遍又一遍地编程闪存。这里最大的问题是内存管理。您的供应商应提供示例链接脚本,但您可能需要根据程序的性质为代码,常量,全局变量或堆栈分配更多的内存。更高级的主题包括代码安全性和运行时闪存编程。

重置非常简单。通常,您只需要注意看门狗定时器,就可以在默认情况下启用它。一遍又一遍地运行相同的代码时,重置在调试过程中更为重要。这样容易由于序列问题而遗漏错误。

关于中断,您需要了解两件事-如何启用和禁用中断以及如何配置中断向量。AVR-GCC使用ISR()宏为您完成后者,但是在其他体系结构上,您可能必须手动将功能地址写入寄存器。

微控制器外围设备通常彼此独立,因此您可以一次学习它们。选择一个外设并使用它来学习系统级内容的一部分可能会有所帮助。Comm外设和PWM适用于时钟和IO,定时器适用于中断。

不要被复杂性所吓倒。这些“基本”微控制器已经教会了您很多需要了解的知识。如果您需要我澄清任何事情,请告诉我。


4
好答案。需要注意的另一件事是DMA外设,以我的经验,这些外设往往具有复杂且文档不足的接口。
Doug McClean 2015年

3
“现在所有整数类型都应该同样快。” 实际上,由于C语言中的整数提升规则,使用8/16位类型可能会导致很多符号/零扩展,并且在Flash内存不足时可能会出现问题。因此,如果有可用的RAM,使用更多的32位类型或至少对堆栈变量更喜欢int/ int_leastN_T类型可能会有所回报。
user694733

我的评论有误。我的意思是; 使用int_fastN_t类型,而不是int_leastN_t类型。
user694733 2015年

@ user694733:我希望C标准允许代码要求一个整数,该整数占用内存中的给定大小并且可以对特定范围内的值进行操作,但是当超出该范围时具有宽松指定的语义。在ARM之类的设备上,an int16_t通常与int32_t存储在内存中的值一样快,但是该标准要求在int17位或更大的平台上,int16_t x=32767; x+=2;必须将其设置x为-32767,即使代码会永远不要利用包装行为。
超级猫

@supercat C标准仅要求对无符号类型进行包装。对于带符号类型,由于可能的表示形式不同,所以任何包装都是UB。因此,对于x+=2,将指令用于16位类型将是合法的,因为编译器可能会假定该值将不会包装,因此使用它不会改变可观察的行为。但是我认为 ARM没有16位ADD指令可以实现这一点。(我可能是错的,我对ARM指令集的了解并不那么好。)
user694733 2015年

8

请记住,ARM拥有微处理器的知识产权,但实际上并不构成零件,这很有用。取而代之的是,制造商许可使用各种ARM处理器版本,并通过功能和外围设备的单独混合来生产自己的独特部件。

话虽这么说,如果您是该体系结构的新手,那么从ARM的文档开始,这实际上是所有此类微处理器的基础文档,可能很有意义。

例如,在ARM网站上描述了Cortex-M0 。

还有一本与ARM相关的书籍清单,可满足各种各样的需求和兴趣。

最后,还有特定制造商的数据表。对于M0,赛普拉斯,恩智浦和意法半导体只是众多基于Cortex-M0的实际零件制造商中的三个。

(不,我从不为ARM工作,也从未如此。)


1
这是一个非常通用的答案,除了链接到某些Cortex-M0文档之外,别无他法,我相信OP可以自己找到。
杰·卡尔森

1
它直接解决了寻求整体文档帮助的问题。这个答案直接回答了需要,并解释了为什么事情如此。
爱德华

8

一个很大的区别是使用供应商提供的库。对于PIC,Atmel等,大多数开发人员并未使用基本的库(用于gpio,计时器,ADC等)。根据我的经验,在编写自己的代码时,人们(最多)会使用它们作为指导。

但是,对于ARM,几乎总是使用这些库。建议制造商遵循一个标准“ CMSIS”。大多数都做。它有助于代码的可移植性(在不同的ARM之间和制造商之间),并提供了一种“标准化”的方法来构造代码。人们习惯于看到和理解库的功能。

当然,有一些开发人员可以直接访问寄存器,但是它们是异常值:)

为了回答您的问题,我发现通读图书馆文档非常有帮助。ST拥有完善的代码,并带有由Doxygen创建的大型帮助文件。您可以查看每个硬件模块的所有选项。

以GPIO为例,初始化函数处理:

  • 方向(向内或向外)
  • 上拉/下拉
  • 开集/推挽
  • 摆率
  • 等等

通过查看选项,您可以看到可能的结果。并且,当然,您将学习如何将这些选项传递给Init函数!

好的,现在我已经说过了,我看到您的特定ARM没有兼容CMSIS的库。相反,他们可以下载其专有的SDK。我将开始寻找他们的SDK文档。

如果您不喜欢该特定产品,那么我建议您选择其他具有更多兼容库的供应商。无论如何,您都将攀登学习曲线,因此也可能使您的投资更具可移植性...

ARM很有趣!我没有回头。


“对于PIC,Atmels等,大多数开发人员并没有太多使用这些库。” 不知道从哪里来。我只使用了PIC,而没有使用AVR,但是肯定不想编写自己的库,例如,用于USB主机接口,TCP堆栈或SD卡文件系统。Microchip的所有这些库似乎都足够。
tcrosley15年

啊,@ tcrosley,您绝对正确。我只想参考基本外围设备所涵盖的功能:gpio,计时器,ADC等
。– bitsmack

我同意,我通常直接访问GPIO,计时器,时钟和UART R / W。有时使用它们的库调用来进行I2C,SPI,ADC和UART设置,但并非总是如此。大量寄存器,无论您使用的是PIC(尤其是PIC32)还是ARM。
tcrosley15年

我认为此答案是针对该问题列出的最实用的答案,即使它不适用于OP的特定控制器也是如此。我认为您可以在不了解AHB或NVIC的情况下做很多出色的嵌入式工程。
杰·卡尔森

@JayCarlson谢谢!您对此答案的修改已被拒绝,因为我们不应该对他人的帖子进行如此重大的更改。但这确实是个很好的信息!我建议您将其发布为您自己的答案,这样可以对人们有所帮助,也可以提高投票资格:)
bitsmack '16

5

是搬家的好时机;8位快死了;当您以5美元的价格购买带有STM32F103的板卡时,STM32F103是功能强大的32位ARM微控制器(甚至带有USB!),毫无疑问,时代已经改变了。

您已经有了一些很好的答案,但是主要是我要说“忘记组装”,几乎要说“忘记关心cpu的工作原理”-有一天,您将需要深入研究(特定的优化或用于调试),但ARM内核(根据设计)运行C代码的表现异常出色,并且您很少需要深入研究内胆。

这确实意味着您将花费一定的时间来应对编译器(尤其是链接器和makefile)的问题,以掩盖您的晦涩错误,但它们都是可以克服的。

直到您真正需要优化的那一天,关于ARM的工作原理(即ARM cpu书籍)的内容都很繁琐,并且并不十分有趣(而且您会惊讶地发现,拥有32位寄存器和PLL的情况很少见) d CPU时钟在100MHz的范围内。

“拆弹” ARM指令集比起更新的“ Thumb2”(在大多数现代微控制器级ARM(Cortex)上可以找到)更容易阅读反汇编代码,但同样也体现了汇编语言指令的内在特性。大部分消失在背景中;如果您拥有正确的工具集(尤其是带有断点/单个步骤等的体面的源代码级调试器),则根本就不必担心它是ARM。

一旦进入了32位寄存器和32位数据总线宽度的世界,而您想在片上获得的所有东西,您就再也不需要回到8位CPU了。基本上,“轻松”和编写代码比提高效率更易读常常没有任何惩罚。

但是...外围设备...是的,还有麻烦。

您肯定会在现代MCU上玩很多东西,其中很多都是花哨的东西。您经常会发现复杂的世界,远远超出了AVR,PIC和8051片上外围设备。

一个可编程计时器?不,有八个!DMA?12个具有可编程优先级和突发模式,链接模式以及自动重载和.. and .. and ...的通道怎么样

I2C?I2S?数十个引脚混合选项?重新编程片上闪存的十五种不同方式?当然!

通常感觉就像您从饥荒过渡到外围设备的盛宴一样,通常您会欣赏整块芯片,但却很少使用(因此,时钟门控)。

如今,片上硬件的数量(以及仅一个供应商的芯片产品线的变化)就令人难以置信。一个芯片供应商当然会倾向于重复使用IP块,因此,一旦您熟悉某个品牌,它就会变得更容易,但是“如今做起来很疯狂”。

如果外围设备及其交互(以及DMA和中断,总线分配以及and ...)非常复杂(有时,与数据表中所描述的不完全一样),那么工程师经常会选择最喜欢的ARM MCU和倾向于仅仅因为他们熟悉外围设备和开发工具而坚持使用它。

良好的库和开发工具(即使用适当的调试器进行快速的编译+调试周期)和大量可运行的示例代码项目对于当今选择ARM MCU绝对至关重要。似乎大多数供应商现在都拥有极其便宜的评估板(

正如我确定的那样,一旦您超越了ARM的微控制器级别并进入SOC级别(例如Raspberry Pi / etc风格的SOC),规则就会完全改变,这一切与您要使用的Linux类型有关跑,因为 - 有难以察觉的例外 - 你会吠叫疯狂尝试别的。

基本上; 无论在这次演出中为您预先选择的CPU是多少(可能),请从几个不同的供应商(TI,STM,Freescale等公司)中购买一些基于超便宜Cortex的评估板,并且对提供的示例代码有所了解。

最后的建议;一旦在数据表中找到第3页或第3页,该页描述了您正在使用的确切零件号芯片的引脚混合选项,您可能需要将其打印出来并粘贴在墙上。在一个项目的后期发现,由于引脚混合无法实现某种外围设备的组合是没有意思的,有时信息被掩埋了,您发誓他们会试图隐藏它:-)


一个快速的附录-如果您的项目远不只是最简单的控制器,请考虑使用RTOS-您选择的内容都有一定的学习曲线,但即使是最小的ARM,如今也可以运行多线程OS。我个人发现ChibiOS是具有精益功能的完美结合(特别是在STM32上运行,它带有一个不错的外设库),但是有很多选择。
理查德·阿普林

4

我也来自AVR,现在通常坚持使用STM32(Cortex-M)。这是我对初学者的建议,并反映了我刚开始时遇到的困难:

  1. 获得带有调试器或至少一个JTAG连接器的电路板(然后购买JTAG调试器)。周围有很多便宜的东西,使用它可以节省很多时间。

  2. 获得包含所有内容的良好IDE。我很久以前就推荐过CooCox CoIDE。从那时起,它停止并重新开始了开发,所以我不确定现在情况如何。“良好的IDE”使您可以立即使基本的Hello World LED闪烁。

  3. “一个好的IDE”应设置制造商的CMSIS标头。基本上,这是寄存器映射,可以更轻松地编写C / C ++程序,并使用变量名代替纯数字和指针。

  4. 如果您不需要绝对最佳的性能,请尝试使用制造商的外围设备库。实际上,由于您正在学习,您现在暂时不这样做。如果以后发现您需要进一步压缩,请查看库代码以了解其作用。关于库的好处还在于,它们通常允许您使用同一制造商的许多不同芯片且具有相同的代码。

  5. 与AVR不同,ARM芯片从禁用外设开始。您需要先启用它们。一个好的外围设备库将提供有关如何正确使用外围设备的示例,您可以从该设备的数据表中获取更多信息。因此,请记住在使用时钟和外设之前先启用它们。是的,即使I / O端口也被视为外设。

  6. 在学习时编写代码。不要试图一次完成所有操作,因为这确实很复杂。我将从学习时钟树(APB,AHB等总线)以及时钟和时钟分频器如何交互开始。然后,我将查看IDE在何处存储设备的链接程序脚本启动代码。链接描述文件几乎就是您组织内存(RAM,闪存,ISR向量表等)的方式。启动脚本会设置您的程序(诸如将全局变量初始化器从闪存复制到RAM之类的东西)。有些IDE在ASM中具有启动脚本,而有些在C中具有启动脚本。有时,您可以使用自己喜欢的语言通过Google编写另一个脚本。

  7. 尽快使调试器运行。一开始会犯一个错误,通常会以与您应该执行的顺序不同的顺序执行某些操作(通常是硬件初始化)。有时,这会触发一个ISR异常,使您陷入while(1);无限循环(该ISR的默认实现),从而终止程序,即使使用调试器也难以跟踪。想象一下没有调试器的情况。

  8. 说到调试器,请尝试使UART也运行,然后使用串行USB适配器读取该信息。printf()调试总是有用的:-)


3

我在8051,AVR或PIC上工作不多。但是最近,我开始研究ARM Cortex MX系列处理器。因此,对于从8051,AVR或PIC过渡的内容,我知之甚少,但主要还是从初学者的角度。

ARM®Cortex™-M4处理器基于哈佛架构,因此具有独立的数据和指令总线。以下是高级图片。

在此处输入图片说明

本周恩智浦代表将参观我们的工厂。我将与他们一起检查是否有NXP ARM-Cortex Mx资源,并将其发布在此处。飞思卡尔具有基于ARM®Cortex®-M内核的Kinetis低功耗32位微控制器(MCU),据我了解,它们也具有学习ARM处理器的类似指南。不幸的是我还没有研究它们。


参考文献:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.