STVD中出现c 库函数数里面的东西提示没有定义,求助

进一步掌握STVD/COSMIC STM8应用笔记
进一步掌握STVD/COSMIC
以下资料由微雪电子整理并发布,未经许可不得转载,否则追究相应责任!
如何分配变量到指定的地址
unsigned char temp_A@0x00; //定义无符号变量temp_A,强制其地址为0x00
unsigned char temp_B@0x100; //定义无符号变量temp_B,强制其地址为0x100
@tiny unsigned char temp_C; //定义无符号变量temp_C,由编译器自动在地址小于0x100的RAM中为其分配一个地址
@near unsigned char temp_D; //定义无符号变量temp_D,由编译器自动在地址大于0xFF的RAM中为其分配一个地址
另外也可以采用伪指令&pragma&将函数或者变量定义到指定的section中,例如:
#pragma section [name] // 将下面定义的未初始化变量定义到.name section中
Unsigned char data1;
Unsigned int data2;
&&(任何需要定义在.name section中的变量)
#pragma section [] // 返回到正常的section.
注意:pragma伪指令可以用来定位函数,初始化变量或者未初始化变量。这三者用不同的括号区分。
(name):代码
[name] :未初始化变量
{name}:初始化变量
如何在COSMIC C文件中使用汇编语言
在COSMIC C文件中使用汇编语言常见的方法有如下两种:使用#asm &#endasm组合格式
或_asm(&&&); 单行格式。
unsigned char temp_A;
Void func1(void)
LD _temp_A,A
注:在C嵌汇编环境下使用全局变量,要在该全局变量名称前加下划线&_&。
Void func1(void)
_asm(&rim&);
_asm(&nop&);
如何观察RAM/FLASH/EEPROM的最终分配情况
在Project-&settings-&linker选项页中,将Category选为Output,再勾选Generate Map File。
点击OK按键后,再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug 目录下)生成 .map 文件。该文件详细地列出RAM/FLASH/EEPROM的分配使用情况。
如何生成hex格式的输出文件
在Project-&settings-&PostBuild选项页中,在commands栏内加入下行命令:
chex &fi -o $(OutputPath)$(TargetSName).hex $(OutputPath)$(TargetSName).sm8
再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug 目录下)生成 .hex 文件。
什么是MEMORY MODEL
STM8的C编译器支持多种存储器模式。用户可以根据应用的需要选择最适合的配置。可以根据需要选择采用2个字节的寻址方式(仅适用于64k以内的程序)或者3字节的寻址方式。也可以规定将变量默认为定义在存储器的哪一区域:zero page内,还是zero page 外。下面对几种供选择的MEMORY MODEL做简单说明。
在Project-&settings-&C Complier选项页中,将Category选为General,里面有一个Memory Models选项栏如下:
在下拉菜单中共有4种MEMORY MODEL可供选择:
程序地址空间在64K以内(即程序容量小于32K)
程序地址哦那个键在64K以上(即程序容量大于32K)
Stack Short
短堆栈模式
Stack Long
长堆栈模式
Stack Short
短堆栈模式
Stack Long
长堆栈模式
程序地址空间
程序所用到的地址空间在64K范围内
程序所用到的地址空间超出64K范围
指针默认类型
函数指针和数据指针默认为@near (2 bytes)
函数指针默认为@far(地址为3字节);
数据指针默认为@near
全局变量默认类型
所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义
所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义
所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义
所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义
.lkf 文件的作用
.lkf文件在程序链接时决定如何具体分配RAM/ROM的空间。在Project Settings & Linker & Category(Input)选项页中,当&Auto&选择框被选中时,由系统自动生成.LKF文件,否则由用户指定。
当&Auto&选择框被勾选时,.lkf文件会自动生成在项目主目录下的 debug/ 和 release/ 目录中。下面以上图所示 at45DBXX Project的 lkf 文件为例,来进一步理解.lkf 。
在.lkf中,以&#&开头的行是注释行,为方便用户理解,将原注释删除,代之以中文注释如下:
# 定义(+seg)一个常量段(.const),开始(b)于0x8080,最大分配(m)0x1ff80个字节(即不超过
# 0x27FFF),为该段起名(n)为.const(和常量段的保留字同名),需要初始化的变量的初始值存
# 放于此段(-it)
+seg .const -b 0x8080 -m 0x1ff80 -n .const -it
# 定义(+seg)一个程序段(.text),紧跟(-a)在.const段后面(和.const 共同位于0x8080 &
# 0x27FFF),为该段起名(n)为. text (和程序段的保留字同名)。
+seg .text -a .const -n .text
# 定义(+seg)一个EEPROM段(.eeprom),开始(b)于0x4000,最大分配(m)0x800个字节(即不超
#过0x47FF),为该段起名(n)为. eeprom (和EEPROM段的保留字同名)。
+seg .eeprom -b 0x4000 -m 0x800 -n .eeprom
# .bsct段服务于定义在0页(地址小于0x100)以内需要初始化的全局变量(如@tiny char a = 9;)
+seg .bsct -b 0x0 -m 0x100 -n .bsct
# .ubsct段服务于定义在0页(地址小于0x100)以内不需要初始化的全局变量(如@)
+seg .ubsct -a .bsct -n .ubsct
# .bit表示位域段,定义后即可在程序中使用_Bool变量(如_Bool c = 1;),-id表示该段需要初始化。
+seg .bit -a .ubsct -n .bit -id
# 这是ST7时代(STM8是基于ST7发展而来的)由于物理堆栈小,速度慢,使用内存来模拟堆栈的变通手段。
+seg .share -a .bit -n .share -is
# .data段服务于定义在0页(地址大于0xFF)以外需要初始化的全局变量(如@near char d = 8;)
+seg .data -b 0x100 -m 0x1300 -n .data
# .bss段服务于定义在0页(地址大于0xFF)以内不需要初始化的全局变量(如@)
+seg .bss -a .data -n .bss
# 段定义结束,下面放置的库及Obj文件中的变量、常量、程序就按照上面的规定进行分配。
#初始化程序
crtsi0.sm8
Debug\main.o
# 一些必要的cosmic库
libis0.sm8
# 重定义常量段,开始于0x8000,用于放置中断向量表(STM8硬件决定此位置)
# &k 用于程序冗余代码优化,详情可参考cosmic用户手册。
+seg .const -b 0x8000 &k
# 中断向量
Debug\stm8_interrupt_vector.o
#定义了三个变量,用于系统初始化
+def __endzp=@.ubsct # end of uninitialized zpage
+def __memory=@.bss # end of bss segment
+def __stack=0x17ff # 不同的芯片__stack内容不同,由系统自动生成
如何实现位操作
Cosmic C 编译器支持位变量的操作,可以将其定义成 _Bool类型。_Bool类型的变量只包含两种值true(1)或者false(0)。若将一个表达式赋值给_Bool变量,则编译器会将表达式与0做比较,然后将布尔值赋给_Bool变量。因此,任何整型或者表达式的值都可以赋给_Bool变量。但是,布尔变量不能定义位数组,只能定义成结构体或者联合。而且,_Bool变量会被打包成字节的形式。
编译器会将所有的全局_Bool变量打包成字节形式,存放在.bit section中。局部_Bool变量也会被打包成字节形式。但是_Bool类型的参数会被扩展成一个单字节。
具体的关于位变量的定义和使用可参考如下例子:
定义位变量:
使用位变量:
in_range = (value &= 10) && (value &= 20);
p_valid = /* p_valid is true if ptr not 0 */
if (p_valid && in_
在使用位变量时,若程序编译时提示如下错误:
#error clnk Debug\example.lkf:1 no default placement for segment .bit
The command: &clnk -l&C:\Program Files\COSMIC\CXSTM8_16K_4.2.10\Lib& -o Debug\example.sm8 -mDebug\example.map -sa Debug\example.lkf & has failed, the returned value is: 1
exit code=1.
实际上是由于,在项目中没有定义.bit section。可按照如下步骤,手工添加.bit section:
打开项目链接配置窗口:Project - Settings - Linker,选择 Input 目录项
在Zero page 或者 Ram 里面定义一个.bit section.
然后重新编译一下就可以了。
进一步掌握STVD/COSMIC查看: 4937|回复: 0
基于STVD+COSMIC编译过程中的几个常见问题
本文作者:milershao
很多人选用STVD+COSMIC做为stm8 系列MCU产品开发的IDE,在编译调试过程中常常遇到些问题。这里我稍加整理,分享几个硬件线路和软件语法以外的话题。抛砖引玉,细节请自行研究相关手册。 一、零页内存区出界溢出的问题。对于这个问题一般会提诸如bsct/ubsct size overflow……这个提示告知默认的零页区放不下现有全局变量或静态变量,导致溢出。这里的RAM零页数据区,即00-0xff区域。至于BSCT/UBSCT是什么意思在COSMIC 编译手册里有讲。关于各STM8芯片的存储分配请看数据手册里的MEMORY MAP.
上面截图来自于COSMIC 里的编译手册里的相关描述。
上面截图来自于STVD+COSMIC 编译环境的相关配置页面。 解决这个问题比较简洁的办法有两种:1、把大部分全局变量或静态变量前冠以@near, 保留部分使用频繁的数据在零页区;上面截图来自于COSMIC 里的编译手册里存储模式的相关描述。2、
在编译配置那里将堆栈模式改为长堆栈模式,数据默认放在0x100以上的区域,把需要放在0页区的变量前冠以@TINY。操作如下图所示。 二、数据存储区溢出话题。数据存储区溢出是指除了堆栈的以外的RAM空间不足以存放现有全局变量或静态变量。一般有诸如.DATA/.BSS size overflow的提示。 如下图,红色RAM空间存放各种全局变量或静态变量,灰色区用作堆栈。上面截图来自于STM8S参考手册里的相关描述。 假设现有变量数据不能压缩精简,那就尝试将堆栈区域压缩。比方将下图中的0x1ff改为0x2ff,具体改多少要结合你实际应用和芯片本身RAM空间大小,满足需求就好。当然如果RAM空间跟你实际需求相差甚远,自然得想别的办法了。
顺便提下,STM8的堆栈是向下生长的,或者是从高位地址往低位地址压入数据的。起始栈顶一般默认为RAM最大地址处。 三、一个跟程序代码编译优化有关的话题
ST官方也为STM8各系列提供了参考标准外设固件库,里面有大量的外设操作库函数。在利用库函数编程时,有时会发现并没有写几句代码,结果生成的目标文件很大,明显不太正常。这个可能在C Compiler的优化那个地方选择不合适,要打开SPLIT选项。
下面有两幅图,找了个简单例程测试下。main()里就一个GPIO读端口,外加TIM1 的默认设置函数和配置函数。
没打开SPLIT选项时,生成的程序代码为4965 Byte,打开SPLIT选项后生成的程序代码是548 Byte,二者的常量代码均为124 Byte。很明显,开与不开相差甚远。
上图是优化配置里的SPLIT项关闭时的情形。
上图是优化配置里的SPLIT项打开时的情形。 注:1、关于SPLIT选项的说明,COSMIC手册里有描述。2、开与不开SPLIT项的机器码文件大小差别也得看你具体调用的库函数和实际应用,并非总是跟上面的例子那样悬殊。 四、中断矢量文件话题。一般来说,不论你自己新建工程还是利用ST官方库的模板建立工程,项目里总会自动生成一个中断矢量文件 stm8_interrupt_vector.c。这里面其实就是放的一个常量表,即STM8芯片各个中断矢量的入口地址。
有的人希望使用自己的中端矢量名字,想把这个stm8_interrupt_vector.c拿掉,比方说改换为vector.c 。发现怎么改都不行。每次改完编译,stm8_interrupt_vector.c如幽灵般的又回来了。
其实,这里是可以修改的,但要LINKER 配置的那个地方同步修改,就像下方图示那样。好奇的话可以去试试。
另外,不建议在这个矢量文件里写中断函数或其它函数,不然有时可能会出现些让你找不着北的奇怪问题。 五、断言函数出错提示问题。
这个问题一般是刚接触STM8开发的人使用库过程中才遇到的。他把main.c里的void assert_failed(uint8_t* file, uint32_t line) 函数体删掉了导致的。一般出错时有如下提示:这个函数作什么用就不用解释了,建议你先不要急于删它。不想要时,就在stm8s_conf.h文件里把 #define USE_FULL_ASSERT
(1)注释后即可删除相关代码。
Powered by如何分配变量到指定的地址
unsigned char temp_A@0x00; //定义无符号变量temp_A,强制其地址为0x00
unsigned char temp_B@0x100; //定义无符号变量temp_B,强制其地址为0x100
@tiny unsigned char temp_C;
//定义无符号变量temp_C,由编译器自动在地址小于0x100的RAM中为其分配一个地址
@near unsigned char temp_D;
//定义无符号变量temp_D,由编译器自动在地址大于0xFF的RAM中为其分配一个地址
另外也可以采用伪指令"pragma"将函数或者变量定义到指定的section中,例如:
#pragma section [name] // 将下面定义的未初始化变量定义到.name section中
Unsigned char data1;
Unsigned int data2;
……(任何需要定义在.name section中的变量)
#pragma section [] // 返回到正常的section.
注意:pragma伪指令可以用来定位函数,初始化变量或者未初始化变量。这三者用不同的括号区分。
(name):代码
[name] :未初始化变量
{name}:初始化变量
如何在COSMIC
C文件中使用汇编语言在COSMIC C文件中使用汇编语言常见的方法有如下两种:使用#asm
…#endasm组合格式
或_asm("…"); 单行格式。
unsigned char temp_A;
Void func1(void)
LD _temp_A,A
注:在C嵌汇编环境下使用全局变量,要在该全局变量名称前加下划线"_"。
Void func1(void)
_asm("rim");
_asm("nop");
如何观察RAM/FLASH/EEPROM的最终分配情况
在Project-&settings-&linker选项页中,将Category选为Output,再勾选Generate
Map File。&&
点击OK按键后,再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug
目录下)生成 .map 文件。该文件详细地列出RAM/FLASH/EEPROM的分配使用情况。
如何生成hex格式的输出文件在Project-&settings-&PostBuild选项页中,在commands栏内加入下行命令:
chex &fi -o $(OutputPath)$(TargetSName).hex
$(OutputPath)$(TargetSName).sm8
再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug 目录下)生成 .hex
什么是MEMORY
MODELSTM8的C编译器支持多种存储器模式。用户可以根据应用的需要选择最适合的配置。可以根据需要选择采用2个字节的寻址方式(仅适用于64k以内的程序)或者3字节的寻址方式。也可以规定将变量默认为定义在存储器的哪一区域:zero
page内,还是zero page 外。下面对几种供选择的MEMORY MODEL做简单说明。
在Project-&settings-&C
Complier选项页中,将Category选为General,里面有一个Memory Models选项栏如下:
在下拉菜单中共有4种MEMORY MODEL可供选择:
程序地址空间在64K以内(即程序容量小于32K)
程序地址哦那个键在64K以上(即程序容量大于32K)
Stack Short
短堆栈模式
Stack Long
长堆栈模式
Stack Short
短堆栈模式
Stack Long
长堆栈模式
程序地址空间
程序所用到的地址空间在64K范围内
程序所用到的地址空间超出64K范围
指针默认类型
函数指针和数据指针默认为@near (2
函数指针默认为@far(地址为3字节);
数据指针默认为@near
全局变量默认类型
所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义
所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义
所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义
所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义
文件的作用.lkf文件在程序链接时决定如何具体分配RAM/ROM的空间。在Project
Settings & Linker &
Category(Input)选项页中,当"Auto"选择框被选中时,由系统自动生成.LKF文件,否则由用户指定。
&当"Auto"选择框被勾选时,.lkf文件会自动生成在项目主目录下的
debug/ 和 release/ 目录中。下面以上图所示 at45DBXX Project的 lkf 文件为例,来进一步理解.lkf
在.lkf中,以"#"开头的行是注释行,为方便用户理解,将原注释删除,代之以中文注释如下:
# 定义(+seg)一个常量段(.const),开始(b)于0x8080,最大分配(m)0x1ff80个字节(即不超过
# 0x27FFF),为该段起名(n)为.const(和常量段的保留字同名),需要初始化的变量的初始值存
# 放于此段(-it)
+seg .const -b 0x8080 -m 0x1ff80 -n .const -it
# 定义(+seg)一个程序段(.text),紧跟(-a)在.const段后面(和.const 共同位于0x8080 &
# 0x27FFF),为该段起名(n)为. text (和程序段的保留字同名)。
+seg .text -a .const -n .text
# 定义(+seg)一个EEPROM段(.eeprom),开始(b)于0x4000,最大分配(m)0x800个字节(即不超
#过0x47FF),为该段起名(n)为. eeprom (和EEPROM段的保留字同名)。
+seg .eeprom -b 0x4000 -m 0x800 -n .eeprom
# .bsct段服务于定义在0页(地址小于0x100)以内需要初始化的全局变量(如@tiny char a = 9;)
+seg .bsct -b 0x0 -m 0x100 -n .bsct
# .ubsct段服务于定义在0页(地址小于0x100)以内不需要初始化的全局变量(如@)
+seg .ubsct -a .bsct -n .ubsct&#
.bit表示位域段,定义后即可在程序中使用_Bool变量(如_Bool c = 1;),-id表示该段需要初始化。
+seg .bit -a .ubsct -n .bit -id
# 这是ST7时代(STM8是基于ST7发展而来的)由于物理堆栈小,速度慢,使用内存来模拟堆栈的变通手段。
+seg .share -a .bit -n .share -is
# .data段服务于定义在0页(地址大于0xFF)以外需要初始化的全局变量(如@near char d = 8;)
+seg .data -b 0x100 -m 0x1300 -n .data
# .bss段服务于定义在0页(地址大于0xFF)以内不需要初始化的全局变量(如@)
+seg .bss -a .data -n .bss
# 段定义结束,下面放置的库及Obj文件中的变量、常量、程序就按照上面的规定进行分配。
#初始化程序
crtsi0.sm8
Debug\main.o
# 一些必要的cosmic库
libis0.sm8
# 重定义常量段,开始于0x8000,用于放置中断向量表(STM8硬件决定此位置)
# &k 用于程序冗余代码优化,详情可参考cosmic用户手册。
+seg .const -b 0x8000 &k
# 中断向量
Debug\stm8_interrupt_vector.o
#定义了三个变量,用于系统初始化
+def __endzp=@.ubsct # end of uninitialized zpage
+def __memory=@.bss # end of bss segment
+def __stack=0x17ff # 不同的芯片__stack内容不同,由系统自动生成
如何实现位操作Cosmic C
编译器支持位变量的操作,可以将其定义成
_Bool类型。_Bool类型的变量只包含两种值true(1)或者false(0)。若将一个表达式赋值给_Bool变量,则编译器会将表达式与0做比较,然后将布尔值赋给_Bool变量。因此,任何整型或者表达式的值都可以赋给_Bool变量。但是,布尔变量不能定义位数组,只能定义成结构体或者联合。而且,_Bool变量会被打包成字节的形式。
编译器会将所有的全局_Bool变量打包成字节形式,存放在.bit
section中。局部_Bool变量也会被打包成字节形式。但是_Bool类型的参数会被扩展成一个单字节。
具体的关于位变量的定义和使用可参考如下例子:
定义位变量:
使用位变量:
in_range = (value &= 10) && (value &= 20);
if (p_valid && in_
在使用位变量时,若程序编译时提示如下错误:
#error clnk Debug\example.lkf:1 no default placement for segment
The command: "clnk -l"C:\Program
Files\COSMIC\CXSTM8_16K_4.2.10\Lib" -o Debug\example.sm8
-mDebug\example.map -sa Debug\example.lkf " has failed, the
returned value is: 1
exit code=1.
实际上是由于,在项目中没有定义.bit section。可按照如下步骤,手工添加.bit section:
打开项目链接配置窗口:Project - Settings - Linker,选择 Input 目录项
在Zero page 或者 Ram 里面定义一个.bit section.
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 库函数编译未定义 的文章

 

随机推荐