maudlu 发表于 2025-7-15 22:32

常见问题解答

    在软件项目中,我们经常会自定义一些数据类型,由于自定义的数据类型不属于关键字,所以在 Keil 中无法高亮显示。Keil 的配置选项中,提供了自定义关键字配置;我们可以将自定义的数据类型设置为关键字,从而实现自定义数据类型的高亮显示。 步骤1:点击工具栏中的扳手图标,打开 Keil 配置选项。https://file1.**/web2/M00/A3/69/wKgaomT5cFyAN5vkAAA9eaMHMaY162.png步骤2:选择 Configuration 中的 User Keywords 选项,左侧 Text File Type 中选择 C/C++ Editor files,在右侧添加自定义关键字后点击 OK 即可。https://file1.**/web2/M00/A3/69/wKgaomT5cFyAC25VAABbf2sq1ug062.pnghttps://file1.**/web2/M00/A3/69/wKgaomT5cFyAU6hnAAAAjgjvZ2U917.png2、调试的两个误会    一、片内RAM用完了?曾有两个不同的用户反馈了相似的问题,他们在对F7Cube库里的工程例程进行编译时,发现了一个令人很不解的事。编译的结果提示芯片内的RAM几乎都耗光了,但以他们对工程基本功能的了解,按理说不应该那样。   具体情况是这样的:他们先在固件库里打开了一个有关lwip应用的工程示例。比如下面目录处的一个工程,使用ARM MDK进行编译。 。 结果发现编译结果提示片内RAM的空间已经基本用完了,但感觉应该用不了那么多RAM内存。客户还想添加自己的其它用户程序,还需使用RAM呢。 打开相应软件工程,使用ARM MDK进行编译,发现编译结果跟客户反馈的一致。https://file1.**/web2/M00/A3/69/wKgaomT5cF2AD-DbAACZ6a0L1WU844.png从编译结果来看,感觉RAM真的被用去了320多K,那RAM用到哪里去了呢?打开对应的MAP文件进一步查看,可得到如下数据。https://file1.**/web2/M00/A3/69/wKgaomT5cF2ADLH8AAEIxVN4CB8186.png先看看芯片内部RAM情况。目前使用的芯片,查看其数据手册可知其内部系统RAM容量为320KB【1KB=1024B】,分别由如下三块RAM区域组成,各区域容量及地址范围如下:https://file1.**/web2/M00/A3/69/wKgaomT5cF2AW10iAADSrsh4Vx4402.png结合编译结果和上面数据信息来看,貌似RAM真的用完了。既然这样,只好硬着头皮继续查看MAP文件的其它细节,‍看看RAM到底消耗在哪些地方去了。后来发现在某个地址段有个巨大的PAD补丁填充区。https://file1.**/web2/M00/A3/69/wKgaomT5cF2AONLRAADLPpuxoV0239.png即从0x2000fd08到0x2004bfff这段区域,共246,520Bytes【即上图‍黄色区域所指】。一般来讲,代码编译后产生的PAD补丁块往往是因为地址对齐方面的原因导致的一些不便使用的零散内存碎片,正常来讲,‍这些补丁块不会大面积的集中在一起。 比如使用下面结构体变量的时候会插入padding.https://file1.**/web2/M00/A3/69/wKgaomT5cF2Ade2pAAA0qCrpHnU525.png‍ 但这里提示的补丁块太大了,高达200多KB而且是连续空间!感觉是哪里误会了。从分析来看,初步判断这个PAD区间应该还是可以被用户使用的。于是尝试在现有代码里随意增加一块16KB的RAM有效使用量,编译一切正常,编译后显示的内存用量结果跟之前几乎一模一样,依然显示RAM用完了。但通过查看MAP文件,可以发现上面提到的那个大补丁块空间也随之减小了16KB。显然,RAM并非真正用完了,只是编译器把它当作类似对齐原因导致的补丁块了。现在问题是,怎么会被编译器误判成这么大的一个补丁块呢?   进一步查看MAP和部分代码源文件,我们可以发现有一块RAM区域,即芯片内的SRAM2区域被用户使用attribute关键字自行做了内存使用分配了,即这块内存空间不是交给编译器安排的。【下图中绿色方框内的内存分配】https://file1.**/web2/M00/A3/69/wKgaomT5cF2AONLRAADLPpuxoV0239.png结合上面的分析,那个巨大的pad区域正是经编译器分配使用到的RAM空间的‍末尾地址开始‍到SRAM2起始地址【0X2004C000】之前的那段空间。 这里让人想到一个地方,那就是MDK IDE选项配置中Target配置的这个地方:https://file1.**/web2/M00/A3/69/wKgaomT5cF2AecTWAACgffXZOh0369.jpg这里片内RAM配置是这样的,意味着从0x20000000到0x2004ffff的全部RAM空间交由编译器分配管理。https://file1.**/web2/M00/A3/69/wKgaomT5cF2AW10iAADSrsh4Vx4402.png而在实际应用代码中,编译器从0x20000000开始分配内存,而SRAM2区域则由用户自行安排使用的。这样的话,经编译器所分配所用到的RAM内存末尾到0x2004BFFF这段未用区域被视为了pad区域。看来只是误会一场。 那如何消除这个误会呢?我们可以将上面的内存配置项稍微修改下,让SRAM2区域不再让编译器分配管理,这样就避免了编译器分配的内存末尾到SRAM2区域起始地址的这段空间被视为补丁区。像下面一样修改:https://file1.**/web2/M00/A3/69/wKgaomT5cF2AAh6gAACqWgBNVRo567.jpg这样修改后再做编译,结果如下,不再给人RAM都用光的感觉了,只用到70多KB的片内RAM。https://file1.**/web2/M00/A3/69/wKgaomT5cF6AfTPmAAAPFKm_iJQ776.png‍‍二、Flash编程算法用不了?发现编译时找不到合适的Flash算法文件,或者MDK自带的现有FLM文件用不了。具体情况是这样的:编译完毕后欲进行下载调试,结果没法完成程序下载,提示FLASH下载错误。https://file1.**/web2/M00/A3/69/wKgaomT5cF6ASD64AAAbeYERsmE463.png检查了各个配置后,怀疑FLASH算法文件是否有问题。 打开MDK选项配置里flash_download的编程配置页面,那里已经添加了相关FLASH编程算法文件。https://file1.**/web2/M00/A3/69/wKgaomT5cF6ASzu_AAEvw06aZWU768.png不过,如果使用芯片做过开发的人可能比较容易发现有个地方有点刺眼,就是起始地址那个地方。用过系列的人可能比较容易发现,那个FLASH起始地址一般是在0x8000000这个地方,这里却是0x00200000。我们再看看MDK选项配置有关内存分配的那个地方,如下图所示:https://file1.**/web2/M00/A3/69/wKgaomT5cF6AIaowAACiBHtLzMI732.jpg这里的片内FLASH默认起始地址却是0x8000000。显然这里跟FLASH编程算法文件的起始地址定义不一致,初步判断应该是这个地方导致的问题。 到此,我们有必要看看的相关技术手册了关于内部FLASH地址分配的内容。下图是片内主从外设及总线的框架图,对于片内FLASH,CPU可以有两条总线通路访问它,一条是通过AXIM接口,经过AXI-AHB桥以64位总线访问,另一条是通过ITCM接口,经过片内ART加速器后访问它。【如下图所示】https://file1.**/web2/M00/A3/69/wKgaomT5cF6AAcCUAAEY1eZRe1M674.png我们通过进一步查看手册,可以得知CPU访问该FLASH区域时因使用不同总线接口而安排了不同的地址访问区域。https://file1.**/web2/M00/A3/69/wKgaomT5cF6AX7AWAACv8wsGXV0973.png从上面表格可以清楚地看到,CPU从不同接口访问FLASH时其对应地址是不一样的。通过AXIM接口访问内部flash的起始地址为0x08000000,通过ITCM接口访问内部flash的起始地址是0x00200000。   结合到上面案例,MDK选项配置中Target页面的片内FLASH地址安排与Flash算法定义的地址不一致导致程序下载失败。那么,我们可以将二者的地址及大小调整得一致,具体根据实际开发需求来调整,即根据你希望CPU通过哪个接口来访问FLASH来做相应调整。   1、如果希望走ITCM接口来访问,我们就将Target页面的FLASH存储起始地址与FLASH算法文件定义的起始地址都设置为0x00200000,如下图所示:https://file1.**/web2/M00/A3/69/wKgaomT5cF6AeWHRAABnX2XxT8U624.png2、如果希望走AXIM接口来访问,我们就将FLASH算法文件定义的起始地址与Target页面定义得一致,这里就是0x08000000。 基于MDK提供的FLASH算法文件我们可以直接修改其起始地址及大小。比如,如果刚加载进来的算法文件是基于ITCM接口的地址定义,如下图所示。https://file1.**/web2/M00/A3/69/wKgaomT5cF-AWCYzAABDMBT07PI542.png我们可以直接基于上面算法文件参数进行起始地址修改,即修改椭圆里的起始地址数据,修改完毕后点击下方的OK按钮即可。操作如下图所示:https://file1.**/web2/M00/A3/69/wKgaomT5cF-AO_msAAEsx4axiA0046.png【注:我所用ARM MDK版本为5.28。】 基于修改后的配置,再进行编译后即可进行下载调试。https://file1.**/web2/M00/A3/69/wKgaomT5cF-ABsqmAABlfhjdEPw085.png
3、分享几篇keil使用问题的文章
下面分享几篇keil使用过程容易遇到的问题以及相关解决方案的文章。   解决KEIL中ARM编译器不能编译的问题 关于keil中无法跳转到函数、变量定义处的问题 keil报错解决:Loading PDSC Debug Description failed for keil出现fatal error: error in backend: ran out of registers during register allocation的解决方案 使用过程中遇到问题是正常的,首先不要着急,先自己根据报错提示信息尝试找到报错问题所在以及报错原因,试着对症下药。如果自己解决不了可以根据报错代码在keil官方手册中查找对应说明。如果平时有遇到其他问题并且还没解决可以后台留言。   如果安装多个keil产品遇到不能共存的问题可以参考视频(这个链接是公众号视频链接可以直接打开):keil MDK与C51共存也算个问题?
页: [1]
查看完整版本: 常见问题解答