最近接触了μC/OS-III,手里的MSP432LaunchPad都尘封了好久了,于是想着让它用上μC/OS-III。在Micrium公司官网下载已经移植好的示例工程,这是为这块板子适配的,拿来就可以用,里面包含了IAR和CCS的工程文件。(所有文件在文末有百度云下载)
先在IAR上玩一下,直接下载调试运行,就可以看到LED1在闪烁了,S1可以调节闪烁频率,S2用来控制RGB LED的点亮
官方的工程文件里面主要是BSP里面的内容需要根据自己的实际情况改写,我这种新手还不习惯官方的写法,于是进行了一番删减
官方的启动文件同之前的不一样,中断向量表里面的函数入口地址每个都已经写好了,复位程序里面就关掉了看门狗,
- /*
- *********************************************************************************************************
- * EXCEPTION / INTERRUPT VECTOR TABLE
- *
- * Note(s) : (1) The Cortex-M4 may have up to 256 external interrupts, which are the final entries in the
- * vector table. The MSP432 has 65 external interrupt vectors.
- *********************************************************************************************************
- */
-
- __root const APP_INTVECT_ELEM __vector_table[] @ ".intvec" = {
- { .Ptr = (void *)__sfe( "CSTACK" )},
- /* 000 Initial stack pointer. */
- App_Reset_ISR, /* 001 Initial program counter. */
- App_NMI_ISR, /* 002 Non-maskable interrupt. */
- App_Fault_ISR, /* 003 Hard fault exception. */
- App_Spurious_ISR, /* 004 Reserved interrupt 4. */
- App_BusFault_ISR, /* 005 Bus fault exception. */
- App_UsageFault_ISR, /* 006 Usage fault exception. */
- App_Spurious_ISR, /* 007 Reserved interrupt 7. */
- App_Spurious_ISR, /* 008 Reserved interrupt 8. */
- App_Spurious_ISR, /* 009 Reserved interrupt 9. */
- App_Spurious_ISR, /* 010 Reserved interrupt 10. */
- App_Spurious_ISR, /* 011 A supervisor call exception. */
- App_Spurious_ISR, /* 012 Debug Monitor. */
- App_Spurious_ISR, /* 013 Reserved interrupt 13. */
- OS_CPU_PendSVHandler, /* 014 PendSV exception. */
- OS_CPU_SysTickHandler, /* 015 SysTick Interrupt. */
-
- BSP_IntHandlerPSS, /* 016 IRQ[ 0] PSS ISR */
- BSP_IntHandlerCS, /* 017 IRQ[ 1] CS ISR */
- .
OS_PendSVHandler和OS_SysTickHandler在移植文件os_cpu_a.asm里面定义,前者用来上下文切换,后者是SysTick定时器的中断服务程序,外设的中断名都已经定义好了,假如PORT6中断发生,那就会执行BSP_IntHandlerPORT6,这个函数在bsp_int.c文件里:
- <blockquote>void BSP_IntHandlerPORT6 (void) { BSP_IntHandler(BSP_INT_ID_PORT6); }
然后又执行BSP_IntHandler(BSP_INT_DI_PORT6),
- void BSP_IntHandler (CPU_INT16U src_nbr)
- {
- CPU_FNCT_VOID isr;
- CPU_SR_ALLOC();
-
- CPU_CRITICAL_ENTER(); /* Tell the OS that we are starting an ISR */
- OSIntEnter();
- CPU_CRITICAL_EXIT();
-
- if (src_nbr < BSP_INT_ID_MAX) {
- isr = BSP_IntVectTbl[src_nbr];
- if (isr != (CPU_FNCT_VOID)0) {
- isr();
- }
- }
-
- OSIntExit(); /* Tell the OS that we are leaving the ISR */
- }
这个函数先定义了一个CPU_FNCT_VIOD类型的变量isr,这是个指向函数指针,该函数参数和返回值均为空,然后根据传入的中断源ID号从BSP_IntVecTbl里面取得地址,BSP_IntVecTbl在bsp_int.c里面定义:
- static CPU_FNCT_VOID BSP_IntVectTbl[BSP_INT_ID_MAX];
这个中断向量表由以下函数初始化:
- void BSP_IntInit (void)
- {
- CPU_INT32U int_id;
-
-
- for (int_id = 0; int_id < BSP_INT_ID_MAX; int_id++) { /* Initialize each interrupt with Dummy Handler */
- BSP_IntVectSet((CPU_INT08U)int_id,
- (CPU_FNCT_VOID)BSP_IntHandlerDummy);
- }
- }
-
- void BSP_IntVectSet (CPU_INT08U int_id,
- CPU_FNCT_VOID isr)
- {
- CPU_SR_ALLOC();
-
-
- if (int_id < BSP_INT_ID_MAX) {
- CPU_CRITICAL_ENTER();
- BSP_IntVectTbl[int_id] = isr; /* Setup interrupt specified in the vector table */
- CPU_CRITICAL_EXIT();
- }
- }
初始化完毕后向量表全部指向
BSP_IntHandlerDummy,这个函数死循环,什么也不做:
- static void BSP_IntHandlerDummy (void)
- {
- while (DEF_TRUE) {
- ;
- }
- }
所以要用中断时先要调用
BSP_IntVectSet 设置对应的中断向量表,比如在官方的例程里面开启了按键的中断:
- BSP_IntVectSet(BSP_INT_ID_PORT1, App_Port1_ISR);
App_Port1_ISR就是自己定义的中断服务程序了,这真是绕了好大一圈啊,这么做我想也是有道理的,不过我不习惯,就给改了,启动代码里面全用App_Spurious_ISR代替BSP_IntHandlerxxx,用到某个中断就把函数名替换过来,这就习惯了,跟原来差不多了,官方提供的一些中断初始化之类的函数就不要了,最后bsp_int.c文件里面就删减得没东西了。
再对着例程看看,任务运行之前都干了些啥
先CPU初始化,CPU name 什么的:CPU_Init();
关中断,以免初始化过程被打断:BSP_IntDisAll(); 这个函数就是执行CPU_IntDis(),就是两条汇编指令,所以可以替换掉;
接着创建启动任务,启动任务里面执行BSP_Init():
- void BSP_Init (void)
- {
- BSP_SysInit(); /* -------------- CLOCK INITIALIZATION --------------- */
- BSP_IntInit(); /* ------------- INTERRUPT INITIALIZATION ------------ */
- BSP_LED_Init(); /* ---------------- LED INITIALIZATION --------------- */
- BSP_PB_Init(); /* ------------ PUSH BUTTON INITIALIZATION ----------- */
- }
BSP_SysInit()函数把MCLK设为48M,SysTick定时器时间间隔为1ms,然后开启了中断,我觉得中断的开启放在外面是不是要好一点
- void BSP_SysInit (void)
- {
- /* - Configure DCO to 48MHz. Make MCLK use the DCO. - */
- CSKEY = CS_ACCESS_KEY; /* Unlock CS module for register access. */
- CSCTL0 = 0u; /* Reset tuning parameters. */
- CSCTL0 = DCORSEL_5; /* Set DCO to 48MHz operation. */
- DEF_BIT_SET(CSCTL0, DCOEN); /* Enable DCO (digitally controlled oscillator). */
-
- /* Select DCO as the MCLK with no divider. */
- DEF_BIT_CLR(CSCTL1, (SELM_M | DIVM_M));
- DEF_BIT_SET(CSCTL1, SELM_3);
- CSKEY = 0u; /* Lock CS module to protect it from inadvertent access.*/
-
- /* Enable SysTick Module */
- DEF_BIT_SET(BSP_SYS_REG_SCS_STCSR,
- SYSTICK_STCSR_CLKSOURCE | SYSTICK_STCSR_ENABLE);
-
- /* Set SysTick period to 1/48000 */
- if (((CSCTL0 & DCORSEL_M) >> 16u) == 5u) {
- SYSTICK_STRVR = 48000u;
- }
-
- CPU_IntEn(); /* Enable Interrupts. */
- }
BSP_IntInit()就是前面说的设置中断向量表,我就不用它了。接着是LED和按键的初始化
然后执行BSP_Tick_Init(),根据所设定的系统滴答设置SysTick定时器的时间间隔,SysTick在Cortex-M4内核的MCU上应该是一样的,
OS_CPU_SysTickInit里面开启了SysTick的中断,我把BSP_Tick_Init函数也写进BSP_Init里面了,bsp_sys.c和bsp_sys.h文件我就不要了
- void BSP_Tick_Init (void)
- {
- CPU_INT32U cpu_clk_freq;
- CPU_INT32U cnts;
-
- cpu_clk_freq = BSP_CPU_ClkFreq(); /* Determine SysTick reference freq. */
-
- #if (OS_VERSION >= 30000u)
- cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz; /* Determine nbr SysTick increments. */
- #else
- cnts = cpu_clk_freq / (CPU_INT32U)OS_TICKS_PER_SEC; /* Determine nbr SysTick increments. */
- #endif
-
- OS_CPU_SysTickInit(cnts); /* Init uC/OS periodic time src (SysTick). */
- }
到这儿初始化工作差不多就完了,然后就可以创建自己的任务了。
调试之前需对工程设置一番:
Debugger里面的Setup选项卡Driver选择TI XDS:
Download选项卡勾上Use flash loader(s):
IAR提供了调试UC/OS的插件,可以勾上μC/OS-III,如果安装了μC/Prob还可勾上:
TI XDS里面Setup选项卡选择调试器和调试包的安装路径:
然后就可以进入调试了,勾选了插件之后菜单栏会有μC/OS-III,任务列表,CPU使用率,堆栈使用量等等都可以显示出来,可是我感觉这个这个显示的并不准确呀,而且不能实时地刷新
我安装了μC/Prob,这个软件也可以显示μC/OS的各种信息,不过教育版使用有限制,首先设置连接方式,有很多可选项,这里由于IAR里面勾选了插件,选择TCP/IP,填上自己的IP地址就可以了
接着加载ELF文件,IAR输出的.out文件就是ELF格式
右键project1,添加μC/OS-III Awareness,并在datascreen里面添加一个温度计,把一个全局变量和温度计关联起来,直接托上去
接着就可以点run了(IAR需要在调试界面),也有各种信息,全局变量也可以显示,可是为啥有时候是实时的,有时候又不是啊???
接着测试FPU,MSP432要用PFU的话,是不是首先编译器要开启FPU,然后程序里面再用库函数开启FPU?我在工程选项里面选择了使用FPU,创建了一个定时器任务,里面调用库函数MAP_FPU_enableModule(),然后每秒对浮点数加0.01,结果任然硬件错误,不启用FPU一切正常,启用FPU不进行浮点运算也是一切正常。。。μC/OS-III里面对浮点寄存器确实是做了进栈和出栈处理的,这里我也不知道该怎么改,汇编什么的都不懂,忧伤。。。。
- <blockquote>void timerTask(void *p_arg)
接着在CCS里面玩,感觉CCS要人性化一点,可是我的是Free License的,不能调试
做同样的删减,同样的程序代码,同样也是浮点的问题,没有浮点运算一切正常,加了浮点运行3秒就死了,而且工程选项里面我关不掉FPU,不能选择第一行空白,还有我在添加驱动库的时候路径必须添加到最后一行,要不然就报错,实在让人无语。。。
刚接触μC/OS-III,也不知道其他的RTOS好用不,比如FreeRTOS和TI RTOS,附上百度云连接,官方代码,自己的工程,μC/Prob:
http://pan.baidu.com/s/1kT1YrxP
本帖最后由 TWENLONG 于 2015-9-27 16:25 编辑