sdcc man阅读笔记(三)——c51专用编译选项
一、C51专用编译选项
1.1 C标准
sdcc提供c89 c99 c11的三种标准,编译选项分别是
1 | --std-c89 |
据说用c99,如果函数没有形参编译就不能通过,不能默认为void。在写for函数的时候,不能在第一分句里申明变量,必须提前申明。—std-sdcc99是默认的编译选项,在使用c99规范的时候,兼容c89规范,真方便。
anyway,我觉得很少有人会使用这个编译选项。
1.2 芯片系列
sdcc提供很多种芯片系列的选择,粗略看了一下有pic16bit,飞思卡尔,z80等等。如果是51系列的话,编译选项是-mmcs511
-mmcs51
1.3 存储模式
ssdc提供的memory model选项有这么几个
1 | --model-small |
small模式,对应keil的SMALL模式,变量默认存在internal ram中,该模式需要变量总占用的空间小于256bit。
medium模式,对应keil的COMPACT模式,变量默认存在external ram中。需要注意的是,有些51单片机本身就有内部的扩展ram,为了与旧单片机相兼容,这些内部扩展ram在名义上也算是一种外部ram。
large和huge模式是一样的,变量也存在external ram中,不同的是,它可以切换bank。由于c51的最大寻址范围也就是FFFFH,即64K。所以如果要扩展64K以上的ram只能用bank切换的办法。bank切换办法是用一个特殊寄存器来切换bank,将LSB存在r0,MSB存在r1,bank号存在r2。然后用 __sdcc_banked_call来调用位于其他bank的函数,再用__sdcc_banked_ret返回当前函数。
1.4 堆栈
1 | --xstack |
可以用xstack选项指定external ram的一段空间作为栈区(通常是前256个字节),这样所有的可重入函数的变量和参数传递都会用堆栈来实现。通常默认的栈空间是在internal ram的后区。
1.5 size检查
sdcc提供一些size选项来检查存储控件的使用情况
1 | --iram-size <Value> |
iram-size 用来检查片内ram的使用情况
xram-size 用来检查外部ram的使用情况
code-size 用来检查rom的使用情况
stack-size 用来检查堆栈的使用情况
1.6 寄存器优化开关
1 | --pack-iram |
—pack-iram是默认选项,意思是将多余的寄存器用来存放变量,以加快运行速度。因为这是一种通俗的做法,所以—no-pack-iram选项几乎很少使用,编译器的作者说下一版将移除这个选项。如果想不让编译器优化某个变量的访问,直接使用volatile关键字就可以了。假如担心一个全局变量会被中断程序或者其他线程修改,那么声明它为volatile就可以了,编译器会让该变量在每次访问时都重新从内存读取。
1.7 汇编优化
1 | --acall-ajmp |
—acall-ajmp选项用来将3字节的汇编指令lcall/ljpm替换成2字节的指令acall-ajmp,这就要求代码总占用空间限制在2K以内。
我很好奇这个选项的使用场景,于是在github上搜索了一下,发现它通常用于一些微型的bootloader。
1 | --no-ret-without-call |
—no-ret-without-call 用于xc800系列的单片机,用于保持堆栈平衡。
总结
- sdcc用-mmcs51来指定单片机为51系列
- sdcc有与keil相同的memory model
- 可以用编译选项告诉编译器程序使用外部ram里的堆栈
- 可以用编译选项检查各存储空间的占用情况