ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:162.46KB ,
资源ID:3540171      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3540171.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(STM32F4ucossystem.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

STM32F4ucossystem.docx

1、STM32F4ucossystem1、 内核简介我使用的是STM公司生产的STM32F407Discovery开发板,其CPU内核是ARM公司车技COTEX-M4内核。Cortex-M4 处理器具有大量高效的信号处理功能,可满足数字信号控制市场的需要。Cortex-M4 处理器采用扩展单周期乘法累加 (MAC) 指令、优化的 SIMD 算术、饱和算术指令以及一个可选的单精度浮点单元 (FPU)。其最高的主频可以到达168Mhz,非常实用与信号处理等方面的控制。ARM Cortex 微控制器软件接口标准 (CMSIS) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层。CMSIS 可为

2、接口外设、实时操作系统和中间件实现一致且简单的处理器软件接口,简化了软件的重用。相对于cotex-m3,内核优势:M4内核主频更高,可以达到168Mhz,而M3内核最高只有73Mhz,更高的主频就是意味着有更高的运算速度,可以再更短的时间里面完成更多的事情。其次,M4内核还有一个浮点处理单元,这是M3内核所不具有的,这个优势将是一个翻天覆地的差异。我们都知道在单片机里面如果遇到一个浮点数的计算将是非常痛苦的一件事情,但是有了一个浮点处理单元过后,浮点运算的周期可以大幅减少,对于数字信号处理来时无疑是一个天大的福音。最后,价格上的优势,M4和M3内核的处理器几个几乎不相上下。当然,除此之外,M4

3、较M3内核有个很大的缺点,就是上市时间较短,还没有得到人们的认同。而且现在市面的参考程序大都是M3内核基础上开发,而M4内核的信息或者可愿意参考的东西变得很少,对于自己学习开发的人来说是一个很不好的因素。2、 uCOS II 系统简介uCOS II系统适用于没有MCU的处理器上面的实时操作系统。它是一种可移植的,可植入ROM的,可裁剪的,抢占式的,实时多任务操作系统内核。C/OS 和C/OS-II 是专门为计算机的嵌入式应用设计的, 绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。严格

4、地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。uC/OS-II 中最多可以支持64 个任务,分别对应优先级063,其中0 为最高优先级。63为最低级,系统保留了4个最高优先级的任务和4个最低优先级的任务,所有用户可以使用的任务数有56个。 uC/OS-II提供了任务管理的各种函数调用,包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。 系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,该任务仅给一个整型变量做累加运算;另一个是统计任务,它的

5、优先级为次低,该任务负责统计当前cpu的利用率。uC/OS-II的时间管理是通过定时中断来实现的,该定时中断一般为10毫秒或100毫秒发生一次,时间频率取决于用户对硬件系统的定时器编程来实现。中断发生的时间间隔是固定不变的,该中断也成为一个时钟节拍。 uC/OS-II要求用户在定时中断的服务程序中,调用系统提供的与时钟节拍相关的系统函数,例如中断级的任务切换函数,系统时间函数。uC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。 1) 核心部分(OSCore.c):是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调

6、度、事件处理等多部分。能够维持系统基本工作的部分都在这里。 2) 任务处理部分(OSTask.c):任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为C/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。 3) 时钟部分(OSTime.c):C/OS-II中的最小时钟单位是timetick(时钟节拍)。任务延时等操作是在这里完成的。 4) 任务同步和通信部分:为事件处理部分,包括信号量、邮箱、消息队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。 5) 与CPU的接口部分:是指C/OS-II针对所使用的CPU的移植部分。三、开

7、发环境搭建:我的电脑上的开发可以开发cotex-M4的环境有两个,一个是Keil一个是IAR。因为从一开始接触到Cotex-m4开始就是使用的Iar开发,主要是因为Iar这个软件相对于Keil来说最后声称的.out或者说是.hex或者是.bin文件更小,就是说用IAR编译的效率更高。但是由于用IAR开发的原因,走了许多许多的弯路,主要还是因为现在互联网上的开发历程都是基于Keil软件的,而且大都是基于M3内核的。这里我们使用IAR为例讲述怎么建立一个STM32f4的project:1、 新建一个文件夹,命名为这个工程的名字,在这个文件夹里面创建工程,然后我们要在此文件夹里面新建三个文件夹,分别

