求助:如何取消KEIL中的_main函数!
本帖最后由 wangpengcheng 于 2014-9-3 16:57 编辑Keil中在初始化之前有个_main函数,是做内存以及堆栈初始化用的,我目前做的工程不想要它,因为他会占用一些空间跟启动时间!可是我不知道如何才能把它去掉?有没有办法?
直接把__main换成你的main函数就行了,不过初始化工作要你自己完成 jiaowoxiaolu 发表于 2014-9-3 16:43
直接把__main换成你的main函数就行了,不过初始化工作要你自己完成
不行的,试过了,它还是会存在! ; Reset handler
Reset_Handler PROC
EXPORTReset_Handler
IMPORTSystemInit
见启动文件
IMPORTyour_main
LDR R0, =SystemInit
BLX R0
LDR R0, =your_main
BX R0
ENDP jiaowoxiaolu 发表于 2014-9-3 16:46
; Reset handler
Reset_Handler PROC
EXPORTReset_Handler
试过了,他还是存在于程序当中,从我的代码一开始的地方就有!我还是不确定我程序从哪开始运行! jiaowoxiaolu 发表于 2014-9-3 16:46
; Reset handler
Reset_Handler PROC
EXPORTReset_Handler
我是想编译完了之后根本不存在的那种! 肯定行,不信你仿真进汇编单步走 jiaowoxiaolu 发表于 2014-9-3 16:49
肯定行,不信你仿真进汇编单步走
呵呵,就是仿真的结果!我才来问的! wangpengcheng 发表于 2014-9-3 16:47
试过了,他还是存在于程序当中,从我的代码一开始的地方就有!我还是不确定我程序从哪开始运行! ...
你是从哪里发现它还在的 tohell 发表于 2014-9-3 16:51
你是从哪里发现它还在的
我是将程序放在RAM中运行的,程序下载完后直接跳到我的RAM的初地址那里,它就存在! 是不是用到了C库的一些东西?那些函数有的会间接引用C运行库的一些异常代码,进而包含初始化代码的。(代码包含是基于Section的,不是基于函数的。)
另外,主函数的名字不要用main, _main这些个,用Main或者其它的任何名字都行。
程序入口main只是C标准的一个约定,但不是必须的,特别是嵌入式环境里,编译器/链接器根本不管是否存在main。
注意,屏蔽了C运行库还是用C库函数的话,可能产生不良后果,要有所预计。 那部分是必须的,做一些初始化的工作,比如全局变量的初始化,C运行时库的初始化,等,然后才跳转到真正的main函数
如果你想丢掉_main函数,是可以的,条件是你不要使用main函数 都说行了你还不信,好像骗你一样!
注意红框,main是我的主函数,__main是库函数 单步进汇编看scatterloader就是__mian干的活 McuPlayer 发表于 2014-9-3 16:56
那部分是必须的,做一些初始化的工作,比如全局变量的初始化,C运行时库的初始化,等,然后才跳转到真正的m ...
不使用main函数编译都编译不过去啊! 本帖最后由 McuPlayer 于 2014-9-3 17:02 编辑
没有main函数,是可以编译通过的,有一个警告,你可以用参数屏蔽掉
没有main函数,你会发现目标代码一下子小了很多,主要是C运行时库的初始化没了
这时候,程序里面避免使用C的运行时函数,比如mallo,free等等 jiaowoxiaolu 发表于 2014-9-3 16:57
都说行了你还不信,好像骗你一样!
你再看看我的图片,呵呵,它还在里面,因为我RAM空间比较小,我需要精减空间! McuPlayer 发表于 2014-9-3 16:58
没有main函数,是可以编译通过的,有一个警告,你可以用参数屏蔽掉
不行啊,通不过!
wangpengcheng 发表于 2014-9-3 16:59
你再看看我的图片,呵呵,它还在里面,因为我RAM空间比较小,我需要精减空间! ...
你在ram你运行是不是有一个ram.ini估计跟他有关 是这样的 打开Option for targert切换到DEBUG 里面有一个run to main的复选框 取消就可以了 你是打算做编程器么?{:titter:} jiaowoxiaolu 发表于 2014-9-3 17:02
你在ram你运行是不是有一个ram.ini估计跟他有关
跟它也没关系,呵呵,那里面只能是确定你需要运行的地址以及一些寄存器的初始化! wangpengcheng 发表于 2014-9-3 16:59
你再看看我的图片,呵呵,它还在里面,因为我RAM空间比较小,我需要精减空间! ...
函数代码还在那里只是占用你的ROM啊,又不会运行到 子鱼 发表于 2014-9-3 17:03
是这样的 打开Option for targert切换到DEBUG 里面有一个run to main的复选框 取消就可以了 ...
也没加那个选项! jiaowoxiaolu 发表于 2014-9-3 17:03
你是打算做编程器么?
是的! wangpengcheng 发表于 2014-9-3 16:59
你再看看我的图片,呵呵,它还在里面,因为我RAM空间比较小,我需要精减空间! ...
用汇编 tohell 发表于 2014-9-3 17:04
函数代码还在那里只是占用你的ROM啊,又不会运行到
RAM空间较小,我想把它干掉,呵呵! holts2 发表于 2014-9-3 17:05
用汇编
晕,不会,呵呵!其实好像IAR里面就没有! dr2001 发表于 2014-9-3 16:54
是不是用到了C库的一些东西?那些函数有的会间接引用C运行库的一些异常代码,进而包含初始化代码的。(代码 ...
这个倒没事,我自己可以掌控得了,现在就是想干掉_main wangpengcheng 发表于 2014-9-3 17:06
晕,不会,呵呵!其实好像IAR里面就没有!
哪就转投IAR, 不是说IAR的效率高,代码紧凑 holts2 发表于 2014-9-3 17:09
哪就转投IAR, 不是说IAR的效率高,代码紧凑
哥,KEIL用习惯了,再说很工作工作都做了,现在转IAR,不现实啊! wangpengcheng 发表于 2014-9-3 17:10
哥,KEIL用习惯了,再说很工作工作都做了,现在转IAR,不现实啊!
总比好过用汇编啊,要不升级硬件,何必为这几个字节费神 wangpengcheng 发表于 2014-9-3 17:01
不行啊,通不过!
要改sct文件,不要用Keil自动生成的那个
这个应该是Keil自动生成的
LR_IROM1 0x08006000 0x0001C000{ ; load region size_region
ER_IROM1 0x08006000 0x0001C000{; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000010 0x00004000{; RW data
.ANY (+RW +ZI)
}
}
这个要改掉,我的程序是在RAM里跑的,scatter文件是这样的,你照猫画虎吧
MODULE 0x20002800 0x3000 ; load region size_region
{
PRO2 0x20002800 0x2700 ; execution address
{
T12.o (TEntryC,+FIRST)
.ANY (+RO)
}
DAT2 0x20004F00 0x100 ; RW data
{
.ANY (+RW +ZI)
}
}
*(InRoot$$Sections)这个部分就是你所认为浪费空间的内容,是C运行时库所必须的
我不用main函数,但在进入TEntryC之前所有代码是我自己做的,相当于自己做scatter loader的功能,如果自己把C运行时库也做了,那相当于自己实现了一个_main McuPlayer 发表于 2014-9-3 17:12
要改sct文件,不要用Keil自动生成的那个
这个应该是Keil自动生成的
这个我也试过,还在存在,呵呵! McuPlayer 发表于 2014-9-3 17:12
要改sct文件,不要用Keil自动生成的那个
这个应该是Keil自动生成的
这样是不是相当把这部份代码搬到自己的程序里做,空间还是省不下来 holts2 发表于 2014-9-3 17:11
总比好过用汇编啊,要不升级硬件,何必为这几个字节费神
唉,我就是贱,明知道换其它方法可以,但就是想把这东西干掉! holts2 发表于 2014-9-3 17:14
这样是不是相当把这部份代码搬到自己的程序里做,空间还是省不下来
我的目的不是节省空间,是为了2个独立的程序,公用一个C运行时库 看看.map文件,看哪里引用了__main holts2 发表于 2014-9-3 17:14
这样是不是相当把这部份代码搬到自己的程序里做,空间还是省不下来
唉,看门狗啊,有时候看门狗会在_main函数运行过程中咬死程序的,所以一开始就需要关掉,但是我要是放前面的话,我就不知道我的程序倒底从哪启动了,还得再把RESET向量加上!这样感觉太恶心! tohell 发表于 2014-9-3 17:16
看看.map文件,看哪里引用了__main
就在程序区最开始的地方! 不是说__main在程序的哪个位置啊,是说谁引用了__main,如果__main没有其他地方用到的话,应该不会链接进生成文件才对
在.map文件中搜一下__main 说不准某些内置的重启代码用到 RAM.ini文件,那个没用,他只是负责调试时的初始化,FreeRun的时候就没用了 tohell 发表于 2014-9-3 17:20
不是说__main在程序的哪个位置啊,是说谁引用了__main,如果__main没有其他地方用到的话,应该不会链接进生 ...
没有任何地方调用它,编译结果他就在程序最开始的起始地址! McuPlayer 发表于 2014-9-3 17:21
RAM.ini文件,那个没用,他只是负责调试时的初始化,FreeRun的时候就没用了
你刚才说怎么样可以在没有MAIN的情况下编译成功? 没人知道吗?自己顶一下! wangpengcheng 发表于 2014-9-3 17:22
你刚才说怎么样可以在没有MAIN的情况下编译成功?
自己翻上去看
其实屏蔽_main是很不好的做法,因为你不知道C什么时候用到运行时库,全局变量的初始化,自己做也未尝不可,倒好解决
我现在已经遇到了这个问题,又不好屏蔽,人工检查一个是工作量大,一个是需要对C运行时库很了解,包括各个版本编译器的差别
自己维护还勉强可以,给同事做都经常出问题
左手用着C语言,右手去阉割它的运行时库,然后你要是C语言的专家才能了然于胸啊
你直接说你想做成什么样子吧,应该不是仅仅为了节省一点Flash空间,然后找下别的路子吧 McuPlayer 发表于 2014-9-3 17:32
自己翻上去看
其实屏蔽_main是很不好的做法,因为你不知道C什么时候用到运行时库,全局变量的初始化,自 ...
那部分空间我已经去掉了,但是他还在!你也知道飞思卡尔所有的芯片都要在一开始处理一下初始化,最主要的是初始化看门狗,因为看门狗在上电时候是打开的,如果不管它有时候他就会在_main函数里面咬死了,但是这样编译下来,我需要的程序入口就找不到了,还得去找RESET向量!所以我想直接从main函数开始算了!而且KE04Z8的芯片只有1K的RAM,空间太小!所以就想把_main屏掉!能省一些空间,也可以直接开始就关狗!但是现在看来有点不太可能! 你这要求够苛刻的,不过如果懂了,请告诉我 lidreamer 发表于 2014-9-3 17:37
你这要求够苛刻的,不过如果懂了,请告诉我
以前KEILC51好像是可以的,现在在ARM中我怎么设置都不行,刚才在网上也查了,好像他们都说解决不了! 首先,_main不消耗你的RAM,用的是一些堆栈变量,执行到main的时候,都会退出来的
其次,在复位向量那里用汇编关狗很简单的
为了解决一个小问题,给自己构建了一个大问题来解决 McuPlayer 发表于 2014-9-3 17:41
首先,_main不消耗你的RAM,用的是一些堆栈变量,执行到main的时候,都会退出来的
其次,在复位向量那里用 ...
他是要把整个程序放ram里面
我也搞不明白为什么要整个放ram里 McuPlayer 发表于 2014-9-3 17:41
首先,_main不消耗你的RAM,用的是一些堆栈变量,执行到main的时候,都会退出来的
其次,在复位向量那里用 ...
呵呵,好吧,我再找找别的资料看看,谢谢啊! tohell 发表于 2014-9-3 17:42
他是要把整个程序放ram里面
我也搞不明白为什么要整个放ram里
因为我要擦除修改整个Flash! wangpengcheng 发表于 2014-9-3 17:44
因为我要擦除修改整个Flash!
那也只要把擦除flash的代码放ram就行啦 我以前做IAP的时候就是只把擦除写入的程序放ram里 tohell 发表于 2014-9-3 17:44
那也只要把擦除flash的代码放ram就行啦
呵呵,我要做的不是你理解的那样!像JLINK那样!芯片里没有任何程序,我要将一段代码放进去! tohell 发表于 2014-9-3 17:48
我以前做IAP的时候就是只把擦除写入的程序放ram里
你那个是基于自己程序的IAP,我要做的是基于SWD的IAP 有一些了解了,楼主你在做IAP是吗?
升级的时候,在RAM里跑,把Flash擦除,然后写入新代码到Flash
你有无想过,如果升级到半路,突然停电了,然后就砖头了。
不怕砖头,是IAP首先要考虑的 McuPlayer 发表于 2014-9-3 17:51
有一些了解了,楼主你在做IAP是吗?
升级的时候,在RAM里跑,把Flash擦除,然后写入新代码到Flash
我不怕砖头,也不会砖头! McuPlayer 发表于 2014-9-3 17:51
有一些了解了,楼主你在做IAP是吗?
升级的时候,在RAM里跑,把Flash擦除,然后写入新代码到Flash
swd就是专业救砖头{:titter:} ,只是LZ思维进入误区暂时还想不通而已 本来以为是只要把启动文件改下就可以的,进来才发现要围观各位大神的解答 jiaowoxiaolu 发表于 2014-9-3 17:54
swd就是专业救砖头 ,只是LZ思维进入误区暂时还想不通而已
有可能过几天就想通了,呵呵,项目还是不能停!{:lol:} wangpengcheng 发表于 2014-9-3 18:01
有可能过几天就想通了,呵呵,项目还是不能停!
我花了大半月才想通这个事情,我会到处说?{:titter:} 没做过swd,不过我觉得swd还需要自己写在目标芯片运行的擦除写入程序这一点比较奇怪 jiaowoxiaolu 发表于 2014-9-3 18:03
我花了大半月才想通这个事情,我会到处说?
其实我已经想了两三个月了还没想通呢! tohell 发表于 2014-9-3 18:03
没做过swd,不过我觉得swd还需要自己写在目标芯片运行的擦除写入程序这一点比较奇怪 ...
呵呵,你做一个就知道了! 看评论长知识 一定要去掉那个吗,再精简一下,其他部分的代码试试,1K也不小了啊,做擦除工作应该够了 {:lol:}{:lol:}{:lol:}去掉 maimaige 发表于 2014-9-3 20:03
一定要去掉那个吗,再精简一下,其他部分的代码试试,1K也不小了啊,做擦除工作应该够了 ...
1K的空间不光是代码,还要有数据,非常紧张!数据量已经在压缩了好多! 空间不够,换单片机型号最方便! fengyunyu 发表于 2014-9-3 20:11
空间不够,换单片机型号最方便!
{:sweat:} 没得可能! 感觉好复杂啊,回头研究 一下 cn_x 发表于 2014-9-3 20:15
感觉好复杂啊,回头研究 一下
唉,空间啊,时间啊,多少年都没考虑过这玩意了,现在又要考虑{:titter:} cn_x 发表于 2014-9-3 20:15
感觉好复杂啊,回头研究 一下
差不多的感觉 看君一片文章,顿感今天上单片机课老师将的很实在。也在讲空间。。将的51 。。告诉我们空间分厂的紧张。。。看了您的文章,发现这需要很高的功底。C 汇编。。编译器。。。。。收藏了。。。有些知识只能以后回头看了。现在也看不懂, 湛泸骏驰 发表于 2014-9-3 20:27
看君一片文章,顿感今天上单片机课老师将的很实在。也在讲空间。。将的51 。。告诉我们空间分厂的紧张。。 ...
呵呵,一般都是这么出发的,但是现在很多场合都用不到了,我是需要利用内核进行Flash烧录,所以才需要这么处理! wangpengcheng 发表于 2014-9-3 20:28
呵呵,一般都是这么出发的,但是现在很多场合都用不到了,我是需要利用内核进行Flash烧录,所以才需要这 ...
内核进行flash烧录,,第一次听说过。。不知能不能指点一下。。 wangpengcheng 发表于 2014-9-3 20:17
唉,空间啊,时间啊,多少年都没考虑过这玩意了,现在又要考虑
我从没考虑过这些········· 湛泸骏驰 发表于 2014-9-3 20:30
内核进行flash烧录,,第一次听说过。。不知能不能指点一下。。
跟Bootload一样的! cn_x 发表于 2014-9-3 20:30
我从没考虑过这些·········
我本以为也不用考虑,谁知道手头这个项目就有这需求啊! wangpengcheng 发表于 2014-9-3 20:30
跟Bootload一样的!
恩恩。。 wangpengcheng 发表于 2014-9-3 20:31
我本以为也不用考虑,谁知道手头这个项目就有这需求啊!
主要我都尽可能买资源多的
工业应用不差那点MCU的成本,多几十无伤大雅
所以不用考虑那么多··············· cn_x 发表于 2014-9-3 20:35
主要我都尽可能买资源多的
工业应用不差那点MCU的成本,多几十无伤大雅
所以不用考虑那么多······ ...
是这样的!呵呵! 这个真没考虑过,不知解决此问题的难度如何,能省多少空间 wxfje 发表于 2014-9-3 21:40
这个真没考虑过,不知解决此问题的难度如何,能省多少空间
网上查了,好像真没什么好办法,唉,可能还真得想其它招! 本帖最后由 laoshuhunya 于 2014-9-3 21:56 编辑
应该可以的,2年前就这么用过了
http://www.amobbs.com/forum.php?mod=viewthread&tid=5462931&page=2#pid5992574
如果你把maim()去掉编译通不过,应该认真看看MDK的编译器文档。
laoshuhunya 发表于 2014-9-3 21:58
如果你把maim()去掉编译通不过,应该认真看看MDK的编译器文档。
谢谢你啊!我现在在想办法压缩代码,应该可以的! wangpengcheng 发表于 2014-9-3 17:17
唉,看门狗啊,有时候看门狗会在_main函数运行过程中咬死程序的,所以一开始就需要关掉,但是我要是放前 ...
明白了,你有洁僻,支持干掉它 holts2 发表于 2014-9-3 23:16
明白了,你有洁僻,支持干掉它
还真有那么一点意思,我甚至怀疑我是不是有强迫症! 本帖最后由 dr2001 于 2014-9-4 08:28 编辑
wangpengcheng 发表于 2014-9-3 17:08
这个倒没事,我自己可以掌控得了,现在就是想干掉_main
你还没明白这事儿。
你用了C库,C库用了某些退出函数作为异常处理;由于Linker加载代码是基于Section的,如果那些Section没分开,那么就会给你做进去。
给个Demo,包含启动和跳转到Main。
RO-Data是CortexM3的向量表,一共64字节(16个32Bit向量);ZI-Data是仿真用的堆空间,这个不用管,我只是懒得改了而已;Code只有20字节。
代码没有任何C运行库初始化。但是有CRTL剪裁,当然,剪裁也可以扔掉,懒的改了而已,浪费了一些RO。
Program Size: Code=20 RO-data=64 RW-data=0 ZI-data=10000000
这个Demo,只是说明一点,C语言标准约定main作为入口函数,是考虑到背后有C-RTL作为基础设施,需要一个标准入口。如果不用C-RTL,并且编译器支持这么干,对Bare Metal的代码来说,main没有存在的必要。
dr2001 发表于 2014-9-4 08:20
你还没明白这事儿。
你用了C库,C库用了某些退出函数作为异常处理;由于Linker加载代码是基于Section的, ...
谢谢你了,我下下来先研究一下! 有main函数,连接器会默认帮用户提前调用_main函数,来实现全局变量的初始化,C运行库的初始化,等工作
可以禁止(使用参数--no_startup),你自行根据需要来实现初始化
也可以自行指定初始化过程(--startup=my_main),此时my_main就相当于原来的_main了。 我最近在做一个按需动态加载Keil产生的axf文件,需要自行做环境的初始化,搜索资料时又看到了这个帖子,顺便回了 McuPlayer 发表于 2014-10-2 03:20
有main函数,连接器会默认帮用户提前调用_main函数,来实现全局变量的初始化,C运行库的初始化,等工作
可 ...
我试着用--no_starup参数,MDK不认识啊! 自己修改启动文件.s应该就可以了吧 看评论长知识-_-好有深度 在__main中会初始化你定义的全局变量和静态变量,否则需要自已手动做。用C的优点也是在于C库,要不用回汇编好了 要想使生成的文件小 那还是使用汇编做吧
页:
[1]
2