Предисловие:
Портирую 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
Собственно помогите разобратся в чем проблема ? перелыл уже кучу всего. ничего не помогает