From cd7ab15d6faca00ad56a3cc55613a1529790aa1c Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 24 Feb 2012 21:34:55 +0000 Subject: Add a test to verify that FPU registers are properly saved and restored on context switches. git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4421 42af7a65-404d-4744-a932-0658087f49c3 --- apps/examples/ostest/Makefile | 8 +- apps/examples/ostest/fpu.c | 278 ++++++++++++++++++++++++++++++++++++++++++ apps/examples/ostest/main.c | 14 ++- apps/examples/ostest/ostest.h | 16 ++- 4 files changed, 305 insertions(+), 11 deletions(-) create mode 100644 apps/examples/ostest/fpu.c (limited to 'apps/examples') diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile index 1405a2afb..45eef5ff6 100644 --- a/apps/examples/ostest/Makefile +++ b/apps/examples/ostest/Makefile @@ -1,8 +1,8 @@ ############################################################################ # apps/examples/ostest/Makefile # -# Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. -# Author: Gregory Nutt +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -42,6 +42,10 @@ include $(APPDIR)/Make.defs ASRCS = CSRCS = main.c dev_null.c +ifeq ($(CONFIG_ARCH_FPU),y) +CSRCS += fpu.c +endif + ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += cancel.c cond.c mutex.c sem.c barrier.c ifneq ($(CONFIG_RR_INTERVAL),0) diff --git a/apps/examples/ostest/fpu.c b/apps/examples/ostest/fpu.c new file mode 100644 index 000000000..ca61c0089 --- /dev/null +++ b/apps/examples/ostest/fpu.c @@ -0,0 +1,278 @@ +/*********************************************************************** + * apps/examples/ostest/fpu.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/*********************************************************************** + * Included Files + ***********************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include "ostest.h" + +/*********************************************************************** + * Pre-processor definitions + ***********************************************************************/ +/* Configuration *******************************************************/ + +#undef HAVE_FPU +#ifdef CONFIG_ARCH_FPU +# if defined(CONFIG_EXAMPLES_OSTEST_FPUSIZE) && defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_DISABLE_SIGNALS) +# define HAVE_FPU 1 +# else +# ifndef CONFIG_EXAMPLES_OSTEST_FPUSIZE +# warning "FPU test not built; CONFIG_EXAMPLES_OSTEST_FPUSIZE not defined" +# endif +# ifndef CONFIG_SCHED_WAITPID +# warning "FPU test not built; CONFIG_SCHED_WAITPID not defined" +# endif +# ifdef CONFIG_DISABLE_SIGNALS +# warning "FPU test not built; CONFIG_DISABLE_SIGNALS defined" +# endif +# endif +#endif + +#ifdef HAVE_FPU + +#ifndef CONFIG_EXAMPLES_OSTEST_FPULOOPS +# define CONFIG_EXAMPLES_OSTEST_FPULOOPS 16 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUMSDELAY +# define CONFIG_EXAMPLES_OSTEST_FPUMSDELAY 750 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUPRIORITY +# define CONFIG_EXAMPLES_OSTEST_FPUPRIORITY SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE +# define CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE 2048 +#endif + +/* Other defintions ****************************************************/ + +#ifndef NULL +# define NULL (void*)0 +#endif + +/*********************************************************************** + * External Dependencies + ***********************************************************************/ +/* This test is very dependent on support provided by the chip/board- + * layer logic. In particular, it expects the following functions + * to be provided: + */ + +/* Given a uint8_t array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE, this + * function will return the current FPU registers. + */ + +extern void arch_getfpu(FAR uint8_t *fpusave); + +/* Given a uint8_t array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE, this + * function will set the current FPU regisers to match the provided + * register save set. + */ + +extern void arch_setfpu(FAR const uint8_t *fpusave); + +/* Given a uint8_t array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE and a + * seed value, this function will set the FPU registers to a known + * values for testing purposes. The contents of the FPU registers + * must be uniqe for each sed value. + */ + +extern void arch_initfpu(FAR uint8_t *fpusave, int seed); + +/* Given two uint8_t arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this + * function will compare then an return true if they are identical. + */ + +extern bool arch_cmpfpu(FAR const uint8_t *fpusave1, FAR const uint8_t *fpusave2); + +/*********************************************************************** + * Private Data + ***********************************************************************/ + +static uint8_t g_fpuno; + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +static void fpu_dump(FAR uint8_t *buffer, FAR const char *msg) +{ + int i, j, k; + + printf("%s (%p):\n", msg, buffer); + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPUSIZE; i += 32) + { + printf("%04x: ", i); + for (j = 0; j < 32; j++) + { + k = i + j; + + if (k < CONFIG_EXAMPLES_OSTEST_FPUSIZE) + { + printf("%02x ", buffer[k]); + } + else + { + break; + } + } + printf("\n"); + } +} + +static int fpu_task(int argc, char *argv[]) +{ + uint8_t fpusave1[CONFIG_EXAMPLES_OSTEST_FPUSIZE]; + uint8_t fpusave2[CONFIG_EXAMPLES_OSTEST_FPUSIZE]; + int id; + int seed; + int incr; + int i; + + /* Which are we? */ + + sched_lock(); + id = (int)(++g_fpuno); + sched_unlock(); + + seed = id << 24 | id << 16 | id << 8 | id; + incr = seed; + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPULOOPS; i++) + { + /* Initialize the FPU registers to a known value */ + + sched_lock(); + arch_initfpu(fpusave1, seed); + arch_setfpu(fpusave1); + + /* Check that the FPU registers were set as we expected */ + + arch_getfpu(fpusave2); + if (!arch_cmpfpu(fpusave1, fpusave2)) + { + printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match (BEFORE waiting)\n"); + fpu_dump(fpusave1, "Values written:"); + fpu_dump(fpusave2, "Values read:"); + sched_unlock(); + return EXIT_FAILURE; + } + + /* Now unlock and sleep for a while */ + + sched_unlock(); + usleep(CONFIG_EXAMPLES_OSTEST_FPUMSDELAY * 1000); + + /* Several context switches should have occurred. Now verify that the floating + * point registers are still correctly set. + */ + + sched_lock(); + arch_getfpu(fpusave2); + if (!arch_cmpfpu(fpusave1, fpusave2)) + { + printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match (AFTER waiting)\n"); + fpu_dump(fpusave1, "Values written:"); + fpu_dump(fpusave2, "Values read:"); + sched_unlock(); + return EXIT_FAILURE; + } + + seed += incr; + } + + printf("FPU#%d: Succeeded\n"); + return EXIT_SUCCESS; +} +#endif /* HAVE_FPU */ + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +void fpu_test(void) +{ +#ifdef HAVE_FPU + pid_t task1; + pid_t task2; + int statloc; + + /* Start two two tasks */ + + g_fpuno = 0; + printf("Starting task FPU#1\n"); + task1 = TASK_CREATE("FPU#1", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task1 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#1 at PID=%d\n", task1); + } + usleep(250); + + printf("Starting task FPU#2\n"); + task2 = TASK_CREATE("FPU#2", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task2 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#2 at PID=%d\n", task2); + } + + /* Wait for each task to complete */ + + (void)waitpid(task1, &statloc, 0); + (void)waitpid(task2, &statloc, 0); + +#else + printf("fpu_test: ERROR: The FPU test is not properly configured\n"); +#endif + printf("fpu_test: Returning\n"); +} diff --git a/apps/examples/ostest/main.c b/apps/examples/ostest/main.c index 327ec60e1..f48bca377 100644 --- a/apps/examples/ostest/main.c +++ b/apps/examples/ostest/main.c @@ -1,8 +1,8 @@ /**************************************************************************** - * examples/ostest/main.c + * apps/examples/ostest/main.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -293,6 +293,14 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif +#ifdef CONFIG_ARCH_FPU + /* Check that the FPU is properly supported during context switching */ + + printf("\nuser_main: FPU test\n"); + fpu_test(); + check_test_memory_usage(); +#endif + #ifndef CONFIG_DISABLE_PTHREAD /* Verify pthreads and pthread mutex */ diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h index 99290828e..a4af37f05 100644 --- a/apps/examples/ostest/ostest.h +++ b/apps/examples/ostest/ostest.h @@ -1,8 +1,8 @@ /**************************************************************************** - * examples/ostest/ostest.h + * apps/examples/ostest/ostest.h * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __OSTEST_H -#define __OSTEST_H +#ifndef __APPS_EXAMPLES_OSTEST_OSTEST_H +#define __APPS_EXAMPLES_OSTEST_OSTEST_H /**************************************************************************** * Included Files @@ -107,6 +107,10 @@ extern int dev_null(void); +/* fpu.c ********************************************************************/ + +extern void fpu_test(void); + /* mutex.c ******************************************************************/ extern void mutex_test(void); @@ -171,4 +175,4 @@ extern int sem_nfreeholders(void); # define sem_nfreeholders() #endif -#endif /* __OSTEST_H */ +#endif /* __APPS_EXAMPLES_OSTEST_OSTEST_H */ -- cgit v1.2.3