cortex m4移植请教

如何把CORTEX M3的uCOS II 代码移植到CORTEX M4芯片上,需要注意哪些问题?

  • M3,M4内核相差不大,M4外设上基本是M3的增强,如定时器有些改动,需注意。没移植过,其他想来应该没什么需要特别注意的。

  • 这个比较简单,注意一下浮点运算就可以了。如果使用keil的话,可以使用直接在选项卡中禁止FPU,原来的LM3上的ucosII就可以跑,如果使能FPU,在进入主函数时初始化浮点运算.

  • 像LM4F232H5QD的浮点运算单元(FPU)默认是disable的,而M3本身没有FPU,而且M3的指令集本身就是M4指令集的子集,所以移植的时候基本上可以直接移植M3的代码。目前micrium还没有提供Cortex M4的Port接口示例代码,如果移植好了,和大家分享一下吧。

  • 谢谢大家的支持,我把把一个UART的例子移植到M4上了,显示屏有显示了,串口测试结果:按复位键上位机能收到数据,但是上位机发数据显示屏上没有显示,用示波仪测相应的RX/TX端口都有数据变化。调试程序时发现UARTIntHandler(void)中断服务函数没响应(STARTUP里面已经注册好串口的中断处理了,UART0的IO也定义和配置好了),

    以下是中断处理函数:

    void
    UARTIntHandler(void)
    {
        unsigned long ulStatus;

        //
        // 获取中断状态
        //
        ulStatus = UARTIntStatus(UART0_BASE, true);

        //
        // 清中断
        //
        UARTIntClear(UART0_BASE, ulStatus);

        //
        // 读FIFO到空
        //
        while(UARTCharsAvail(UART0_BASE))
        {
           *pbuff++=UARTCharGetNonBlocking(UART0_BASE); //放入RecBuff中
          RecNum++;                                    //接收数据个数加1
        }
        if(ulStatus&UART_INT_RT)//接收超时时,去main里显示接收到内容
        RecFlag=TRUE;           //置超时标记

    }

     以下是主函数:

    while(1)
        {
          if(RecFlag)     //当把RecFlag改为:(RecFlag==0)时,下面的代码才能运行,在中断设断断了没有停下来,说明中断服务函数未响应。
          {
            RecFlag=FALSE;
            //显示接收到的字符
            GrContextForegroundSet(&g_sContext,ClrBlack);
            GrRectFill(&g_sContext, &sRect);
            GrContextForegroundSet(&g_sContext, ClrWhite);
            GrContextFontSet(&g_sContext, &g_sFontCm20);
            GrStringDraw(&g_sContext, RecBuff,RecNum, 150, 165, 0); 
            //发送接收到的字符
            UARTSend(RecBuff, RecNum);
            //清本次接收到的数据和数据个数,准备下一次接收
            RecNum=0;
            pbuff=RecBuff;
          }
          OSTimeDlyHMSM(0,0,0,50);
        }

    请帮忙分析是什么原因。谢谢!

     

  • 你使能了UART的超时中断吗?

  • 使能了

  • 程序一运行就跑到FaultISR中断函数里去了,不知道是怎么回事,硬件配置,堆栈值,优先级等都试了,还是找不到问题原因所在,会不会是M4不支持uCOS II的移植呢???

  • UART的中断标志置位了没?不加UCOS,这个程序能进入中断吗?

  • M4肯定是支持uCOS II的移植的,楼主最好跟踪下具体从哪句跳进FaultISR的,这样才好定位到底是哪里出了问题

  • 中断标志是已经加进去了的。不加UCOSII是能进入中断的,通讯都正常。

     

    OSStartHighRdy

        LDR     R4, =NVIC_SYSPRI2                                           ;  set the PendSV exception
                                                                            ;  priority设置PendSV优先级
        LDR     R5, =NVIC_PENDSV_PRI 
        STR     R5, [R4]
        
        MOV     R4, #0                                                      ;  set the PSP to 0 for initial 
                                                                            ;  context switch call 使PSP等于0
        MSR     PSP, R4

        LDR     R4, __OS_Running                                            ;  OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]

        LDR     R4, =NVIC_INT_CTRL                                          ;  trigger the PendSV exception
                                                                            ;  触发软件中断
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]                                            单步运行从这一句就跳到FaultISR了。

        CPSIE   I                                                           ;  enable interrupts at processor
                                                                            ;  level使能所有优先级的中断
    OSStartHang
        B       OSStartHang                 如果用step into运行这一段代码的话,就会停留在这一步,此时如果再用step over的话就会进入FaultISR程序去了。

     

  • 用串口调试助手收发数据:

    在按下目标板(M4开发板)的RESET键然后在1秒时间内(即显示屏闪烁的瞬间)触发串口调试助手的发送键时,在目标板的显示屏上能接收到PC机发送的信息。

  • 按照你的说法,可以排除UART本身代码的问题。

    那你UCOSII启动了几个任务呢?任务优先级又如何分配?

    你可以在FaultISR的while(1)之前添加如下代码,帮你定位一下问题:

       printf("\r\n Task: %s", OSTCBCur->OSTCBTaskName);

       printf("\r\n State: %p", OSTCBCur->OSTCBStat);

       printf("\r\n StackBase: %p", OSTCBCur->OSTCBStkPtr);

       printf("\r\n HardFault: %0x", *(volatile ULONG *) NVIC_HFAULT_STAT);

       printf("\r\n ConfFault: %0x", *(volatile ULONG *) NVIC_FAULT_STAT);

       printf("\r\n FaultAddr: %0x", *(volatile ULONG *) NVIC_FAULT_ADDR);

       printf("\r\n MemAddr: %0x", *(volatile ULONG *) NVIC_MM_ADDR);

  • 启动了两个任务,一个是UART,另一个LCD。

    优先级分配如下所示:

    #define TASK_START_PRIO                  0

    #define TASK_UART_PRIO                    4

    #define TASK_LCD_PRIO                  5

  • 启动了两个任务,一个是UART,另一个LCD。

    优先级分配如下所示:

    #define TASK_START_PRIO                  0

    #define TASK_UART_PRIO                    4

    #define TASK_LCD_PRIO                  5

  • 你尝试一下吧栈空间改大一些试试看。

  • 试过了,不行

  • 那进入faultISR后打印出来的信息是什么呢?

    如果你不能打印,直接设断点在faultISR中,看看那几个变量的值。

  • 加了这些代码,可编译出错

  • 可能你没有定义printf,那就这样吧:

    你在faultISR的while(1)处设置断点,等进入faultISR时,你查看一下OSTCBCur任务控制块的信息

    可以看到是什么任务导致挂死。

  • 附件是OSTCBCur任务控制块的信息

    OSTCBCur任务控制块的信息.zip
  • 当前导致系统挂起的任务的优先级是7,你查一下优先级为7的任务是什么?统计任务or Idle任务?或者其他?

  • 我只定义了两个任务,一个是UART 优先级定为 4,另一个是LCD优先级定为 5 ;  没有所谓的优先级为7的任务啊。

    单步调试(step into)运行到OSStartHighRdy里面的      B       OSStartHang      这行代码就运行不下去了,

    OSStartHighRdy

        LDR     R4, =NVIC_SYSPRI2                                           ;  set the PendSV exception
                                                                            ;  priority设置PendSV优先级
        LDR     R5, =NVIC_PENDSV_PRI 
        STR     R5, [R4]
        
        MOV     R4, #0                                                      ;  set the PSP to 0 for initial 
                                                                            ;  context switch call 使PSP等于0
        MSR     PSP, R4

        LDR     R4, __OS_Running                                            ;  OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]

        LDR     R4, =NVIC_INT_CTRL                                          ;  trigger the PendSV exception
                                                                            ;  触发软件中断
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]

        CPSIE   I                                                           ;  enable interrupts at processor
                                                                            ;  level使能所有优先级的中断
    OSStartHang
        B       OSStartHang         

  • 你把os_cfg.h文件传上来看看你的配置吧

  • 只能过通step over 才能运行进入FaultISR程序(while(1)处设断点停止运行。)

  • 哦,我看了,os_cfg.h的#define OS_LOWEST_PRIO       7              定义为7

  • 意思就是空闲任务出错啦?

  • 把最大任务数量改一下,试试附件中的这个

    os_cfg.h
  • 试了,还是不行

  • 看了相关uCOS II的书籍,说问题是出在OSTaskStkInit()函数 ,没有将正确的任务启地址放在启任务堆栈中

     

    OS_STK *OSTaskStkInit (void  (*task)(void  *parg), void  *parg, OS_STK  *ptos, INT16U  opt)
    {
        OS_STK *stk;


        (void)opt;                                                          /*  'opt' is not used, prevent  */
                                                                            /*  warning 没有用'opt',       */
                                                                            /*  防止编译警告                */
                                                                               
        stk = ptos;                                                         /*  Load stack pointer          */
                                                                            /*  装载堆栈指针                */                                   

                                                                            /*  Registers stacked as if     */
                                                                            /*  auto-saved on exception     */            
                                                                     /*  模拟成异常,自动把寄存器压栈*/

        *(stk) = (INT32U)0x01000000L;                                       /*  xPSR                        */
        *(--stk) = (INT32U)task;                                            /*  Entry Point of the task     */
                                                                            /*  任务入口地址                */
        *(--stk) = (INT32U)0xFFFFFFFEL;                                     /*  R14 (LR)  (init value will  */
                                                                            /*  cause fault if ever used)   */
                                                                              
        *(--stk) = (INT32U)0x12121212L;                                     /*  R12                         */
        *(--stk) = (INT32U)0x03030303L;                                     /*  R3                          */
        *(--stk) = (INT32U)0x02020202L;                                     /*  R2                          */
        *(--stk) = (INT32U)0x01010101L;                                     /*  R1                          */
        *(--stk) = (INT32U)parg;                                            /*  R0 : argument  输入参数     */
                                                                            /*  Remaining registers saved on*/
                                                                            /*  process stack               */  
                                                                     /*  剩下的寄存器保存到堆栈      */

        *(--stk) = (INT32U)0x11111111L;                                     /*  R11                         */
        *(--stk) = (INT32U)0x10101010L;                                     /*  R10                         */
        *(--stk) = (INT32U)0x09090909L;                                     /*  R9                          */
        *(--stk) = (INT32U)0x08080808L;                                     /*  R8                          */
        *(--stk) = (INT32U)0x07070707L;                                     /*  R7                          */
        *(--stk) = (INT32U)0x06060606L;                                     /*  R6                          */
        *(--stk) = (INT32U)0x05050505L;                                     /*  R5                          */
        *(--stk) = (INT32U)0x04040404L;                                     /*  R4                          */

        return(stk);
    }

    不知道应该改哪一块

  • 这个函数不用修改的。

    如果“没有将正确的任务启地址放在启任务堆栈中”

    你检查一下创建任务的代码OSTaskCreate()传的参数有没有问题。

  • OSTaskGreate() 的参数为:0x2450,.

    那问题究竟出在哪里?

  • INT8U  OSTaskCreate (void   (*task)(void *p_arg),

                        void    *p_arg,

                        OS_STK  *ptos,

                        INT8U    prio)

    你检查传进该函数的参数是否有问题。

  • 这段代码是在OS_TASK.C里面的条件编译语句里面,没法查看其数据呢,

    #if OS_TASK_CREATE_EN > 0

    INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)

    {

    #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */

       OS_CPU_SR  cpu_sr;

    #endif

       OS_STK    *psp;

       INT8U      err;

  • 植移了个ADC的uCOS程序到里面去,AD的采样值(改变AD输入端的电位器值)只有按下复位键后才能变化值。

  • AD采样值在LCD上才有显示变化值

  • aiqin he 说:

    这段代码是在OS_TASK.C里面的条件编译语句里面,没法查看其数据呢,

    #if OS_TASK_CREATE_EN > 0

    INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)

    {

    #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */

       OS_CPU_SR  cpu_sr;

    #endif

       OS_STK    *psp;

       INT8U      err;

    那你怎么创建任务的呢?

    创建任务的时候,要么用OSTaskCreat,要么用OSTaskCreateExt。

     

  • OSTaskCreat信息

  • 这样看不出,

    要不你把main.c main.h, target.c target.h传上来看看

    最好能把你的代码传上来

  • main.c main.h, target.c target.h文件

    UART.rar
  • aiqin he 说:

    main.c main.h, target.c target.h文件

    不好意思,没有看明白你的代码

    你建立的uart task要做什么呢?就是延时等待?

    你可以找一个CM3的移植例程参考一下任务的设计和创建。

     

  • 以上程序是从CORTEX M3 9B96芯片上正常运行的程序搬过来的

  • 建立的uart task要做串口通讯。程序的思想是串口收发数据在LCD显示屏上显示出来

  • 会不会是芯片的不成熟导致的结果呢?做了好几个例程进来都不行。

  • 会不会是M4芯片的问题导致移植不能正常工作。都跑了好几个程序了都不行。真烦人!

  • 怎么没有人问答我的问题呢?  TI有没有M4移植的实例呢?

  • 怎么没有人问答我的问题呢?  TI有没有M4移植的实例呢?

  • 暂时还没有

1 2