Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ARM1176JF-S + IAR + uCos + FPU
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Devnir
Предисловие:
Портирую uCos на ARM1176JF-S, использую IAR.
Процесс: впринципе проблем не возникало пока не дошел до FPU
Казалось бы, проблем возникать не должно, но..
1. Micrium предлогает порт для ARM1176 - для RVDS, не беда, асемблерные файлы переписали. проинициализировали все - прекрасно работает.
2. Все в том же злополучном порте от Micrium-а, напрось отсутсвует инициализация и использование FPU. Опять же не проблема, в init.s добавляю:
Код
      ;; Enable the VFP coprocessor.

      ; Enable ARM11 VFP (cp10 and cp11) full access
      ; in the Coprocessor Access Control Register
        MRC     p15, 0, r0, c1, c0, 2
        ORR     r0, r0, #0x00F00000
        MCR     p15, 0, r0, c1, c0, 2

        MOV     r0, #0x40000000    ; Set EN bit in VFP
        FMXR    fpexc, r0             ; FPEXC, clear others.

;
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
;

        MOV     r0, #0x03000000    ; Set FZ and DN bits in VFP
        FMXR    fpscr, r0             ; FPSCR, clear others.


после чего подключаю еще arm_cpu_fpu.s со следующим содержанием:
Код
    PUBLIC  OS_CPU_FP_Restore
    PUBLIC  OS_CPU_FP_Save

    RSEG CODE:CODE:NOROOT(2)
    CODE32


OS_CPU_FP_Restore
        FLDMIAS R0!, {S0-S31}         ; Restore the VFP registers from pblk
        BX      LR                    ; Return to calling function



OS_CPU_FP_Save
        FSTMIAS R0!, {S0-S31}         ; Save the VFP registers in pblk
        BX      LR                    ; Return to calling function


        END


ну и собственно в os_cpu_c.c добавляю:

Код
#define  OS_NTASKS_FP          (OS_MAX_TASKS + OS_N_SYS_TASKS - 1)
#define  OS_FP_STORAGE_SIZE            128L

#if OS_TMR_EN > 0
static  INT16U  OSTmrCtr;
#endif

#if OS_CPU_FPU_EN > 0
static  OS_MEM  *OSFPPartPtr;                    /* Ptr to memory partition for storing FPU registers  */
static  INT32U   OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)];
#endif

#if OS_CPU_FPU_EN > 0
void  OS_CPU_FP_Init (void)
{
    INT8U    err;
#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN
    OS_TCB  *ptcb;
    void    *pblk;
#endif


    OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err);

#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN           /* CHANGE 'OPTIONS' for OS_TaskStat()           */
    ptcb            = OSTCBPrioTbl[OS_TASK_STAT_PRIO];
    ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP;             /* Allow floating-point support for Stat task   */
    pblk            = OSMemGet(OSFPPartPtr, &err);     /* Get storage for VFP registers                */
    if (pblk != (void *)0) {                           /* Did we get a memory block?                   */
        ptcb->OSTCBExtPtr = pblk;                      /* Yes, Link to task's TCB                      */
        OS_CPU_FP_Save(pblk);                          /*      Save the VFP registers in block         */
    }
#endif
}
#endif


в OSInitHookEnd
Код
void  OSInitHookEnd (void)
{
#if OS_CPU_INT_DIS_MEAS_EN > 0
    OS_CPU_IntDisMeasInit();
#endif
    
#if OS_CPU_FPU_EN > 0
    OS_CPU_FP_Init();                            /* Initialize support for VFP register save / restore */
#endif

в OSTaskCreateHook
Код
void  OSTaskCreateHook (OS_TCB *ptcb)
{
#if OS_CPU_FPU_EN > 0
    INT8U  err;
    void  *pblk;
#endif


#if OS_CPU_FPU_EN > 0
    if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) {  /* See if task needs FP support                       */
        pblk = OSMemGet(OSFPPartPtr, &err);      /* Yes, Get storage for VFP registers                 */
        if (pblk != (void *)0) {                 /*      Did we get a memory block?                    */
            ptcb->OSTCBExtPtr = pblk;            /*      Yes, Link to task's TCB                       */
            OS_CPU_FP_Save(pblk);                /*           Save the VFP registers in block          */
        }
    }
#endif

в OSTaskDelHook
Код
void  OSTaskDelHook (OS_TCB *ptcb)
{
#if OS_CPU_FPU_EN > 0
    if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) {            /* See if task had FP support               */
        if (ptcb->OSTCBExtPtr != (void *)0) {              /* Yes, OSTCBExtPtr must not be NULL        */
            OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr);      /*      Return memory block to free pool    */
        }
    }
#endif


OSTaskSwHook
Код
void  OSTaskSwHook (void)
{
  
#if OS_CPU_FPU_EN > 0
    void  *pblk;
#endif

#if OS_CPU_FPU_EN > 0                                      /* Save VFP context of preempted task       */
    if (OSRunning == OS_TRUE) {                            /* Don't save on OSStart()!                 */
        if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) {    /* See if task used FP                      */
            pblk = OSTCBCur->OSTCBExtPtr;                  /* Yes, Get pointer to FP storage area      */
            if (pblk != (void *)0) {                       /*      Make sure we have storage           */
                OS_CPU_FP_Save(pblk);                      /*      Save the VFP registers in block     */
            }
        }
    }
                                                           /* Restore VFP context of new task          */
    if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) {    /* See if new task uses FP                  */
        pblk = OSTCBHighRdy->OSTCBExtPtr;                  /* Yes, Get pointer to FP storage area      */
        if (pblk != (void *)0) {                           /*      Make sure we have storage           */
            OS_CPU_FP_Restore(pblk);                       /*      Get contents of VFP registers       */
        }
    }
#endif


3. Включаю в опцыях проекта использование FPU 2.0
4. Тестовая задача:
Код
float a =0;
while(1){
.... ждем семафора
if(a > 0.7) a = 0;
a+=0.1;
LedToggle(a*10); //переключаем диод, параметр ф-и  - номер диода.
com_print("%lf", a); //выводим в порт значение "а"
}

Результат:
1. задачи работавшие паралельно - работают и далее, прекрасно, адекватно...
2. постоянно мигает 1й диод.
3. в порт получаю: 0.000000
Собственно помогите разобратся в чем проблема ? перелыл уже кучу всего. ничего не помогает
IgorKossak
Ограничить задачу до минимума (исключить из проекта uCOS) и посмотреть листинг.
Devnir
Локализировал проблему.
Отключив uCOS все начало работать корректно.
Код
int main(void)
{
  float a =0.25;
  uart_open(UART1,0,0, 115200);  
  com_print(UART1, "%lf\n", a);
  for(;;);
}



Следовательно FPU инициализируется корректно. (проверял отключив кусок кода отвечающий за инициализацию, соответсвенно работать перестало)

Но от этого легче не стало sad.gif кто по uCOS-у подскажет что я там пропустил когда пытался его заставить работать с ФПУ ?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.