8、命名为src,inc,startup,结果如图所示:;2、 从上面我们可以知道CMSIS是cotex系列的开发软件接口,因此我们需要把相关的文件或者是库函数放到我们的工程目录中:Inc文件夹:放置库函数的头文件User文件夹:放置库函数的c语言文件以及用户自己创立的文件StartUp文件夹:放置处理器一开始自启动时候的汇编代码3、 打开Iar,电机Project-Creat new prject ,出现下面对话框点击ok,并将工程放到我们刚才建立的文件夹当中,我们便建立好了一个工程。4、 点击File下面的工程,点击Add,AddGroup,创建三个类分别是Starup,user,inc。然后

9、分别点击三个类添加file,将我们刚才文件夹里面添加的问价全部一一对应的project的虚拟目录中去。5、 点击option,打开C/c+Compler,打开Prerocessor按照下图设置打开Iinker选项,进行设置,如图Debuger选择STlink,在STlink中选择SWD方式,工程设置结束。3、 uCos操作系统开发1、 ucos代码移植,因为现在的网上大都是用的M3内核的ucos的移植,对于M4内核现在移植还不是很成熟,所以使用基于M3的ucos进行开发,因为M3和M4在很大程度还是具有很大的相似性。2、 更改到适合M4内核,首先它的c语言的大部分代码都是脱离硬件的,因此可以不

10、用更改,唯独有一个OS_CPU_A.asm文件是一个汇编文件,里面对m4内核的寄存器设置需要更改,主要更改的地方有这么几个:OSStartHighRdy LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority LDR R1, =NVIC_PENDSV_PRI STRB R1, R0 MOVS R0, #0 ; Set the PSP to 0 for initial context switch call MSR PSP, R0 LDR R0, =OSRunning ; OSRunning = TRUE MOVS R1, #1 ST

11、RB R1, R0 LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, R0 CPSIE I ; Enable interrupts at processor levelOSStartHang B OSStartHang ; Should never get hereOSCtxSw LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context swit

12、ch) LDR R1, =NVIC_PENDSVSET STR R1, R0 BX LR其中有个NVIC_INT_CTRL以及NVIC_PENDSVSET都是需要更改其中这些变量定义是:NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register.NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14).NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest).NVIC_PENDSVSET

13、EQU 0x10000000 ; Value to trigger PendSV exception.3、 Ucos操作系统启动过程:在经过硬件初始化以及始终设置(这些都是在startup_stm32f4xx.s这个汇编代码和startup_stm32f4xx.c文件中进行设置的),经过一个OSInit();的函数进行系统的初始化。其代码如下void OSInit (void) OSInitHookBegin(); /* Call port specific initialization code */ OS_InitMisc(); /* Initialize miscellaneous va

14、riables */ OS_InitRdyList(); /* Initialize the Ready List */ OS_InitTCBList(); /* Initialize the free list of OS_TCBs */ OS_InitEventList(); /* Initialize the free list of OS_EVENTs */#if (OS_FLAG_EN 0u) & (OS_MAX_FLAGS 0u) OS_FlagInit(); /* Initialize the event flag structures */#endif#if (OS_MEM_E

15、N 0u) & (OS_MAX_MEM_PART 0u) OS_MemInit(); /* Initialize the memory manager */#endif#if (OS_Q_EN 0u) & (OS_MAX_QS 0u) / OS_QInit(); /* Initialize the message queue structures */#endif / OS_InitTaskIdle(); /* Create the Idle Task */#if OS_TASK_STAT_EN 0u OS_InitTaskStat(); /* Create the Statistic Tas

