本文作者是:Miler Shao
一般来讲,微处理器的用户程序运行前总有个启动文件或类似的文件先行启动,完成微处理器从复位过渡到运行大家耳熟能详的main()函数所需要的基本环境的搭建和准备,具体内容跟开发环境及芯片类型而有所差异。STMCU也不例外,不论STM8还是STM32系列的MCU的程序运行都有相应的启动文件。关于STM32 MCU的启动文件,以汇编指令完成。网络上很多关于启动文件的讲解,有些还讲得比较透彻,有兴趣的话可以搜索阅读。STM32的启动文件的基本功能就是实施有关堆和栈的配载、系统时钟的初始配置、中断矢量的入口配置、各个中断服务程序的入口地址加载、复位程序的执行、以及到MAIN()函数的跳转等。
很多时候,当我们按部就班的建立项目工程的时候,那个后缀为S的启动文件可能被无视,貌似可有可无。其实不然,它的作用很重要、很关键。 在STM32开发应用过程中,碰到外设中断不响应的因素可能很多。比方有关外设的时钟没开启、外设时钟选择错误、NVIC中断矢量没有正确配置等。这里主要分享下跟STM32启动文件有关的外设中断不响应话题。
曾经有人利用STM32F1系列某芯片开发产品,好像是用到SPI外设中断,调试时发现怎么也进不了中断。反复检查相关配置和中断函数代码就是发现不了问题。后来查看其代码,发现配置没有问题,唯一就发现中断函数名跟启动文件里中断矢量表里加载的函数名不一致。比方矢量表里的加载的是SPI1_IRQHandler,而他自己则另取了一个函数名,比如SPI1_INT或其它名字,反正不是SPI1_IRQHandler。这里不是不可以调整,调整的话,你新的函数名要与中断矢量表里声明的函数名一致,否则中断发生时时CPU是跳不进你定义的函数代码里的。 另外一个跟启动文件有关的问题,多发生在STM32同一系列不同型号间的移植的时候。比方STM32F1或STM32F4系列又各分好几个子系列,各个子系列又对应不同的启动文件。虽然子系列间的管脚及程序代码兼容性极高,但它们的外设往往存在一些多寡的差异,导致相关外设的中断矢量定义在各自的启动文件里也会有所不同。有时尽管用户程序代码写得美轮美奂,结果发现个别外设中断就是不响应,检查代码配置及语法很难发现问题。最后发现问题就出在前面提到的启动文件常开发者忽视,没有及时根据芯片型号变动而调整。 有一次某广州的工程师用STM32F1做研发颇有些时日,算是熟手了。因为产品的原因,他经常选用STM32F1系列不同芯片做产品开发。有一次他发现UART4没法响应中断,芯片手册也明确告知是有UART4的,而UART1/2又好好的,翻来覆去找不到原因。后来几经痛苦折腾,突然大彻大悟想到到了启动文件。原来他在从低容量的STM32F1芯片移植升级到更大容量、更多外设的芯片时,忘记了做启动文件的同步更新。因为有些外设的中断向量在低容量芯片的启动文件里根本就没有。比如在STM32F1的低、中容量芯片的启动文件里就没有相关UART4/5中断矢量的定义。前不久有位深圳工程师在做STM32项目移植时好像也碰到这个问题。 当然,我这里只是举个例而已,同一STM32系列不同型号间的外设差异并不仅仅体现在UART上。类似问题,在拿别人的程序模板基础上自行调整并做MCU型号往高端方向移植时尤其容易碰到。因为我们往往会把注意力主要集中在应用代码的更新升级和开发调试上,而忘记相关启动文件的同步调整。 好,先就聊到这里,权当提醒。愿各位STM32开发者尤其初学者,在调试开发过程中少走弯路,并期望从类似的分享中有更多的感悟或收获。 |