test_fp_sharing: Enable for Cortex-M4

Update the FP sharing test project for use with the Cortex-M4.

Change-Id: If04a191b26291058bd7002ce8a0939eda8a5eb48
Signed-off-by: Peter Mitsis <peter.mitsis@windriver.com>
This commit is contained in:
Peter Mitsis 2016-05-20 10:09:52 -04:00
parent 3490627a97
commit b4eee20e4b
12 changed files with 205 additions and 15 deletions

View file

@ -1,6 +1,6 @@
MDEF_FILE = prj.mdef
KERNEL_TYPE = micro
BOARD ?= qemu_x86
CONF_FILE = prj.conf
CONF_FILE = prj_$(ARCH).conf
include ${ZEPHYR_BASE}/Makefile.inc

View file

@ -35,6 +35,18 @@ or
--------------------------------------------------------------------------------
Advanced:
Depending upon the board's speed, the frequency of test output may range from
every few seconds to every few minutes. The speed of the test can be controlled
through the variable PI_NUM_ITERATIONS (default 700000). Lowering this value
will increase the test's speed, but at the expense of the calculation's
precision.
make qemu PI_NUM_ITERATIONS=100000
--------------------------------------------------------------------------------
Sample Output:
Floating point sharing tests started

View file

@ -0,0 +1,9 @@
CONFIG_FLOAT=y
CONFIG_FP_SHARING=y
CONFIG_STDOUT_CONSOLE=y
# Let stack canaries use non-random number generator.
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y

View file

@ -2,3 +2,11 @@ ccflags-y += -I${ZEPHYR_BASE}/tests/include
obj-y += main.o
obj-$(CONFIG_MICROKERNEL) += pi.o
# Some boards are significantly slower than others resulting in the test
# output being in the range of every few seconds to every few minutes. To
# compensate for this, one can control the number of iterations in the PI
# calculation through PI_NUM_ITERATIONS. Lowering this value will increase
# the speed of the test but it will come at the expense of precision.
PI_NUM_ITERATIONS ?= 700000
ccflags-y += "-DPI_NUM_ITERATIONS=${PI_NUM_ITERATIONS}"

View file