16、k */#endif#if OS_TMR_EN 0u OSTmr_Init(); /* Initialize the Timer Manager */#endif OSInitHookEnd(); /* Call port specific init. code */#if OS_DEBUG_EN 0u OSDebugInit();#endif此函数是OS运行的第一个函数,它完成各初始变量的初始化,建立任务空闲键表OSTCBFreeList, 建立事件空闲键表OSEventFreeList.创建一个空闲任务OS_TaskIdle,以及初始化其它如果有用到的功能 Q,MEM等。我个人的理解也是从

17、这里开始的。通过空闲任务的创建基本上涉及到OS中任务块和事件块的管理,同时还对系统中的一些端口进行了初始化。4、Ucos操作系统的任务建立: Ucos是一个实时的多任务抢占式的系统,因此对于任务的建立显得尤为重要。建立任务的函数有两个OSTaskCreateExt和OSTaskCreate,第一个函数定义如下:INT8U OSTaskCreateExt (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio, INT16U id, OS_STK *pbos, INT32U stk_size, void *pext, I

18、NT16U opt)这个函数的调用者:任务或者是启动代码,但是不可以在中断中调用。 此函数建立一个新文件,是OSTaskCreate()的升级版。 参数:task 指向任务代码的指针。p_arg 指向一个类型可以选择的数据区,很多时候是(void *)0。ptos指向任务堆栈栈顶的指针。任务堆栈用于保存局部变量、函数参数、返回地址及中断时cpu寄存器的状 态。如果初始化常量OS_STK_GROWTH设为1(在os_cpu.h中定义),将堆栈设为Stack grows from HIGH to LOW memory on ARM ,此时ptos应该指向任务堆栈空间的最高地址。prio 任务的优先

19、级。数字越小,优先级越高。id任务的标识,可以设置同优先级。pbos 指向堆栈低端的指针。stk_size 指定任务堆栈的大小。pext 定义数据结构的指针,很多时候是(void *)0。opt存放与任务相关的操作信息。另外一个建立任务的函数是OSTaskCreate,它的简单的一个版本其中变量的定义和上面的一致,因此不再陈述,下面放上这个函数完整的代码:INT8U OSTaskCreate (void( *task) (void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) OS_STK *psp; INT8U err;#if OS_CRIT

20、ICAL_METHOD = 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag = OS_TRUE) OS_SAFETY_CRITICAL_EXCEPTION(); return (OS_ERR_ILLEGAL_CREATE_RUN_TIME); #endif#if OS_ARG_CHK_EN 0u if (prio OS_LOWEST_PRIO) /* Make

21、 sure priority is within allowable range */ return (OS_ERR_PRIO_INVALID); #endif OS_ENTER_CRITICAL(); if (OSIntNesting 0u) /* Make sure we dont create the task from within an ISR */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_CREATE_ISR); if (OSTCBPrioTblprio = (OS_TCB *)0) /* Make sure task doesnt alre

22、ady exist at this priority */ OSTCBPrioTblprio = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing . */ /* . the same thing until task is created. */ OS_EXIT_CRITICAL(); psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the tasks stack */ err = OS_TCBInit(prio, psp, (OS_ST

23、K *)0, 0u, 0u, (void *)0, 0u);if (err = OS_ERR_NONE) if (OSRunning = OS_TRUE) /* Find highest priority task if multitasking has started */ OS_Sched(); else OS_ENTER_CRITICAL(); OSTCBPrioTblprio = (OS_TCB *)0;/* Make this priority available to others */ OS_EXIT_CRITICAL(); return (err); OS_EXIT_CRITI

24、CAL(); return (OS_ERR_PRIO_EXIST);理论上,Ucos系统还有非常多的机制值得讨论,多任务的抢占的机制,系统时间的生成,系统错误以及矫正等等,限于篇幅,这里就不在一一阐述。从实际出发,我们可以不去重视这个系统的内部机制具体是什么,只需要了解他的工作原理就可以开始编写程序,设定合适的堆栈等。4、 我的应用程序:我的应用程序是通过stm32F4播放一段音频,并且有个TFT显示器进行显示。1、 应用程序接口:希望把我的应用程序嵌入到Ucos系统当中去需要按照Ucos系统的要求制定一个软件接口:我的软件接口代码如下:static void App_TaskCreate(v

25、oid) INT8U os_err; os_err = OSTaskCreate(void (*) (void *) App_TaskMUSIC, (void *) 0, (OS_STK *) &App_TaskMUSICStkAPP_TASK_MUSIC_STK_SIZE - 1, (INT8U) APP_TASK_LCD_PRIO);我调用的是简单化的任务创建函数进行任务生成,其中一些具体变量说明如下: App_TaskMUSIC:是一个指向我实际函数的函数指针,将这个函数传递给任务生成函数,达到创建任务的目的。 (void *) 0:这个变量代表一个类型可以选择的数据区,这里我给的变量是

