预算图片的有限堆叠大小是一个问题区域,我已经调整了我的代码以适应这一现实。我目前采用了一种粗略的范例,将密切相关的函数分组到一个模块中,并在模块中声明所有变量全局静态(以减少存储在auto psect中的变量的数量,并且可变性问题只与ISR相关,我对此进行了说明)。我这样做并不是因为这是一个好的实践,但现实是,您有有限的空间来分配存在于整个项目中的所有本地函数变量。在8/16位芯片的嵌入式世界中,如果我确定采取必要的预防措施,这是一种合适的方法吗?我还做了一些事情,比如为以太网分配> 256字节的RAM (我知道标准MTU应该是1500字节,但我们有一个自定义的情况,RAM非常有限),并且必须通过指针访问那个内存,这样我就可以避免内存库的语义。我做错了吗?我的应用程序工作正常,但我对改进建议持100%的开放态度。C
发布于 2014-08-15 09:07:47
我知道这个问题是4年前提出的,但它仍然没有得到适当的回答。我相信OP问的是他们绕过HiTech PICC18 C编译器有效性和/或最佳实践的限制的方法。正如在后来的评论中提到的那样,这个限制(一个相当糟糕的限制,Hitech并没有很好地宣传)是“高科技编译器只允许256字节的自动变量”。实际上,限制比这更糟糕,因为局部变量和参数总共有256个字节。当超过这个值时,链接器警告也是相当隐秘的。如果函数位于调用树的不同分支上,则编译器可以重叠变量以重用空间。这意味着您可以有效地拥有超过256个字节。但请注意,中断处理程序(如果使用优先级方案,则为处理程序)有自己的调用树,共享256字节的local/param块。
本地变量减少本地变量所需空间的两种解决方案是:使本地变量成为全局变量或使其成为静态变量。将它们设为静态,可以保持作用域不变,并且假设函数不是从中断中调用的,这是安全的(无论如何,编译器都不允许可重入性)。这可能是首选选项。缺点是编译器不能重用这些变量的位置来减少整体内存消耗。将变量移动到全局作用域允许重用,但重用管理必须由程序员管理。也许最好的平衡是让简单的变量成为静态变量,但使像字符串缓冲区这样的大块内存成为全局的,并小心地重用它们。
在初始化时要小心。
foo()
{
int myvar = 5;
}必须更改为
foo()
{
static int myvar;
myvar = 5;
}参数如果您在参数中向调用树传递大量数据,您很快就会遇到同样的256字节限制。这里你最好的选择可能是传递一个指向全局分配的“.Alternatively”结构的指针。你可以拥有全局设置变量,这些变量由顶级调用者设置,并由树下的被调用者读取。这真的取决于软件的设计,哪种方法更好。
和OP一样,我也遇到过同样的问题,我认为从长远来看,最好的选择就是放弃使用Hitech编译器。编译器编写者采取的在一个块中分配所有局部变量/参数的优化决策仅真正适合于非常小的ram大小的PICS。对于较大的PICS,在达到设备的内存大小之前,就会耗尽local/param。然后你必须开始修改你的代码以适应编译器,这是不合理的。
总之..。是的,你的方法是有效的。但是,如果合适的话,请考虑简单地将局部变量设为静态变量,因为通常情况下,减小作用域会使代码更安全。
发布于 2013-08-14 02:59:32
虽然C18编译器使用了一些XC8 (指针)来管理数据堆栈,但听起来像是Microchip的新FSR编译器使用了已编译的堆栈,因此您应该确切地知道在编译时堆栈占用了多少空间。您还将确切地知道每个堆栈变量的存储位置。我在XC8 user's guide上读到了所有关于这方面的内容,听起来很棒。假设您使用的是XC8,那么这个特性应该会使这个问题变得毫无意义。
发布于 2010-11-04 21:14:46
我在内存有限的芯片上使用编译器/链接器的经验是,只要你不使用递归函数并将此告知编译器,那么编译器就非常有能力确定所需的最小堆栈空间。
我甚至见过编译器为每个自动存储的变量分配一个全局固定的地址(根本没有堆栈),其中几个变量被分配到重叠的内存中,只要它们的生命周期不重叠。
在进行(速度或空间)优化时,一般的建议是:进行测量,以证明您的优化确实有积极的效果。
https://stackoverflow.com/questions/4093695
复制相似问题