编写固件:汇编还是高级?

相关:

  • 测试固件
  • 启动微控制器模拟器/仿真器
  • 解释汇编代码

如果您正在为微控制器编写代码,那么如果您使用汇编语言或C语言或其他高级语言编写,会有真正的区别吗? 如果您编写C代码,您将如何编译它?

谢谢

几条评论:

1)绝对不是assembly,除非性能或优化限制保证。 以下指标通过汇编进入屋顶:

  • 是时候编码了
  • 时间来调试它
  • 时间来测试它
  • 记录它的时间
  • 是时候弄清楚(1年后)你编码的时候你在做什么
  • 犯错的可能性

2)我的首选项是C ++而不是C,因为它的命名空间封装和它促进了编译时面向对象的实践。 C对全局变量和命名空间冲突有太多机会。 (实时Java会很好,但据我所知,它的要求仍然很高)

或者更确切地说是C ++的一个子集:排除exception,虚函数,运行时类型识别,以及大多数情况下的动态内存分配 – 基本上是在编译时未指定的任何内容,因为在运行时通常需要大量额外资源。 这是C ++的“臃肿”。

我已经使用TI和IAR的C ++编译器,分别用于TMS320和MSP430微控制器,并且通过适当的优化设置,它们可以很好地减少您对C ++的开销。 (特别是如果你通过明智地使用inline关键字来帮助它)

我甚至使用模板来获得一些编译时的好处,这些好处可以促进良好的代码重用:例如,编写单个源代码文件来处理8位,16位和32位CRC; 和编译时多态 ,允许您指定类的通常行为,然后重用它,但覆盖它的一些function。 同样,TI编译器具有极低的开销,并具有适当的优化设置。

我一直在寻找Microchip PIC的C ++编译器; 我找到的唯一一家生产IAR的公司就是IAR。 ($$$一直是个障碍,但我希望有时会买一份)Microchip C18 / C30编译器非常好,但它们是C,而不是C ++。

3)关于编译器优化的一个具体警告:它可以/将使调试变得非常困难; 通常不可能单步执行优化的C / C ++代码,并且您的监视窗口可能会显示与您认为应该包含未优化代码的内容无关的变量。 (一个好的调试器会警告你一个特定的变量已经优化不存在或者进入寄存器而不是内存位置。很多调试器都没有。> 🙁

另外一个好的编译器可以让你通过#pragmas在function级别选择/选择优化。 我使用过的只允许您在文件级别指定优化。

4)将C代码连接到汇编:这通常很困难。 最简单的方法是创建一个具有所需签名的存根函数,例如uint16_t foo(uint16_t a, uint32_t b) {return 0; } uint16_t foo(uint16_t a, uint32_t b) {return 0; } ,其中uint16_t = unsigned short,我们通常将#位显式化。 然后编译它并编辑它生成的程序集(只需确保保留代码的开始/退出部分)并注意不要在完成之后删除任何寄存器而不进行恢复。

内联汇编通常会遇到问题,除非您正在执行一些非常简单的操作,例如启用/禁用中断。

我最喜欢的方法是编译器内在函数/“扩展ASM”语法。 Microchip的C编译器基于GNU C编译器,它具有“ 扩展ASM ”,允许您对内联汇编的位进行编码,但是您可以给它提供大量提示,告诉它您正在引用哪些寄存器/变量,它将处理所有的保存/恢复寄存器以确保您的汇编代码与C一起“很好”.TI的TMS320 DSP编译器不支持这些; 它确实有一组有限的内在函数,它们有一些用处。

我已经使用汇编来优化一些经常执行的控制循环代码,或者计算sin(),cos()和arctan()。 但是否则我会远离集会并坚持使用高级语言。

大多数微控制器制造商都提供某种交叉编译器,您可以在PC上编译代码然后将其传输到微控制器。

为何选择C?
C的一个优点是您的代码将来更容易移植到其他微控制器。 计算历史表明,代码通常比硬件实现更耐用。
第二个优点是控制结构(if,for,while)使代码更易读和可维护。

为什么汇编语言?
您可以手工优化。

判决书
与这类问题的情况一样,权衡取决于具体用途。
请注意,通常可以通过在C代码中进行汇编调用来混合这两者,这样您就可以找到适合您项目的余额。

特定于PIC硬件
您似乎没有大多数PIC硬件的GCC选项。 另一方面,作为评论者注意到,16位PIC24和dsPIC33的Microchip C30编译器是gcc。
SDCC尚不支持PIC。
新信息:根据评论,SDCC对PIC有可行的支持。
还有其他一些开源选项 ,但我没有使用它们的经验。

最好的选择可能是用C编写代码,然后对于需要手动优化并且可以比编译器做得更好的极少数实例,您应该将程序集编码到c文件中。

对于PC来说,汇编编码已成为过去,但在嵌入式编码中非常重要。

在嵌入式中编写程序集与在PC上编写程序集不同。 PC编译器在生成优化指令时“比人类更好”。 嵌入式系统通常具有奇怪的架构,其优化编译器并不像PC优化编译器那样成熟。

我在为微控制器编写程序集时遇到的一个问题是需要非常小心地编写代码。 有一个跳转表跨越内存边界,并导致您的代码跳转到非常奇怪的地方是相当令人不安的。 在C语言编码中,编译器为您提供了基础。

我肯定会选择C.它更快,它创造了更可靠的软件。 大会几乎没有提供,在稀缺的场合。 请记住在C:

  • 您可以轻松地从现有平台移植代码,甚至可以从PC移植代码。
  • 您可以使用高级语言进行开发,而不会影响执行速度或代码大小。 如果可以使用高质量的编译器(PIC18有很多选择),那么使用C语言时,这些编译器可能比手工制作的组件更好。
  • 调试,测试和维护代码要容易得多。 C生成更可靠的代码。

