stm32f103移植

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

stm32移植stm32移植本文件请参考《都江堰操作系统与嵌入式系统设计》第15章,该书在可以下载。1.浅谈移植本次移植针对的硬件平台,是“起航一号”djyos评估板,大家可到这里了解这块评估板:=6043。Djyos为方便大家移植,所有在移植时可能需要修改的地方,均注有“移植关键”字样。在开始之前,对于OS移植,先回答一个大家普遍关心的问题:“移植操作系统的首要工作是什么?”“废话,这算哪门子问题哦,不就是用新cpu的指令重写汇编部分代码,重写硬件相关的部分代码嘛!”如果这样想的话,你就大错特错了!操作系统就是计算机中的政府机关,开机后首先得到cpu眷顾的就是你,你享有控制一切社会资源的权利,移植操作系统,就相当于以某一个地区政府为蓝本,在一个新大陆上建立起政治制度相同的政府机关。然而各地有自己的乡土人情、风俗习惯、文化程度、经济水平等,政府机构的设置虽大同,但必存小异。依葫芦画瓢地创建一套行政机关,必然水土不服。因此,同一个操作系统,由不同的人移植到同一套硬件平台上,结果可能大相迳庭,甚至运行效率也相差很远。移植操作系统的首要工作是:决定目标系统资源的使用方式和权限管理策略,也就是常说的先定个调。一般来说,移植操作系统,在动手写代码之前,至少应该确定以下几个策略:1、有许多cpu有多种运行模式,操作系统要安排好内核和应用程序代码分别在什么模式下运行,应用程序代码有什么权限,使其各守本分,各司其职。2、分配内存空间,代码存放地址,运行时地址,数据存放地址,运行时地址,堆内存地址,线程的栈地址,异常处理程序的栈空间,中断的栈空间等。3、系列化安排,嵌入式cpu都是系列化的cpu,同一个内核,系列化型号,不同型号之间大同小异,内核在适应不同型号cpu时,不应该修改代码,而是应该只修改配置文件。4、决定中断管理硬件如何与操作系统的中断模块匹配。前三点是传统操作系统需要考虑的,而第四条是djyos独有的。这来源于djyos特有的中断管理模块,传统操作系统对中断的管理很少,基本上不外乎提供以下几个功能:1、提供一个中断处理函数的封皮和封底,一般用汇编语言实现,使应用程序可以用普通C语言函数的方式写ISR。2、提供关中断和开中断的函数。3、提供中断连接函数,使中断发生时相应的应用程序ISR能被调用。4、设置中断ISR的栈指针。5、linux提供了上下半部的管理功能,算是有一点管理,其实现方式虽然跟djyos的“中断同步”完全不一样,但能实现相似的目的。而djyos则对中断实施了系统级的管理,详见《都江堰操作系统与嵌入式系统设计》一书的第六章,djyos把中断划分为实时中断和异步信号,并且提供中断同步功能,使得大部分中断代码变得更加容易,少量实时性要求高的代码又有更高的实时性,而且更加方便了项目经理管理项目团队。Djyos有无以伦比的中断延迟,在M0(主频40Mhz,flash速度20Mhz)平台下,可保证在昀坏情况下实现1.5us的中断响应时间。在RTOS应用中,设计者往往会把实时性要求昀高的功能,放在中断中完成,在这个意义上,RTOS的实时性,等效于昀坏情况下中断延迟时间。然而,有得必有失,这些红利不是白白得来的,你需要在移植操作系统时,付出代价。因此,移植djyos的工作量,会比普通stm32移植同类操作系统大一些。然而,移植操作系统是一次性的,应用程序项目则有成千上万,故这种付出是值得的。讲了这么多大道理,都是纸上谈兵,来点实际的吧,我们也给si版本的djyosforstm32定个调:1、操作系统内核和应用程序都在特权模式下运行。2、异步事件的优先级全部设为昀低优先级,且不可改变。3、所有异常ISR函数使用使用同一个栈,栈指针是msp,其他代码使用线程栈,栈指针psp。4、代码在flash中执行。2.开发环境先交代一下开发环境,eclipse+codesourcery+djysdk插件,其中djysdk插件是我们自己开发的,使用说明见《djysdk使用手册》(可在下载),该文详细介绍了djysdk的使用方法。说一下调试环境的问题,keilMDK是有严重bug的,大家注意规避,表现为:1、如果在中断函数中下断点,由于keil处理psp(栈指针)有问题,能正确压栈,但不能正确更新psp,所以只要进入了中断函数的断点,中断返回时程序必死无疑,这时候必须使用CDT带的调试器,该调试器使用方法在《djysdk使用手册》有详细说明。2、不能使用keilMDK4.21及更高版本,自从4.21以后,一直存在一个严重问题,就是结构里面还套结构、联合或其指针的话,在watch窗口中不能正常显示。keilMDK4.20也有一点则结构内套联合不能正常显示,其余还没发现问题。更低版本则不能正确识别elf格式的执行文件,不能用。3.启动代码啰嗦半天后,终于开始移植代码了。移植操作系统,首先修改的永远是启动代码,启动代码是为后续程序准备昀起码的运行环境的,每个OS都要有自己独特的要求,像IAR、MDK之类的工具自带的启动代码一般是不能用了,你把它翻译到gcc汇编也没用。Gcc自备的启动代码crt0.s呢,一般来说也没有用了,启动代码必须自己写,这点是不能偷懒的。Djyos无论arm7还是arm9的版本中,总有洋洋数百行的启动代码initcpu.s,令人望而生畏!不过,arm公司在设计cm3时,做了大量改进,使得不需要汇编就能书写启动代码。用调试工具打开qh_1工程后,大家会看到,PC指针停在函数cpu_init(在initcpuc.c文件中)。在cpu_init之前,还需要安排异常向量表,这个,其实也可以用C语言实现,但djyos中没有这样做。毕竟,学嵌入式,会看几行汇编,也是十分必要的。.section.isr_vector,ax,%progbits.align3.globalisr_vectorisr_vector:.wordmsp_top.wordcpu_init.wordnmi_handler.wordhardfault_handler.word0@Reserved.word0@Reserved.word0@Reservedstm32移植.word0@Reserved.word0@Reserved.word0@Reserved.word0@Reserved.wordexp_svc_handler@SVCallHandler.word0@Reserved.word0@Reserved.word0@PendSVHandler.wordexp_systick_handler@SysTickHandler首先,这行:.section.isr_vector,ax,%progbits定义了一个isr_vector段,这段是必须定位到0地址的,那么,编译器又如何知道该把这段代码放到零地址的呢?这要归功于“内存配置工具”,该工具的用法见这个文档:“(开发工具)使用手册20120712.pdf”在内存配置界面中,我们可以看到:其中startup下的第一行,就是指定把isr_vector段放到startup段的开始位置的。我们来看看cpu_init函数都干了些什么,代码如下:voidcpu_init(void){__set_PSP((uint32_t)msp_top);//设置栈指针__set_PRIMASK(1);//禁止中断__set_FAULTMASK(1);//禁止全部异常__set_CONTROL(0);//选择主栈指针MSP,特权级switch(pg_scb_reg-CPUID)//根据CPU的不同版本,做相应设置{casecn_revision_r0p0:break;//市场没有版本0的芯片casecn_revision_r1p0:pg_scb_reg-CCR|=1bo_scb_ccr_stkalign;break;casecn_revision_r1p1:pg_scb_reg-CCR|=1bo_scb_ccr_stkalign;break;casecn_revision_r2p0:break;//好像没什么要做的}stm32移植//以下几句设置flash等待周期pg_inflash_fpec_reg-ACR&=~(u32)0x1f;pg_inflash_fpec_reg-ACR|=(cn_mclk-1)/24000000;//设置等待周期。pg_inflash_fpec_reg-ACR|=0x10;//开启预取//这句判断很重要,因为时钟起振要很长时间,如果系统运行中复位,此时时钟是已经初始化好的,无须重复做一次if(((pg_rcc_reg-CR&cn_cr_check_mask)!=cn_cr_check)||((pg_rcc_reg-CFGR&cn_cfgr_check_mask)!=cn_cfgr_check)){//开始初始化时钟//step1:复位时钟控制寄存器pg_rcc_reg-CR|=(uint32_t)0x00000001;//复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0]MCO[2:0]位pg_rcc_reg-CFGR&=(uint32_t)0xF8FF0000;//复位HSEON,CSSONandPLLON位pg_rcc_reg-CR&=(uint32_t)0xFEF6FFFF;//复位HSEBYP位pg_rcc_reg-CR&=(uint32_t)0xFFFBFFFF;//复位PLLSRC,PLLXTPRE,PLLMUL[3:0]andUSBPRE位pg_rcc_reg-CFGR&=(uint32_t)0xFF80FFFF;//禁止所有中断pg_rcc_reg-CIR=0x00000000;//step2:设置各时钟控制位以及倍频、分频值pg_rcc_reg-CFGR=cn_cfgr_set+(724);//setclockconfigurationregisterpg_rcc_reg-CR=cn_cr_set;//setclockcontrolregisterwhile(bb_rcc_cr_hserdy==0);while(bb_rcc_cr_pllrdy==0);}SRAM_Init();//外扩SRAM初始化,无外扩ram的,无须这句load_preload();//执行预加载模块,此时,cpu初始化已经完成}初始化时钟的代码,先判断了一下时钟是否已经正常工作,为什么要这样做呢?这个跟djyos的启动过程是有关的,djyos允许用在昀紧急的控制系统中。任何系统都可能因bug而崩溃,崩溃导致重新启动时,系统会短暂失效,用户肯定希望关键功能失效时间越短越好,djyos的危急代码加载和实时中断机制就是为这个量身定做的。但如果硬件初始化需要很长时间的话,系统就无法在几个微秒内获得关键控制权。有硬件经验的人都知道,晶体起振和PLL稳定是需要比较长的时间的,在灾难恢复中,灾难事件往往没有破坏系统的时钟部分,这种情况就无需重新初始化时钟,以节约时间。所以在代码的开头,我们首先判断时钟状态,也就是判断RCC寄存器组的CR和CFGR两个寄存器中跟主时钟相关的成员的值是否等于就绪状态。stm32移植4.中断系统中断系统是djyos中昀具特色的系统之一,djyos中断系统的设计,使得djyos具有无以伦比的实时性,这在嵌入式应用中,是至关重要的。在一定程度下,RTOS的实时性,等同于“昀坏情况下的中断延迟”。前面说道,djyos移植有一个重要的工作就是中断系统的决策,djyos允许在中断服务中执行系统调用,可能会使比被中断线程更高优先级的线程就绪,中断返回时将直接返回到高优先级的线程,这就需要有一个被中断线程的栈、高优先级线程栈、中

1 / 12
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功