本帖最后由 ISO14882 于 2018-8-11 17:32 编辑
本着不作死就不会死的精神,我在学习原子哥的部分教程的时候是尝试用V6的编译器,因此也踩了不少坑,相信很多大佬觉得这是一件十分简单的事,但是对新手来说确实不友好。从 armcc 到 armclang arm 也开始加入了LLVM神教,将前端从EDG换成了Clang,v5版本也只进行维护,重点将放在v6上,对初学者来说是一大福音,其精准的错误提示可以节省很多排查文法错误的时间,同时对ISO标准的跟进也是比较快的,但是相对的,也付出了兼容性的代价,由于前端的改变导致编译器扩展从ARM变成了类似GNU的
扩展。
首先要解决的第一个问题是CMSIS的兼容问题,CMSIS和arm家的编译器都是结合得比较紧密的,所以尽量使用新版的CMSIS,而且里面有编译器的识别宏有跨编译器兼容性。对应的ST官方提供的CMSIS实现是没有针对v6的启动代码,虽然这个可以通过调用armasm解决,但是还有一种方法就是借助CMSIS官方的启动代码模板来重新写启动代码,这部分是比较简单的,只要根据原来arm语法转换成gas的汇编将中断向量定义好就行了类似 例如将 DCD WWDG_IRQHandler 修改为 .long WWDG_IRQHandler ,默认中断发生时运行的是无限循环。堆栈大小设置可以通过 configuration wizard 实现
之后是比较常见的编译器扩展,比如使用外部RAM的at,在V6中改为了__attribute__((section(".ARM.__at_0xC0000000"))),从符号表中可以看到确实如此,由于使用了字符串,如果想通过宏控制的话要转换一下,还有一种方法是section的双引号内使用自定义段名,再在 scatter file 中定义,这和GNU比较像可以更加精细地控制段的属性如ZI,RO,XO等,具体可以通过ARM官方文档得知。内联汇编必须使用gas语法,而一些特殊汇编指令可以使用编译器提供的扩展。
一周热门 更多>