另一件事与PIC18有关。 您不必处理非直观的PIC架构和内存BANK等问题。

我以前在8051的IAR C编译器方面有很好的经验。

我最近的方法一直是: –

使用良好的优化编译器将其写入C,并且只有在大小或速度有问题时,才考虑在汇编程序中重写某些部分。

但是,由于采用这种方法,我从来不需要编写一行汇编程序……

去找c!

我曾为一家大型CE制造商工作过。 上次我看到汇编是在1996年左右的一些小型中断服务程序中用于RC5和RC6解码和电视调谐算法。 之后总是使用c和C ++(只使用类,没有stl,exception或rtti)。 我对8051的旧KEIL编译器以及greenhills编译器(MIPS)和VxWorks工具集(基于PowerPC)有很好的经验。

正如Roddy所说,首先用C语言编写,然后稍后优化组装(如果需要)。

在许多情况下,assembly可以更快; 当你在桌面上时,编译器往往被优化到手工assembly很少是必需的程度,但在uC世界中,它往往是。 此外,如果您需要编写中断处理例程和类似的东西,您通常无法在C中执行此操作。

至于编译,谷歌周围为你的目标的C编译器。

绝对是C,除了

  • 程序存储器非常有限。 在经过精心设计的汇编程序代码后,您可以设法在这个1024字节的Flash中使用您的程序,剩下0个字节。 在这种情况下,没有C编译器会有任何好处。

  • 你想要有绝对时间控制。 如果任何数量的中断延迟太长,您将不得不依赖汇编程序。

现在的问题是嵌入式可以是任何东西,从具有6个引脚和几个字节RAM的ATTiny到运行嵌入式操作系统的多核SBC,这会让一些人的桌面计算机感到羞耻。

因此,语言/开发环境的选择需要考虑您需要的效率与系统的复杂程度。

首先 – C在任何地方都可以工作并且可以很好地扩展,越高,你就会越多地调用外部库等来处理复杂性。

对于非常小的微型(测量flash / ram,以字节为单位),最好使用ASM,当你达到kb范围时,可以使用C或任何其他传统语言,因为你不需要计算每个字节。 一旦你有兆字节可以玩,你就有能力并且越来越有可能要求使用RTOS来处理所有事情并缩短开发时间。 当你拥有硬件时,你可以运行一个完整的操作系统,你可以从硬件中抽象自己,只需在像Java这样的填充单元格中编写所有东西,而不必过多担心这一切是多么浪费,以及你是如何不再是一个真正的程序员…;)

上述情况的例外情况是,当您需要从硬件中获取的所有性能时,您可能需要降低一到两个级别才能保持高效。

还有一次可能需要在汇编中进行写入:如果需要进行低级RAM测试或类似操作,则需要绝对控制数据的存储位置。

例如,确认SIL -2(安全完整性等级)及以上的软件可能需要对RAM进行连续检查,以便检测任何可能的数据损坏。 您正在检查的RAM区域在检查时无法更改,因此在汇编程序中编写测试可以确保这是真的,例如将任何局部变量存储在特定寄存器或RAM的另一个区域中。 如果不是不可能的话,在C中这将是困难的。

尽管提供了这种类型的代码,但也可以用汇编程序为同一写入的内容写入使RAM归零并初始化非零静态变量的启动代码。

如果您编写的代码高度依赖于特定于设备的外设,并且您使用的工具链无法提供必要的内在函数来有效地利用它们(如蹩脚的Freescale DSP563CC编译器),那么请使用汇编。

除此之外,我认为使用汇编语言与高级语言的不成文规则与桌面软件开发的规则大致相同:保持代码清洁,可维护,并使用机器语言优化热代码。

这是底线,如果你使用C你可以稍后进行优化,我不会使用除C或汇编程序之外的任何东西(没有C ++等)。

关键是微控制器指令集,如果你使用的是PIC,甚至是8051我只使用汇编程序。 如果它是一个编译器友好的像arm或avr或msp430然后使用C来保存一些键入,但你可能会因为各种原因在汇编程序中有一些例程。 同样地,你可能想要避免使用C库,即使newlib也可能过于笨重,从它们那里借用代码或想法,但不要只链接一个。哦,回到问题,看看C编译器可用于目标,再次胳膊和avr你不会有任何问题。 可能msp也没问题。 仅仅因为Keil或Iar会卖给你一个编译器并不意味着你应该买它或使用它,付费和免费编译器的输出可能是可怕的。 无论如何你需要精通asm并检查输出(你可能必须写一个反汇编来做这个)。

底线(另一个底线),没有全局答案(完全避免任何高于C的全局答案)它总是取决于平台是什么,你的资源是什么,你的任务是什么,性能要求是什么,便携性要求是(如果它真的嵌入在微控制器上,大部分都是定义不可移植的)编译器,调试器,jtag等是可用的,即使你正在开发的主机操作系统可能是一个重要因素。

到目前为止,没有人提到Forth或Scheme太糟糕了。 两者都适用于小型环境,可以提高生产效率。

普通C或Pascal,Modula2。 但由于编译器的可用性,这意味着C.

由于动态分配和程序大小通常非常有限,因此C ++和类似物的额外function仅仅是出于风格的考虑。

如果您的应用程序变得紧张,更复杂的运行时也会很麻烦。

汇编程序也很有用,但只有当你卖出非常大的数量时,较小的固件意味着更小,更便宜的芯片(更少的闪存)并且程序的大小是可监督的(读:你有可能在时间上免费获得它)