26、(void *)0,表示这个任务没有一个数据区域。 &App_TaskMUSICStkAPP_TASK_MUSIC_STK_SIZE - 1:表示的这个任务所拥有的堆栈的大小,其中这个堆栈是从高地址向低地址递增的堆栈,App_TaskMUSICStk是栈顶的指针,APP_TASK_MUSIC_STK_SIZE表示的是这个任务堆栈的大小,在这里我设置APP_TASK_MUSIC_STK_SIZE是128byte。 APP_TASK_LCD_PRIO :便是这个任务的优先级,我设定的是5。通过以上的设置从理论上我们便可以创建出一个任务了。2、 我的音频播放:我的音频播放是将音频信号量化后储存在fl

27、ash中,然后通过AD转换并且放大后放到耳机上面,达到音乐播放的效果。我的音频播放的顶层函数是:WavePlayBack(I2S_AudioFreq_48k);主要代码如下:void WavePlayBack(uint32_t AudioFreq)AudioPlayStart = 1; RepeatState =0; WavePlayerInit(AudioFreq); /* Initialize wave player (Codec, DMA, I2C) */ AudioFlashPlay(uint16_t*)(AUDIO_SAMPLE + AUIDO_START_ADDRESS),AUDI

28、O_FILE_SZE,AUIDO_START_ADDRESS); LED_Toggle = 6; /* LED Blue Start toggling */ while(1) /* Infinite loop */ /* check on the repeate status */ if (RepeatState = 0) if (PauseResumeStatus = 0) LED_Toggle = 0; /* LED Blue Stop Toggling */ WavePlayerPauseResume(PauseResumeStatus); /* Pause playing */ Pau

29、seResumeStatus = 2; else if (PauseResumeStatus = 1) LED_Toggle = 6; /* LED Blue Toggling */ WavePlayerPauseResume(PauseResumeStatus); /* Resume playing */ PauseResumeStatus = 2; else WavePlayerStop();/* Stop playing */ LED_Toggle = 4; /* Green LED toggling */ ,太过于硬件设置的顶层函数就不多讲了,但是顶层的有这么几个函数需要介绍一下: W

30、avePlayerInit(AudioFreq):AudioFreq定义的是(uint32_t)48000),表示IIS的传输速度是48Khz。这个函数的功能主要是为播放做准备包括硬件系统的初始化:包括GPIO端口,IIS传输总行设置,端口和功能的时钟开启,NVIC中断,AD功能的设置等。 AudioFlashPlay(uint16_t*)(AUDIO_SAMPLE AUIDO_START_ADDRESS),AUDIO_FILE_SZE,AUIDO_START_ADDRESS):表示开始播放音频:穿进去的变量是储存音频信号的地址。经过这么设置过后就可以完成音频播放的功能。3、24万色TFT显示

31、的程序设置:顶层调用的函数主要有这么两个:LCD_Init();LCD_Clear(WHITE);LCD_ShowString(30,50,embeded class _);这三个函数的功能是: LCD_Clear(WHITE);:首先清除显示屏的信息,将背景显示为指定的颜色; LCD_Init();:完成硬件的初始化和寄存器配置; LCD_ShowString(30,50,embeded class _);:从像素点(30,50)写入指定的内容;我使用的TFT驱动芯片是ILI9328,使用的是16位数据线驱动的方式;其中LCD_Init();函数代码如下:void LCD_Init(void) TFT_ModuleInit(); delay_ms(50); / del

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1