STM32F4ucossystemWord文档下载推荐.docx
- 文档编号:16445502
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:16
- 大小:162.46KB
STM32F4ucossystemWord文档下载推荐.docx
《STM32F4ucossystemWord文档下载推荐.docx》由会员分享,可在线阅读,更多相关《STM32F4ucossystemWord文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。
uC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。
1)核心部分(OSCore.c):
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。
能够维持系统基本工作的部分都在这里。
2)任务处理部分(OSTask.c):
任务处理部分中的内容都是与任务的操作密切相关的。
包括任务的建立、删除、挂起、恢复等等。
因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。
3)时钟部分(OSTime.c):
μC/OS-II中的最小时钟单位是timetick(时钟节拍)。
任务延时等操作是在这里完成的。
4)任务同步和通信部分:
为事件处理部分,包括信号量、邮箱、消息队列、事件标志等部分;
主要用于任务间的互相联系和对临界资源的访问。
5)与CPU的接口部分:
是指μC/OS-II针对所使用的CPU的移植部分。
三、开发环境搭建:
我的电脑上的开发可以开发cotex-M4的环境有两个,一个是Keil一个是IAR。
因为从一开始接触到Cotex-m4开始就是使用的Iar开发,主要是因为Iar这个软件相对于Keil来说最后声称的.out或者说是.hex或者是.bin文件更小,就是说用IAR编译的效率更高。
但是由于用IAR开发的原因,走了许多许多的弯路,主要还是因为现在互联网上的开发历程都是基于Keil软件的,而且大都是基于M3内核的。
这里我们使用IAR为例讲述怎么建立一个STM32f4的project:
1、新建一个文件夹,命名为这个工程的名字,在这个文件夹里面创建工程,然后我们要在此文件夹里面新建三个文件夹,分别命名为src,inc,startup,结果如图所示:
;
2、从上面我们可以知道CMSIS是cotex系列的开发软件接口,因此我们需要把相关的文件或者是库函数放到我们的工程目录中:
Inc文件夹:
放置库函数的头文件
User文件夹:
放置库函数的c语言文件以及用户自己创立的文件
StartUp文件夹:
放置处理器一开始自启动时候的汇编代码
3、打开Iar,电机Project->
Creatnewprject,出现下面对话框
点击ok,并将工程放到我们刚才建立的文件夹当中,我们便建立好了一个工程。
4、点击File下面的工程,点击Add,AddGroup,创建三个类分别是Starup,user,inc。
然后分别点击三个类添加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语言的大部分代码都是脱离硬件的,因此可以不用更改,唯独有一个OS_CPU_A.asm文件是一个汇编文件,里面对m4内核的寄存器设置需要更改,主要更改的地方有这么几个:
OSStartHighRdy
LDRR0,=NVIC_SYSPRI14;
SetthePendSVexceptionpriority
LDRR1,=NVIC_PENDSV_PRI
STRBR1,[R0]
MOVSR0,#0;
SetthePSPto0forinitialcontextswitchcall
MSRPSP,R0
LDRR0,=OSRunning;
OSRunning=TRUE
MOVSR1,#1
LDRR0,=NVIC_INT_CTRL;
TriggerthePendSVexception(causescontextswitch)
LDRR1,=NVIC_PENDSVSET
STRR1,[R0]
CPSIEI;
Enableinterruptsatprocessorlevel
OSStartHang
BOSStartHang;
Shouldnevergethere
OSCtxSw
BXLR
其中有个NVIC_INT_CTRL以及NVIC_PENDSVSET都是需要更改其中这些变量定义是:
NVIC_INT_CTRLEQU0xE000ED04;
Interruptcontrolstateregister.
NVIC_SYSPRI14EQU0xE000ED22;
Systempriorityregister(priority14).
NVIC_PENDSV_PRIEQU0xFF;
PendSVpriorityvalue(lowest).
NVIC_PENDSVSETEQU0x10000000;
ValuetotriggerPendSVexception.
3、Ucos操作系统启动过程:
在经过硬件初始化以及始终设置(这些都是在startup_stm32f4xx.s这个汇编代码和startup_stm32f4xx.c文件中进行设置的),经过一个OSInit();
的函数进行系统的初始化。
其代码如下
voidOSInit(void)
{
OSInitHookBegin();
/*Callportspecificinitializationcode*/
OS_InitMisc();
/*Initializemiscellaneousvariables*/
OS_InitRdyList();
/*InitializetheReadyList*/
OS_InitTCBList();
/*InitializethefreelistofOS_TCBs*/
OS_InitEventList();
/*InitializethefreelistofOS_EVENTs*/
#if(OS_FLAG_EN>
0u)&
&
(OS_MAX_FLAGS>
0u)
OS_FlagInit();
/*Initializetheeventflagstructures*/
#endif
#if(OS_MEM_EN>
(OS_MAX_MEM_PART>
OS_MemInit();
/*Initializethememorymanager*/
#if(OS_Q_EN>
(OS_MAX_QS>
//OS_QInit();
/*Initializethemessagequeuestructures*/
//OS_InitTaskIdle();
/*CreatetheIdleTask*/
#ifOS_TASK_STAT_EN>
0u
OS_InitTaskStat();
/*CreatetheStatisticTask*/
#ifOS_TMR_EN>
OSTmr_Init();
/*InitializetheTimerManager*/
OSInitHookEnd();
/*Callportspecificinit.code*/
#ifOS_DEBUG_EN>
OSDebugInit();
}
此函数是OS运行的第一个函数,它完成各初始变量的初始化,建立任务空闲键表OSTCBFreeList,建立事件空闲键表OSEventFreeList.创建一个空闲任务OS_TaskIdle,以及初始化其它如果有用到的功能Q,MEM等。
我个人的理解也是从这里开始的。
通过空闲任务的创建基本上涉及到OS中任务块和事件块的管理,同时还对系统中的一些端口进行了初始化。
4、Ucos操作系统的任务建立:
Ucos是一个实时的多任务抢占式的系统,因此对于任务的建立显得尤为重要。
建立任务的函数有两个OSTaskCreateExt和OSTaskCreate,第一个函数定义如下:
INT8UOSTaskCreateExt(void(*task)(void*p_arg),
void*p_arg,
OS_STK*ptos,
INT8Uprio,
INT16Uid,
OS_STK*pbos,
INT32Ustk_size,
void*pext,
INT16Uopt)
这个函数的调用者:
任务或者是启动代码,但是不可以在中断中调用。
此函数建立一个新文件,是OSTaskCreate()的升级版。
参数:
task指向任务代码的指针。
p_arg指向一个类型可以选择的数据区,很多时候是(void*)0。
ptos指向任务堆栈栈顶的指针。
任务堆栈用于保存局部变量、函数参数、返回地址及中断时cpu寄存器的状态。
如果初始化常量OS_STK_GROWTH设为1(在os_cpu.h中定义),将堆栈设为StackgrowsfromHIGHtoLOWmemoryonARM,此时ptos应该指向任务堆栈空间的最高地址。
prio任务的优先级。
数字越小,优先级越高。
id任务的标识,可以设置同优先级。
pbos指向堆栈低端的指针。
stk_size指定任务堆栈的大小。
pext定义数据结构的指针,很多时候是(void*)0。
opt存放与任务相关的操作信息。
另外一个建立任务的函数是OSTaskCreate,它的简单的一个版本其中变量的定义和上面的一致,因此不再陈述,下面放上这个函数完整的代码:
INT8UOSTaskCreate(void(*task)(void*p_arg),void*p_arg,OS_STK*ptos,INT8Uprio)
OS_STK*psp;
INT8Uerr;
#ifOS_CRITICAL_METHOD==3u/*AllocatestorageforCPUstatusregister*/
OS_CPU_SRcpu_sr=0u;
#ifdefOS_SAFETY_CRITICAL_IEC61508
if(OSSafetyCriticalStartFlag==OS_TRUE){
OS_SAFETY_CRITICAL_EXCEPTION();
return(OS_ERR_ILLEGAL_CREATE_RUN_TIME);
}
#ifOS_ARG_CHK_EN>
if(prio>
OS_LOWEST_PRIO){/*Makesurepriorityiswithinallowablerange*/
return(OS_ERR_PRIO_INVALID);
OS_ENTER_CRITICAL();
if(OSIntNesting>
0u){/*Makesurewedon'
tcreatethetaskfromwithinanISR*/
OS_EXIT_CRITICAL();
return(OS_ERR_TASK_CREATE_ISR);
if(OSTCBPrioTbl[prio]==(OS_TCB*)0){/*Makesuretaskdoesn'
talreadyexistatthispriority*/
OSTCBPrioTbl[prio]=OS_TCB_RESERVED;
/*Reservetheprioritytopreventothersfromdoing...*/
/*...thesamethinguntiltaskiscreated.*/
psp=OSTaskStkInit(task,p_arg,ptos,0u);
/*Initializethetask'
sstack*/
err=OS_TCBInit(prio,psp,(OS_STK*)0,0u,0u,(void*)0,0u);
if(err==OS_ERR_NONE){
if(OSRunning==OS_TRUE){/*Findhighestprioritytaskifmultitaskinghasstarted*/
OS_Sched();
}else{
OSTCBPrioTbl[prio]=(OS_TCB*)0;
/*Makethispriorityavailabletoothers*/
return(err);
return(OS_ERR_PRIO_EXIST);
理论上,Ucos系统还有非常多的机制值得讨论,多任务的抢占的机制,系统时间的生成,系统错误以及矫正等等,限于篇幅,这里就不在一一阐述。
从实际出发,我们可以不去重视这个系统的内部机制具体是什么,只需要了解他的工作原理就可以开始编写程序,设定合适的堆栈等。
4、我的应用程序:
我的应用程序是通过stm32F4播放一段音频,并且有个TFT显示器进行显示。
1、应用程序接口:
希望把我的应用程序嵌入到Ucos系统当中去需要按照Ucos系统的要求制定一个软件接口:
我的软件接口代码如下:
staticvoidApp_TaskCreate(void)
INT8Uos_err;
os_err=OSTaskCreate((void(*)(void*))App_TaskMUSIC,(void*)0,
(OS_STK*)&
App_TaskMUSICStk[APP_TASK_MUSIC_STK_SIZE-1],
(INT8U)APP_TASK_LCD_PRIO);
我调用的是简单化的任务创建函数进行任务生成,其中一些具体变量说明如下:
●App_TaskMUSIC:
是一个指向我实际函数的函数指针,将这个函数传递给任务生成函数,达到创建任务的目的。
●(void*)0:
这个变量代表一个类型可以选择的数据区,这里我给的变量是(void*)0,表示这个任务没有一个数据区域。
●&
App_TaskMUSICStk[APP_TASK_MUSIC_STK_SIZE-1]:
表示的这个任务所拥有的堆栈的大小,其中这个堆栈是从高地址向低地址递增的堆栈,App_TaskMUSICStk是栈顶的指针,APP_TASK_MUSIC_STK_SIZE表示的是这个任务堆栈的大小,在这里我设置APP_TASK_MUSIC_STK_SIZE是128byte。
●APP_TASK_LCD_PRIO:
便是这个任务的优先级,我设定的是5。
通过以上的设置从理论上我们便可以创建出一个任务了。
2、我的音频播放:
我的音频播放是将音频信号量化后储存在flash中,然后通过AD转换并且放大后放到耳机上面,达到音乐播放的效果。
我的音频播放的顶层函数是:
WavePlayBack(I2S_AudioFreq_48k);
主要代码如下:
voidWavePlayBack(uint32_tAudioFreq)
AudioPlayStart=1;
RepeatState=0;
WavePlayerInit(AudioFreq);
/*Initializewaveplayer(Codec,DMA,I2C)*/
AudioFlashPlay((uint16_t*)(AUDIO_SAMPLE+AUIDO_START_ADDRESS),AUDIO_FILE_SZE,AUIDO_START_ADDRESS);
LED_Toggle=6;
/*LEDBlueStarttoggling*/
while
(1)/*Infiniteloop*/
{
/*checkontherepeatestatus*/
if(RepeatState==0)
{
if(PauseResumeStatus==0)
LED_Toggle=0;
/*LEDBlueStopToggling*/
WavePlayerPauseResume(PauseResumeStatus);
/*Pauseplaying*/
PauseResumeStatus=2;
elseif(PauseResumeStatus==1)
/*LEDBlueToggling*/
/*Resumeplaying*/
else
WavePlayerStop();
/*Stopplaying*/
LED_Toggle=4;
/*GreenLEDtoggling*/
,太过于硬件设置的顶层函数就不多讲了,但是顶层的有这么几个函数需要介绍一下:
●WavePlayerInit(AudioFreq):
AudioFreq定义的是((uint32_t)48000),表示IIS的传输速度是48Khz。
这个函数的功能主要是为播放做准备包括硬件系统的初始化:
包括GPIO端口,IIS传输总行设置,端口和功能的时钟开启,NVIC中断,AD功能的设置等。
●AudioFlashPlay((uint16_t*)(AUDIO_SAMPLEAUIDO_START_ADDRESS),AUDIO_FILE_SZE,AUIDO_START_ADDRESS):
表示开始播放音频:
穿进去的变量是储存音频信号的地址。
经过这么设置过后就可以完成音频播放的功能。
3、24万色TFT显示的程序设置:
顶层调用的函数主要有这么两个:
LCD_Init();
LCD_Clear(WHITE);
LCD_ShowString(30,50,"
embededclass^_^"
);
这三个函数的功能是:
●LCD_Clear(WHITE);
:
首先清除显示屏的信息,将背景显示为指定的颜色;
●LCD_Init();
:
完成硬件的初始化和寄存器配置;
●LCD_ShowString(30,50,"
从像素点(30,50)写入指定的内容;
我使用的TFT驱动芯片是ILI9328,使用的是16位数据线驱动的方式;
其中LCD_Init();
函数代码如下:
voidLCD_Init(void)
{
TFT_ModuleInit();
delay_ms(50);
//del
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- STM32F4ucossystem