@ -37,7 +37,6 @@
* _load_all_float_registers()
* _load_then_store_all_float_registers()
* _store_all_float_registers()
* _store_non_volatile_float_registers()
*/
#if defined(CONFIG_ISA_IA32)
@ -74,7 +73,32 @@ struct fp_non_volatile_register_set {
#define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
#define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
#else /* ! CONFIG_ISA_IA32 */
#elif defined(CONFIG_CPU_CORTEX_M4)
#define FP_OPTION 0
/*
* Registers s0..s15 are volatile and do not
* need to be preserved across function calls.
*/
struct fp_volatile_register_set {
float s[16];
};
/*
* Registers s16..s31 are non-volatile and
* need to be preserved across function calls.
*/
struct fp_non_volatile_register_set {
float s[16];
};
#define SIZEOF_FP_VOLATILE_REGISTER_SET \
sizeof(struct fp_volatile_register_set)
#define SIZEOF_FP_NON_VOLATILE_REGISTER_SET \
sizeof(struct fp_non_volatile_register_set)
#else
#error "Architecture must provide the following definitions:\n" \
"\t'struct fp_volatile_registers'\n" \
@ -101,8 +125,6 @@ struct fp_register_set {
#define MAIN_FLOAT_REG_CHECK_BYTE (unsigned char)0xe5
#define FIBER_FLOAT_REG_CHECK_BYTE (unsigned char)0xf9
void _store_non_volatile_float_registers(struct fp_non_volatile_register_set *regs);
extern int fpu_sharing_error;
#endif /* _FLOATCONTEXT_H */

View file

@ -0,0 +1,100 @@
/**
* @file
* @brief ARM Cortex-M4 GCC specific floating point register macros
*/
/*
* Copyright (c) 2016, Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _FLOAT_REGS_ARM_GCC_H
#define _FLOAT_REGS_ARM_GCC_H
#if !defined(__GNUC__) || !defined(CONFIG_CPU_CORTEX_M4)
#error __FILE__ goes only with Cortex-M4 GCC
#endif
#include <toolchain.h>
#include "float_context.h"
/**
*
* @brief Load all floating point registers
*
* This function loads ALL floating point registers pointed to by @a regs.
* It is expected that a subsequent call to _store_all_float_registers()
* will be issued to dump the floating point registers to memory.
*
* The format/organization of 'struct fp_register_set'; the generic C test
* code (main.c) merely treat the register set as an array of bytes.
*
* The only requirement is that the arch specific implementations of
* _load_all_float_registers() and _store_all_float_registers() agree
* on the format.
*
* @return N/A
*/
static inline void _load_all_float_registers(struct fp_register_set *regs)
{
__asm__ volatile (
"vldmia %0, {s0-s15};\n\t"
"vldmia %1, {s16-s31};\n\t"
:: "r" (&regs->fp_volatile), "r" (&regs->fp_non_volatile)
);
}
/**
*
* @brief Dump all floating point registers to memory
*
* This function stores ALL floating point registers to the memory buffer
* specified by @a regs. It is expected that a previous invocation of
* _load_all_float_registers() occurred to load all the floating point
* registers from a memory buffer.
*
* @return N/A
*/
static inline void _store_all_float_registers(struct fp_register_set *regs)
{
__asm__ volatile (
"vstmia %0, {s0-s15};\n\t"
"vstmia %1, {s16-s31};\n\t"
:: "r" (&regs->fp_volatile), "r" (&regs->fp_non_volatile)
: "memory"
);
}
/**
*
* @brief Load then dump all float registers to memory
*
* This function loads ALL floating point registers from the memory buffer
* specified by @a regs, and then stores them back to that buffer.
*
* This routine is called by a high priority thread prior to calling a primitive
* that pends and triggers a co-operative context switch to a low priority
* thread.
*
* @return N/A
*/
static inline void _load_then_store_all_float_registers(struct fp_register_set *regs)
{
_load_all_float_registers(regs);
_store_all_float_registers(regs);
}
#endif /* _FLOAT_REGS_ARM_GCC_H */

View file

@ -57,11 +57,19 @@ x87 FPU registers are being saved/restored.
#include <zephyr.h>
#if defined(__GNUC__)
#include <float_regs_x86_gcc.h>
#else
#include <float_regs_x86_other.h>
#endif /* __GNUC__ */
#if defined(CONFIG_ISA_IA32)
#if defined(__GNUC__)
#include <float_regs_x86_gcc.h>
#else
#include <float_regs_x86_other.h>
#endif /* __GNUC__ */
#elif defined(CONFIG_CPU_CORTEX_M4)
#if defined(__GNUC__)
#include <float_regs_arm_gcc.h>
#else
#include <float_regs_arm_other.h>
#endif /* __GNUC__ */
#endif
#include <arch/cpu.h>
#include <tc_util.h>
@ -244,6 +252,7 @@ void load_store_low(void)
return;
}
#if defined(CONFIG_ISA_IA32)
/*
* After every 1000 iterations (arbitrarily chosen), explicitly
* disable floating point operations for the task. The
@ -258,6 +267,15 @@ void load_store_low(void)
if ((load_store_low_count % 1000) == 0) {
task_float_disable(sys_thread_self_get());
}
#elif defined(CONFIG_CPU_CORTEX_M4)
/*
* The routine task_float_disable() allows for thread-level
* granularity for disabling floating point. Furthermore, it
* is useful for testing on the fly thread enabling of floating
* point. Neither of these capabilities are currently supported
* for ARM.
*/
#endif
}
}
@ -312,7 +330,6 @@ void load_store_high(void)
reg_set_ptr[i] = init_byte++;
}
#if defined(CONFIG_ISA_IA32)
/*
* Utilize an architecture specific function to load all the
* floating point registers with the contents of the
@ -333,7 +350,6 @@ void load_store_high(void)
*/
_load_then_store_all_float_registers(&float_reg_set);
#endif
/*
* Relinquish the processor for the remainder of the current

View file

@ -45,7 +45,10 @@ has occurred.
#include <float_context.h>
#define PI_NUM_ITERATIONS 700000
/*
* PI_NUM_ITERATIONS: This macro is defined in the project's Makefile and
* is configurable from the command line.
*/
static double reference_pi = 0.0f;

View file

@ -1,4 +1,4 @@
[test]
[test_x86]
tags = core
platform_whitelist = qemu_x86
slow = true
@ -6,3 +6,10 @@ slow = true
# under normal circumstances. On a heavily loaded machine, extra time
# may be required--hence the 10 minute timeout.
timeout = 600
[test_arm]
tags = core
platform_whitelist = frdm_k64f
slow = true
extra_args = PI_NUM_ITERATIONS=70000
timeout = 600

View file

@ -0,0 +1,9 @@
CONFIG_FLOAT=y
CONFIG_FP_SHARING=y
CONFIG_STDOUT_CONSOLE=y
# Let stack canaries use non-random number generator.
# This option is NOT to be used in production code.
CONFIG_TEST_RANDOM_GENERATOR=y

View file

@ -1,3 +1,7 @@
[test]
[test_x86]
tags = core
platform_whitelist = qemu_x86
[test_arm]
tags = core
platform_whitelist = frdm_k64f