在低功耗多核微控制器中使用全局变量是不是很糟糕? (C ++)

时间:2015-02-01 15:46:43

标签: c++ global-variables microcontroller multicore

我有一个Parallax螺旋桨,它是一个8核微控制器,时钟频率为80MHz(即它比Arduino好很多但并不令人惊讶)。

我需要在我的代码中访问一些变量 - 俯仰和滚动角度,等等(所有浮点数)。我的目的是将它们声明为外部易失性 - 全局设置在一个类中,并且在其他地方读取(易失性存在,因为它是多核的)(extern)因为班级在一个单独的文件中。)

这是不好的做法吗?我试图避免使用函数调用它们,因为这只会减慢速度 - 所有变量都存储在主ram中,所以它们放在那里的方式并不重要。有更好的方法吗?

假设最好使用函数调用它们,这将如何完成?

4 个答案:

答案 0 :(得分:2)

volatile保证编译器不会优化对变量的访问" (经典的例子是:

 bool b = false;

 while(!b) /* do nothing */;
编译器转向的

 bool b = false;

 bool tmp = !b;         // tmp is really a processor register.
 while(tmp) /* do nothing */;

由于循环中没有任何内容正在发生变化b,因此它是编译器执行此操作的有效优化。

使用volatile bool b;可确保您每次使用"在代码中b,编译器读取/写入实际变量,而不是某些"临时副本"。

但是,volatile不保证:

  1. 数据以原子方式更新 - 换句话说,如果您存储某些内容,可能会存储一半的新数据,而另一半则是旧值,导致各种有趣的"结果[例如float]中的随机值。

  2. 其他cpu的缓存知道值已经改变了 - 换句话说,一个CPU读取的值可能已经在另一个CPU上更新了一段时间 - 比如b在上面的代码中 - despit volatile,CPU很可能不会在另一个CPU的缓存上引起冲洗。

  3. 您需要处理缓存和原子更新,以确保您不会感到有趣"任何一个没有正确完成的错误。无论您是使用全局变量还是以其他方式在处理器之间共享数据,这当然都适用 - 您可以依赖它的唯一情况是您通过操作系统或运行时环境获得适当的接口,这为这些事情提供了保证。

答案 1 :(得分:1)

对于热门话题:不,在微控制器中使用全局变量并不一定是坏事。 Propeller是否是“低功耗”是有争议的,但如果我没记错,它既没有浮点也没有功能来进行多字原子访问。无论是否需要,其中的任何内核都具有主存储器访问周期的1/8。

您描述了在一组全局变量中存储态度。如果每个单词都可以独立更新并且用一个原子操作编写(我相信螺旋桨有32位RAM和处理器),你可以忽略同步,但是如果需要关联你想要的测量使用某种障碍或锁定。 Propeller设计为通过具有可预测的时序而无锁地运行,但这基本上仅适用于循环计数装配程序员;它根本不会帮助你使用C ++。

Propeller确实有hardware locks,通过一组毫无意义的笨拙且有限的测试和设置原语来实现。如果您设法理解它们Spin documentation,您可以使用它们(因为数据表和GCC文档都没有涵盖它们的语义)。

这个控制器比Arduino“好多了”?我不会说这是给定的。它只有原始定时器和视频生成外设(其他任何东西都是用软件完成的),每个指令的处理器需要4个周期,而AVR的典型值只有一个或两个,你可以很容易地得到一个基于Cortex M4F的微控制器。浮点。

答案 2 :(得分:1)

问题继承自多线程应用程序,即两个或多个线程可以并行访问(读取或写入)一个变量。在这种情况下,同步是最重要的方面之一。您使用的技术(锁定,原子操作,信号量等)都是相同的,您可以避免变量的不一致(即在读取操作期间,其他线程会写入变量)。

因此,如果您使用外部全局变量,则所有外部模块都可以直接访问此变量不同步。当然,实现指定模块的开发人员可以使用原子操作(或其他解决方案),但这取决于他或她的注意力,并且同步的责任归于访问全局变量的所有外部模块,这是一个糟糕的方法和(如果可能的话)你必须避免。

作为大多数多线程系统的解决方案,所有可以直接访问变量的方法都必须在同一个模块中实现。这个解决方案的好处:

  • 这些方法可以使用通用同步解决方案,因此可以解决变量的并行和同步访问。

  • 通常一个模块由一个开发人员实现,因此同步错误也会减少。

  • 其他模块(和其他开发人员)将获得一个明确指定的同步接口来访问公共资源(全局变量)。

因此,外部模块只能通过接口方法访问这些全局变量。当然在这种情况下会出现一些无关紧要的调用开销,但是如果你想避免它并使代码更有效,你可以将这些接口方法声明为内联方法

答案 3 :(得分:0)

螺旋桨上的gcc或C命令最多只是一个黑客攻击多核功能和东西被抛出来使C可用。因此,虽然说C标准这个或那个或者全球性的宗教辩论是一回事是一回事,但是那个平台上的C的实现可能会或可能不符合任何所述标准。

我同意另一个人如果按照设计使用螺旋桨有一些有趣的功能,但arduino更清洁,几乎任何东西。如果你真的想要硬件多线程与XMOS一起使用,它有自己的C实现的功能,非常酷的硬件,如风格/设计,但不像功耗一样酷。螺旋桨是一个整洁的玩具,如果你扔C并按照设计使用它,一旦你使用C,你就会瘫痪它并把它变成一个非常微弱的微控制器,几乎所有其他竞争对手在这一点上都更好。当我终于买了一个并且看着窗帘后,我感到非常失望。

除非它们是一个实现问题,否则可以使用全局变量并使用volatile来获取代码以共享该全局变量。可能会在一些人的口中留下不好的味道,但根据规格它应该有用。