MSP432用上μC/OS-III,却开不了FPU

2019-03-24 09:41发布

本帖最后由 TWENLONG 于 2015-9-27 16:25 编辑

最近接触了μC/OS-III,手里的MSP432LaunchPad都尘封了好久了,于是想着让它用上μC/OS-III。在Micrium公司官网下载已经移植好的示例工程,这是为这块板子适配的,拿来就可以用,里面包含了IAR和CCS的工程文件。(所有文件在文末有百度云下载)
无标题.png
先在IAR上玩一下,直接下载调试运行,就可以看到LED1在闪烁了,S1可以调节闪烁频率,S2用来控制RGB LED的点亮
官方的工程文件里面主要是BSP里面的内容需要根据自己的实际情况改写,我这种新手还不习惯官方的写法,于是进行了一番删减
官方的启动文件同之前的不一样,中断向量表里面的函数入口地址每个都已经写好了,复位程序里面就关掉了看门狗,
  1. /*
  2. *********************************************************************************************************
  3. *                                  EXCEPTION / INTERRUPT VECTOR TABLE
  4. *
  5. * Note(s) : (1) The Cortex-M4 may have up to 256 external interrupts, which are the final entries in the
  6. *               vector table.  The MSP432 has 65 external interrupt vectors.
  7. *********************************************************************************************************
  8. */

  9. __root  const  APP_INTVECT_ELEM  __vector_table[] @ ".intvec" = {
  10.     { .Ptr = (void *)__sfe( "CSTACK" )},
  11.                                                                 /* 000 Initial stack pointer.                           */
  12.     App_Reset_ISR,                                              /* 001 Initial program counter.                         */
  13.     App_NMI_ISR,                                                /* 002 Non-maskable interrupt.                          */
  14.     App_Fault_ISR,                                              /* 003 Hard fault exception.                            */
  15.     App_Spurious_ISR,                                           /* 004 Reserved interrupt 4.                            */
  16.     App_BusFault_ISR,                                           /* 005 Bus fault exception.                             */
  17.     App_UsageFault_ISR,                                         /* 006 Usage fault exception.                           */
  18.     App_Spurious_ISR,                                           /* 007 Reserved interrupt 7.                            */
  19.     App_Spurious_ISR,                                           /* 008 Reserved interrupt 8.                            */
  20.     App_Spurious_ISR,                                           /* 009 Reserved interrupt 9.                            */
  21.     App_Spurious_ISR,                                           /* 010 Reserved interrupt 10.                           */
  22.     App_Spurious_ISR,                                           /* 011 A supervisor call exception.                     */
  23.     App_Spurious_ISR,                                           /* 012 Debug Monitor.                                   */
  24.     App_Spurious_ISR,                                           /* 013 Reserved interrupt 13.                           */
  25.     OS_CPU_PendSVHandler,                                       /* 014 PendSV exception.                                */
  26.     OS_CPU_SysTickHandler,                                      /* 015 SysTick Interrupt.                               */

  27.     BSP_IntHandlerPSS,                                          /* 016 IRQ[  0] PSS ISR                                 */
  28.     BSP_IntHandlerCS,                                           /* 017 IRQ[  1] CS ISR                                  */
  29. .
复制代码OS_PendSVHandler和OS_SysTickHandler在移植文件os_cpu_a.asm里面定义,前者用来上下文切换,后者是SysTick定时器的中断服务程序,外设的中断名都已经定义好了,假如PORT6中断发生,那就会执行BSP_IntHandlerPORT6,这个函数在bsp_int.c文件里:
  1. <blockquote>void  BSP_IntHandlerPORT6                 (void)  { BSP_IntHandler(BSP_INT_ID_PORT6);               }
复制代码然后又执行BSP_IntHandler(BSP_INT_DI_PORT6),
  1. void  BSP_IntHandler (CPU_INT16U  src_nbr)
  2. {
  3.     CPU_FNCT_VOID  isr;
  4.     CPU_SR_ALLOC();

  5.     CPU_CRITICAL_ENTER();                                       /* Tell the OS that we are starting an ISR            */
  6.     OSIntEnter();
  7.     CPU_CRITICAL_EXIT();

  8.     if (src_nbr < BSP_INT_ID_MAX) {
  9.         isr = BSP_IntVectTbl[src_nbr];
  10.         if (isr != (CPU_FNCT_VOID)0) {
  11.             isr();
  12.         }
  13.     }

  14.     OSIntExit();                                                /* Tell the OS that we are leaving the ISR            */
  15. }
复制代码这个函数先定义了一个CPU_FNCT_VIOD类型的变量isr,这是个指向函数指针,该函数参数和返回值均为空,然后根据传入的中断源ID号从BSP_IntVecTbl里面取得地址,BSP_IntVecTbl在bsp_int.c里面定义:
  1. static CPU_FNCT_VOID BSP_IntVectTbl[BSP_INT_ID_MAX];
复制代码这个中断向量表由以下函数初始化:
  1. void  BSP_IntInit (void)
  2. {
  3.     CPU_INT32U  int_id;


  4.     for (int_id = 0; int_id < BSP_INT_ID_MAX; int_id++) {       /* Initialize each interrupt with Dummy Handler         */
  5.         BSP_IntVectSet((CPU_INT08U)int_id,
  6.                        (CPU_FNCT_VOID)BSP_IntHandlerDummy);
  7.     }
  8. }

  9. void  BSP_IntVectSet (CPU_INT08U     int_id,
  10.                       CPU_FNCT_VOID  isr)
  11. {
  12.     CPU_SR_ALLOC();


  13.     if (int_id < BSP_INT_ID_MAX) {
  14.         CPU_CRITICAL_ENTER();
  15.         BSP_IntVectTbl[int_id]   = isr;                         /* Setup interrupt specified in the vector table        */
  16.         CPU_CRITICAL_EXIT();
  17.     }
  18. }
复制代码初始化完毕后向量表全部指向BSP_IntHandlerDummy,这个函数死循环,什么也不做:
  1. static void  BSP_IntHandlerDummy (void)
  2. {
  3.     while (DEF_TRUE) {
  4.         ;
  5.     }
  6. }
复制代码所以要用中断时先要调用BSP_IntVectSet 设置对应的中断向量表,比如在官方的例程里面开启了按键的中断:
  1. 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():
  1. void  BSP_Init (void)
  2. {
  3.     BSP_SysInit();                                              /* -------------- CLOCK INITIALIZATION --------------- */
  4.     BSP_IntInit();                                              /* ------------- INTERRUPT INITIALIZATION ------------ */
  5.     BSP_LED_Init();                                             /* ---------------- LED INITIALIZATION --------------- */
  6.     BSP_PB_Init();                                              /* ------------ PUSH BUTTON INITIALIZATION ----------- */
  7. }
复制代码BSP_SysInit()函数把MCLK设为48M,SysTick定时器时间间隔为1ms,然后开启了中断,我觉得中断的开启放在外面是不是要好一点
  1. void  BSP_SysInit (void)
  2. {
  3.                                                                 /* - Configure DCO to 48MHz. Make MCLK use the DCO.   - */
  4.     CSKEY  = CS_ACCESS_KEY;                                     /* Unlock CS module for register access.                */
  5.     CSCTL0 = 0u;                                                /* Reset tuning parameters.                             */
  6.     CSCTL0 = DCORSEL_5;                                         /* Set DCO to 48MHz operation.                          */
  7.     DEF_BIT_SET(CSCTL0, DCOEN);                                 /* Enable DCO (digitally controlled oscillator).        */
  8.    
  9.                                                                 /* Select DCO as the MCLK with no divider.              */
  10.     DEF_BIT_CLR(CSCTL1, (SELM_M | DIVM_M));
  11.     DEF_BIT_SET(CSCTL1, SELM_3);
  12.     CSKEY = 0u;                                                 /* Lock CS module to protect it from inadvertent access.*/

  13.                                                                 /* Enable SysTick Module                                */
  14.     DEF_BIT_SET(BSP_SYS_REG_SCS_STCSR,
  15.                         SYSTICK_STCSR_CLKSOURCE | SYSTICK_STCSR_ENABLE);

  16.                                                                 /* Set SysTick period to 1/48000                        */
  17.     if (((CSCTL0 & DCORSEL_M) >> 16u) == 5u) {
  18.             SYSTICK_STRVR = 48000u;
  19.     }
  20.                                                
  21.     CPU_IntEn();                                                /* Enable Interrupts.                                   */
  22. }
复制代码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文件我就不要了
  1. void BSP_Tick_Init (void)
  2. {
  3.     CPU_INT32U  cpu_clk_freq;
  4.     CPU_INT32U  cnts;

  5.     cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */

  6. #if (OS_VERSION >= 30000u)
  7.     cnts  = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;       /* Determine nbr SysTick increments.                    */
  8. #else
  9.     cnts  = cpu_clk_freq / (CPU_INT32U)OS_TICKS_PER_SEC;        /* Determine nbr SysTick increments.                    */
  10. #endif

  11.     OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */
  12. }
复制代码到这儿初始化工作差不多就完了,然后就可以创建自己的任务了。
调试之前需对工程设置一番:
Debugger里面的Setup选项卡Driver选择TI XDS:
捕获.PNG
Download选项卡勾上Use flash loader(s):
捕获4.PNG
IAR提供了调试UC/OS的插件,可以勾上μC/OS-III,如果安装了μC/Prob还可勾上:
捕获5.PNG
TI XDS里面Setup选项卡选择调试器和调试包的安装路径:
捕获3.PNG
然后就可以进入调试了,勾选了插件之后菜单栏会有μC/OS-III,任务列表,CPU使用率,堆栈使用量等等都可以显示出来,可是我感觉这个这个显示的并不准确呀,而且不能实时地刷新
捕获6.PNG
我安装了μC/Prob,这个软件也可以显示μC/OS的各种信息,不过教育版使用有限制,首先设置连接方式,有很多可选项,这里由于IAR里面勾选了插件,选择TCP/IP,填上自己的IP地址就可以了
捕获7.PNG
接着加载ELF文件,IAR输出的.out文件就是ELF格式
捕获8.PNG
右键project1,添加μC/OS-III Awareness,并在datascreen里面添加一个温度计,把一个全局变量和温度计关联起来,直接托上去
捕获9.PNG
接着就可以点run了(IAR需要在调试界面),也有各种信息,全局变量也可以显示,可是为啥有时候是实时的,有时候又不是啊???
捕获10.PNG
捕获11.PNG

接着测试FPU,MSP432要用PFU的话,是不是首先编译器要开启FPU,然后程序里面再用库函数开启FPU?我在工程选项里面选择了使用FPU,创建了一个定时器任务,里面调用库函数MAP_FPU_enableModule(),然后每秒对浮点数加0.01,结果任然硬件错误,不启用FPU一切正常,启用FPU不进行浮点运算也是一切正常。。。μC/OS-III里面对浮点寄存器确实是做了进栈和出栈处理的,这里我也不知道该怎么改,汇编什么的都不懂,忧伤。。。。
捕获12.PNG
  1. <blockquote>void timerTask(void *p_arg)
复制代码接着在CCS里面玩,感觉CCS要人性化一点,可是我的是Free License的,不能调试
做同样的删减,同样的程序代码,同样也是浮点的问题,没有浮点运算一切正常,加了浮点运行3秒就死了,而且工程选项里面我关不掉FPU,不能选择第一行空白,还有我在添加驱动库的时候路径必须添加到最后一行,要不然就报错,实在让人无语。。。
捕获13.PNG
刚接触μC/OS-III,也不知道其他的RTOS好用不,比如FreeRTOS和TI RTOS,附上百度云连接,官方代码,自己的工程,μC/Prob:
http://pan.baidu.com/s/1kT1YrxP
此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
54chenjq
1楼-- · 2019-03-24 15:33
< 上下文切换中有没有对与浮点运算有关的寄存器进行压栈和出栈的处理,没有这些代码是不是会出错?
TWENLONG
2楼-- · 2019-03-24 16:36
 精彩回答 2  元偷偷看……
sunduoze
3楼-- · 2019-03-24 21:36
Mark,差的还远着呢,得向楼主学习~
unknownobj
4楼-- · 2019-03-24 22:01
When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the
*                          Floating-Point Context Control Register (FPCCR).

一周热门 更多>

相关问题

    相关文章