Add software
This commit is contained in:
@ -0,0 +1,156 @@
|
||||
#
|
||||
# !!!! Do NOT edit this makefile with an editor which replace tabs by spaces !!!!
|
||||
#
|
||||
##############################################################################################
|
||||
#
|
||||
# On command line:
|
||||
#
|
||||
# make all = Create project
|
||||
#
|
||||
# make clean = Clean project files.
|
||||
#
|
||||
# To rebuild project do "make clean" and "make all".
|
||||
#
|
||||
|
||||
##############################################################################################
|
||||
# Start of default section
|
||||
#
|
||||
|
||||
TRGT = mingw32-
|
||||
CC = $(TRGT)gcc
|
||||
AS = $(TRGT)gcc -x assembler-with-cpp
|
||||
COV = gcov
|
||||
|
||||
# List all default C defines here, like -D_DEBUG=1
|
||||
DDEFS = -DSIMULATOR
|
||||
|
||||
# List all default ASM defines here, like -D_DEBUG=1
|
||||
DADEFS =
|
||||
|
||||
# List all default directories to look for include files here
|
||||
DINCDIR =
|
||||
|
||||
# List the default directory to look for the libraries here
|
||||
DLIBDIR =
|
||||
|
||||
# List all default libraries here
|
||||
DLIBS = -lws2_32
|
||||
|
||||
# Must be a directory in ${CHIBIOS}/os/hal/platforms
|
||||
HOST_TYPE = Win32
|
||||
|
||||
#
|
||||
# End of default section
|
||||
##############################################################################################
|
||||
|
||||
##############################################################################################
|
||||
# Start of user section
|
||||
#
|
||||
|
||||
# Define project name here
|
||||
PROJECT = ch
|
||||
|
||||
# Define linker script file here
|
||||
LDSCRIPT=
|
||||
|
||||
# List all user C define here, like -D_DEBUG=1
|
||||
UDEFS =
|
||||
|
||||
# Define ASM defines here
|
||||
UADEFS =
|
||||
|
||||
# Imported source files
|
||||
CHIBIOS = ../..
|
||||
include $(CHIBIOS)/boards/simulator/board.mk
|
||||
include ${CHIBIOS}/os/hal/hal.mk
|
||||
include ${CHIBIOS}/os/hal/platforms/$(HOST_TYPE)/platform.mk
|
||||
include ${CHIBIOS}/os/ports/GCC/SIMIA32/port.mk
|
||||
include ${CHIBIOS}/os/kernel/kernel.mk
|
||||
include ${CHIBIOS}/test/test.mk
|
||||
|
||||
# List C source files here
|
||||
SRC = ${PORTSRC} \
|
||||
${KERNSRC} \
|
||||
${TESTSRC} \
|
||||
${HALSRC} \
|
||||
${PLATFORMSRC} \
|
||||
$(BOARDSRC) \
|
||||
${CHIBIOS}/os/hal/platforms/$(HOST_TYPE)/console.c \
|
||||
main.c
|
||||
|
||||
# List ASM source files here
|
||||
ASRC =
|
||||
|
||||
# List all user directories here
|
||||
UINCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
|
||||
$(CHIBIOS)/os/various
|
||||
|
||||
# List the user directory to look for the libraries here
|
||||
ULIBDIR =
|
||||
|
||||
# List all user libraries here
|
||||
ULIBS =
|
||||
|
||||
# Define optimisation level here
|
||||
OPT = -ggdb -O0 -fomit-frame-pointer -fprofile-arcs -ftest-coverage
|
||||
|
||||
#
|
||||
# End of user defines
|
||||
##############################################################################################
|
||||
|
||||
|
||||
INCDIR = $(patsubst %,-I%,$(DINCDIR) $(UINCDIR))
|
||||
LIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
|
||||
DEFS = $(DDEFS) $(UDEFS)
|
||||
ADEFS = $(DADEFS) $(UADEFS)
|
||||
OBJS = $(ASRC:.s=.o) $(SRC:.c=.o)
|
||||
LIBS = $(DLIBS) $(ULIBS)
|
||||
|
||||
LDFLAGS = -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch -lgcov $(LIBDIR)
|
||||
ASFLAGS = -Wa,-amhls=$(<:.s=.lst) $(ADEFS)
|
||||
CPFLAGS = $(OPT) -Wall -Wextra -Wstrict-prototypes -fverbose-asm -Wa,-alms=$(<:.c=.lst) $(DEFS)
|
||||
|
||||
# Generate dependency information
|
||||
CPFLAGS += -MD -MP -MF .dep/$(@F).d
|
||||
|
||||
#
|
||||
# makefile rules
|
||||
#
|
||||
|
||||
all: $(OBJS) $(PROJECT).exe
|
||||
|
||||
%o : %c
|
||||
$(CC) -c $(CPFLAGS) -I . $(INCDIR) $< -o $@
|
||||
|
||||
%o : %s
|
||||
$(AS) -c $(ASFLAGS) $< -o $@
|
||||
|
||||
%exe: $(OBJS)
|
||||
$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
|
||||
|
||||
.PHONY: gcov
|
||||
gcov:
|
||||
-mkdir gcov
|
||||
$(COV) -u $(subst /,\,$(KERNSRC))
|
||||
-mv -f *.gcov ./gcov
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -f $(OBJS)
|
||||
-rm -f $(PROJECT).exe
|
||||
-rm -f $(PROJECT).map
|
||||
-rm -f $(SRC:.c=.c.bak)
|
||||
-rm -f $(SRC:.c=.lst)
|
||||
-rm -f $(SRC:.c=.gcno)
|
||||
-rm -f $(SRC:.c=.gcda)
|
||||
-rm -f $(ASRC:.s=.s.bak)
|
||||
-rm -f $(ASRC:.s=.lst)
|
||||
-rm -fR .dep
|
||||
|
||||
#
|
||||
# Include the dependency files, should be the last of the makefile
|
||||
#
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
# *** EOF ***
|
@ -0,0 +1,532 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/chconf.h
|
||||
* @brief Configuration file template.
|
||||
* @details A copy of this file must be placed in each project directory, it
|
||||
* contains the application specific kernel settings.
|
||||
*
|
||||
* @addtogroup config
|
||||
* @details Kernel related settings and hooks.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHCONF_H_
|
||||
#define _CHCONF_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Kernel parameters and options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief System tick frequency.
|
||||
* @details Frequency of the system timer that drives the system ticks. This
|
||||
* setting also defines the system tick time unit.
|
||||
*/
|
||||
#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
|
||||
#define CH_FREQUENCY 1000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Round robin interval.
|
||||
* @details This constant is the number of system ticks allowed for the
|
||||
* threads before preemption occurs. Setting this value to zero
|
||||
* disables the preemption for threads with equal priority and the
|
||||
* round robin becomes cooperative. Note that higher priority
|
||||
* threads can still preempt, the kernel is always preemptive.
|
||||
*
|
||||
* @note Disabling the round robin preemption makes the kernel more compact
|
||||
* and generally faster.
|
||||
*/
|
||||
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
|
||||
#define CH_TIME_QUANTUM 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Managed RAM size.
|
||||
* @details Size of the RAM area to be managed by the OS. If set to zero
|
||||
* then the whole available RAM is used. The core memory is made
|
||||
* available to the heap allocator and/or can be used directly through
|
||||
* the simplified core memory allocator.
|
||||
*
|
||||
* @note In order to let the OS manage the whole RAM the linker script must
|
||||
* provide the @p __heap_base__ and @p __heap_end__ symbols.
|
||||
* @note Requires @p CH_USE_MEMCORE.
|
||||
*/
|
||||
#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
|
||||
#define CH_MEMCORE_SIZE 0x20000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Idle thread automatic spawn suppression.
|
||||
* @details When this option is activated the function @p chSysInit()
|
||||
* does not spawn the idle thread automatically. The application has
|
||||
* then the responsibility to do one of the following:
|
||||
* - Spawn a custom idle thread at priority @p IDLEPRIO.
|
||||
* - Change the main() thread priority to @p IDLEPRIO then enter
|
||||
* an endless loop. In this scenario the @p main() thread acts as
|
||||
* the idle thread.
|
||||
* .
|
||||
* @note Unless an idle thread is spawned the @p main() thread must not
|
||||
* enter a sleep state.
|
||||
*/
|
||||
#if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__)
|
||||
#define CH_NO_IDLE_THREAD FALSE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Performance options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief OS optimization.
|
||||
* @details If enabled then time efficient rather than space efficient code
|
||||
* is used when two possible implementations exist.
|
||||
*
|
||||
* @note This is not related to the compiler optimization options.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__)
|
||||
#define CH_OPTIMIZE_SPEED FALSE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Subsystem options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Threads registry APIs.
|
||||
* @details If enabled then the registry APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_REGISTRY TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Threads synchronization APIs.
|
||||
* @details If enabled then the @p chThdWait() function is included in
|
||||
* the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
|
||||
#define CH_USE_WAITEXIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Semaphores APIs.
|
||||
* @details If enabled then the Semaphores APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_SEMAPHORES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Semaphores queuing mode.
|
||||
* @details If enabled then the threads are enqueued on semaphores by
|
||||
* priority rather than in FIFO order.
|
||||
*
|
||||
* @note The default is @p FALSE. Enable this if you have special requirements.
|
||||
* @note Requires @p CH_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Atomic semaphore API.
|
||||
* @details If enabled then the semaphores the @p chSemSignalWait() API
|
||||
* is included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__)
|
||||
#define CH_USE_SEMSW TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Mutexes APIs.
|
||||
* @details If enabled then the mutexes APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MUTEXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Conditional Variables APIs.
|
||||
* @details If enabled then the conditional variables APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_MUTEXES.
|
||||
*/
|
||||
#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__)
|
||||
#define CH_USE_CONDVARS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Conditional Variables APIs with timeout.
|
||||
* @details If enabled then the conditional variables APIs with timeout
|
||||
* specification are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_CONDVARS.
|
||||
*/
|
||||
#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define CH_USE_CONDVARS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Events Flags APIs.
|
||||
* @details If enabled then the event flags APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
|
||||
#define CH_USE_EVENTS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Events Flags APIs with timeout.
|
||||
* @details If enabled then the events APIs with timeout specification
|
||||
* are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_EVENTS.
|
||||
*/
|
||||
#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define CH_USE_EVENTS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Synchronous Messages APIs.
|
||||
* @details If enabled then the synchronous messages APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MESSAGES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Synchronous Messages queuing mode.
|
||||
* @details If enabled then messages are served by priority rather than in
|
||||
* FIFO order.
|
||||
*
|
||||
* @note The default is @p FALSE. Enable this if you have special requirements.
|
||||
* @note Requires @p CH_USE_MESSAGES.
|
||||
*/
|
||||
#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MESSAGES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Mailboxes APIs.
|
||||
* @details If enabled then the asynchronous messages (mailboxes) APIs are
|
||||
* included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MAILBOXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I/O Queues APIs.
|
||||
* @details If enabled then the I/O queues APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_QUEUES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Core Memory Manager APIs.
|
||||
* @details If enabled then the core memory manager APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MEMCORE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Heap Allocator APIs.
|
||||
* @details If enabled then the memory heap allocator APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or
|
||||
* @p CH_USE_SEMAPHORES.
|
||||
* @note Mutexes are recommended.
|
||||
*/
|
||||
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
|
||||
#define CH_USE_HEAP TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief C-runtime allocator.
|
||||
* @details If enabled the the heap allocator APIs just wrap the C-runtime
|
||||
* @p malloc() and @p free() functions.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
* @note Requires @p CH_USE_HEAP.
|
||||
* @note The C-runtime may or may not require @p CH_USE_MEMCORE, see the
|
||||
* appropriate documentation.
|
||||
*/
|
||||
#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MALLOC_HEAP FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Memory Pools Allocator APIs.
|
||||
* @details If enabled then the memory pools allocator APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MEMPOOLS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Dynamic Threads APIs.
|
||||
* @details If enabled then the dynamic threads creation APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_WAITEXIT.
|
||||
* @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS.
|
||||
*/
|
||||
#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__)
|
||||
#define CH_USE_DYNAMIC TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Debug options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Debug option, system state check.
|
||||
* @details If enabled the correct call protocol for system APIs is checked
|
||||
* at runtime.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_SYSTEM_STATE_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, parameters checks.
|
||||
* @details If enabled then the checks on the API functions input
|
||||
* parameters are activated.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, consistency checks.
|
||||
* @details If enabled then all the assertions in the kernel code are
|
||||
* activated. This includes consistency checks inside the kernel,
|
||||
* runtime anomalies and port-defined checks.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, trace buffer.
|
||||
* @details If enabled then the context switch circular trace buffer is
|
||||
* activated.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_ENABLE_TRACE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, stack checks.
|
||||
* @details If enabled then a runtime stack check is performed.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
* @note The stack check is performed in a architecture/port dependent way.
|
||||
* It may not be implemented or some ports.
|
||||
* @note The default failure mode is to halt the system with the global
|
||||
* @p panic_msg variable set to @p NULL.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_ENABLE_STACK_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, stacks initialization.
|
||||
* @details If enabled then the threads working area is filled with a byte
|
||||
* value when a thread is created. This can be useful for the
|
||||
* runtime measurement of the used stack.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_FILL_THREADS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, threads profiling.
|
||||
* @details If enabled then a field is added to the @p Thread structure that
|
||||
* counts the system ticks occurred while executing the thread.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note This debug option is defaulted to TRUE because it is required by
|
||||
* some test cases into the test suite.
|
||||
*/
|
||||
#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_THREADS_PROFILING TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Kernel hooks
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Threads descriptor structure extension.
|
||||
* @details User fields added to the end of the @p Thread structure.
|
||||
*/
|
||||
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
|
||||
#define THREAD_EXT_FIELDS \
|
||||
/* Add threads custom fields here.*/
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Threads initialization hook.
|
||||
* @details User initialization code added to the @p chThdInit() API.
|
||||
*
|
||||
* @note It is invoked from within @p chThdInit() and implicitly from all
|
||||
* the threads creation APIs.
|
||||
*/
|
||||
#if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
|
||||
#define THREAD_EXT_INIT_HOOK(tp) { \
|
||||
/* Add threads initialization code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Threads finalization hook.
|
||||
* @details User finalization code added to the @p chThdExit() API.
|
||||
*
|
||||
* @note It is inserted into lock zone.
|
||||
* @note It is also invoked when the threads simply return in order to
|
||||
* terminate.
|
||||
*/
|
||||
#if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__)
|
||||
#define THREAD_EXT_EXIT_HOOK(tp) { \
|
||||
/* Add threads finalization code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Context switch hook.
|
||||
* @details This hook is invoked just before switching between threads.
|
||||
*/
|
||||
#if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__)
|
||||
#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \
|
||||
/* Context switch code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Idle Loop hook.
|
||||
* @details This hook is continuously invoked by the idle thread loop.
|
||||
*/
|
||||
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
|
||||
#define IDLE_LOOP_HOOK() { \
|
||||
/* Idle loop code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System tick event hook.
|
||||
* @details This hook is invoked in the system tick handler immediately
|
||||
* after processing the virtual timers queue.
|
||||
*/
|
||||
#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__)
|
||||
#define SYSTEM_TICK_EVENT_HOOK() { \
|
||||
/* System tick event code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief System halt hook.
|
||||
* @details This hook is invoked in case to a system halting error before
|
||||
* the system is halted.
|
||||
*/
|
||||
#if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
|
||||
#define SYSTEM_HALT_HOOK() { \
|
||||
/* System halt code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Port-specific settings (override port settings defaulted in chcore.h). */
|
||||
/*===========================================================================*/
|
||||
|
||||
#endif /* _CHCONF_H_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,312 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/halconf.h
|
||||
* @brief HAL configuration header.
|
||||
* @details HAL configuration file, this file allows to enable or disable the
|
||||
* various device drivers from your application. You may also use
|
||||
* this file in order to override the device drivers default settings.
|
||||
*
|
||||
* @addtogroup HAL_CONF
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HALCONF_H_
|
||||
#define _HALCONF_H_
|
||||
|
||||
/*#include "mcuconf.h"*/
|
||||
|
||||
/**
|
||||
* @brief Enables the TM subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_TM) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_TM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the PAL subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_PAL FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ADC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_ADC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the CAN subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_CAN FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the EXT subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_EXT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the GPT subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_GPT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the I2C subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_I2C FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ICU subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_ICU FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_MAC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MMC_SPI subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_MMC_SPI FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the PWM subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_PWM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the RTC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_RTC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SDC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SDC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SERIAL FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL over USB subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SERIAL_USB FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SPI subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SPI FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the UART subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_UART FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the USB subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_USB FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* ADC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define ADC_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define ADC_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* CAN driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Sleep mode related APIs inclusion switch.
|
||||
*/
|
||||
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
|
||||
#define CAN_USE_SLEEP_MODE TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I2C driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the mutual exclusion APIs on the I2C bus.
|
||||
*/
|
||||
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define I2C_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MAC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables an event sources for incoming packets.
|
||||
*/
|
||||
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
|
||||
#define MAC_USE_ZERO_COPY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables an event sources for incoming packets.
|
||||
*/
|
||||
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
|
||||
#define MAC_USE_EVENTS TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MMC_SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
* This option is recommended also if the SPI driver does not
|
||||
* use a DMA channel and heavily loads the CPU.
|
||||
*/
|
||||
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
#define MMC_NICE_WAITING TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SDC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Number of initialization attempts before rejecting the card.
|
||||
* @note Attempts are performed at 10mS intervals.
|
||||
*/
|
||||
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
|
||||
#define SDC_INIT_RETRY 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Include support for MMC cards.
|
||||
* @note MMC support is not yet implemented so this option must be kept
|
||||
* at @p FALSE.
|
||||
*/
|
||||
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
|
||||
#define SDC_MMC_SUPPORT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
*/
|
||||
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
#define SDC_NICE_WAITING TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SERIAL driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Default bit rate.
|
||||
* @details Configuration parameter, this is the baud rate selected for the
|
||||
* default configuration.
|
||||
*/
|
||||
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_DEFAULT_BITRATE 38400
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Serial buffers size.
|
||||
* @details Configuration parameter, you can change the depth of the queue
|
||||
* buffers depending on the requirements of your application.
|
||||
* @note The default is 64 bytes for both the transmission and receive
|
||||
* buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_BUFFERS_SIZE 16
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define SPI_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define SPI_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
#endif /* _HALCONF_H_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "test.h"
|
||||
#include "console.h"
|
||||
|
||||
/*
|
||||
* Simulator main.
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
msg_t result;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
/*
|
||||
* System initializations.
|
||||
* - HAL initialization, this also initializes the configured device drivers
|
||||
* and performs the board-specific initializations.
|
||||
* - Kernel initialization, the main() function becomes a thread and the
|
||||
* RTOS is active.
|
||||
*/
|
||||
halInit();
|
||||
conInit();
|
||||
chSysInit();
|
||||
|
||||
result = TestThread(&CD1);
|
||||
if (result)
|
||||
exit(1);
|
||||
else
|
||||
exit(0);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
In order to compute the code coverage:
|
||||
|
||||
- Build the test application: make
|
||||
- Run the test suite: ch
|
||||
- Compute the code coverage: make gcov
|
||||
- Clear everything: make clean
|
390
Software/portapack-mayhem/firmware/chibios/test/test.c
Normal file
390
Software/portapack-mayhem/firmware/chibios/test/test.c
Normal file
@ -0,0 +1,390 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test.c
|
||||
* @brief Tests support code.
|
||||
*
|
||||
* @addtogroup test
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "test.h"
|
||||
#include "testthd.h"
|
||||
#include "testsem.h"
|
||||
#include "testmtx.h"
|
||||
#include "testmsg.h"
|
||||
#include "testmbox.h"
|
||||
#include "testevt.h"
|
||||
#include "testheap.h"
|
||||
#include "testpools.h"
|
||||
#include "testdyn.h"
|
||||
#include "testqueues.h"
|
||||
#include "testbmk.h"
|
||||
|
||||
/*
|
||||
* Array of all the test patterns.
|
||||
*/
|
||||
static ROMCONST struct testcase * ROMCONST *patterns[] = {
|
||||
patternthd,
|
||||
patternsem,
|
||||
patternmtx,
|
||||
patternmsg,
|
||||
patternmbox,
|
||||
patternevt,
|
||||
patternheap,
|
||||
patternpools,
|
||||
patterndyn,
|
||||
patternqueues,
|
||||
patternbmk,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool_t local_fail, global_fail;
|
||||
static unsigned failpoint;
|
||||
static char tokens_buffer[MAX_TOKENS];
|
||||
static char *tokp;
|
||||
|
||||
/*
|
||||
* Static working areas, the following areas can be used for threads or
|
||||
* used as temporary buffers.
|
||||
*/
|
||||
union test_buffers test;
|
||||
|
||||
/*
|
||||
* Pointers to the spawned threads.
|
||||
*/
|
||||
Thread *threads[MAX_THREADS];
|
||||
|
||||
/*
|
||||
* Pointers to the working areas.
|
||||
*/
|
||||
void * ROMCONST wa[5] = {test.wa.T0, test.wa.T1, test.wa.T2,
|
||||
test.wa.T3, test.wa.T4};
|
||||
|
||||
/*
|
||||
* Console output.
|
||||
*/
|
||||
static BaseSequentialStream *chp;
|
||||
|
||||
/**
|
||||
* @brief Prints a decimal unsigned number.
|
||||
*
|
||||
* @param[in] n the number to be printed
|
||||
*/
|
||||
void test_printn(uint32_t n) {
|
||||
char buf[16], *p;
|
||||
|
||||
if (!n)
|
||||
chSequentialStreamPut(chp, '0');
|
||||
else {
|
||||
p = buf;
|
||||
while (n)
|
||||
*p++ = (n % 10) + '0', n /= 10;
|
||||
while (p > buf)
|
||||
chSequentialStreamPut(chp, *--p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prints a line without final end-of-line.
|
||||
*
|
||||
* @param[in] msgp the message
|
||||
*/
|
||||
void test_print(const char *msgp) {
|
||||
|
||||
while (*msgp)
|
||||
chSequentialStreamPut(chp, *msgp++);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prints a line.
|
||||
*
|
||||
* @param[in] msgp the message
|
||||
*/
|
||||
void test_println(const char *msgp) {
|
||||
|
||||
test_print(msgp);
|
||||
chSequentialStreamWrite(chp, (const uint8_t *)"\r\n", 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokens.
|
||||
*/
|
||||
static void clear_tokens(void) {
|
||||
|
||||
tokp = tokens_buffer;
|
||||
}
|
||||
|
||||
static void print_tokens(void) {
|
||||
char *cp = tokens_buffer;
|
||||
|
||||
while (cp < tokp)
|
||||
chSequentialStreamPut(chp, *cp++);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Emits a token into the tokens buffer.
|
||||
*
|
||||
* @param[in] token the token as a char
|
||||
*/
|
||||
void test_emit_token(char token) {
|
||||
|
||||
chSysLock();
|
||||
*tokp++ = token;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Assertions.
|
||||
*/
|
||||
bool_t _test_fail(unsigned point) {
|
||||
|
||||
local_fail = TRUE;
|
||||
global_fail = TRUE;
|
||||
failpoint = point;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t _test_assert(unsigned point, bool_t condition) {
|
||||
|
||||
if (!condition)
|
||||
return _test_fail(point);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t _test_assert_sequence(unsigned point, char *expected) {
|
||||
char *cp = tokens_buffer;
|
||||
while (cp < tokp) {
|
||||
if (*cp++ != *expected++)
|
||||
return _test_fail(point);
|
||||
}
|
||||
if (*expected)
|
||||
return _test_fail(point);
|
||||
clear_tokens();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t _test_assert_time_window(unsigned point, systime_t start, systime_t end) {
|
||||
|
||||
return _test_assert(point, chTimeIsWithin(start, end));
|
||||
}
|
||||
|
||||
/*
|
||||
* Threads utils.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets a termination request in all the test-spawned threads.
|
||||
*/
|
||||
void test_terminate_threads(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
if (threads[i])
|
||||
chThdTerminate(threads[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for the completion of all the test-spawned threads.
|
||||
*/
|
||||
void test_wait_threads(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
if (threads[i] != NULL) {
|
||||
chThdWait(threads[i]);
|
||||
threads[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if CH_DBG_THREADS_PROFILING
|
||||
/**
|
||||
* @brief CPU pulse.
|
||||
* @note The current implementation is not totally reliable.
|
||||
*
|
||||
* @param[in] duration CPU pulse duration in milliseconds
|
||||
*/
|
||||
void test_cpu_pulse(unsigned duration) {
|
||||
systime_t start, end, now;
|
||||
|
||||
start = chThdSelf()->p_time;
|
||||
end = start + MS2ST(duration);
|
||||
do {
|
||||
now = chThdSelf()->p_time;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
while (end > start ? (now >= start) && (now < end) :
|
||||
(now >= start) || (now < end));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delays execution until next system time tick.
|
||||
*
|
||||
* @return The system time.
|
||||
*/
|
||||
systime_t test_wait_tick(void) {
|
||||
|
||||
chThdSleep(1);
|
||||
return chTimeNow();
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer utils.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set to @p TRUE when the test timer reaches its deadline.
|
||||
*/
|
||||
bool_t test_timer_done;
|
||||
|
||||
static VirtualTimer vt;
|
||||
static void tmr(void *p) {
|
||||
(void)p;
|
||||
|
||||
test_timer_done = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the test timer.
|
||||
*
|
||||
* @param[in] ms time in milliseconds
|
||||
*/
|
||||
void test_start_timer(unsigned ms) {
|
||||
|
||||
systime_t duration = MS2ST(ms);
|
||||
test_timer_done = FALSE;
|
||||
chVTSet(&vt, duration, tmr, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test suite execution.
|
||||
*/
|
||||
static void execute_test(const struct testcase *tcp) {
|
||||
int i;
|
||||
|
||||
/* Initialization */
|
||||
clear_tokens();
|
||||
local_fail = FALSE;
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
threads[i] = NULL;
|
||||
|
||||
if (tcp->setup != NULL)
|
||||
tcp->setup();
|
||||
tcp->execute();
|
||||
if (tcp->teardown != NULL)
|
||||
tcp->teardown();
|
||||
|
||||
test_wait_threads();
|
||||
}
|
||||
|
||||
static void print_line(void) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 76; i++)
|
||||
chSequentialStreamPut(chp, '-');
|
||||
chSequentialStreamWrite(chp, (const uint8_t *)"\r\n", 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test execution thread function.
|
||||
*
|
||||
* @param[in] p pointer to a @p BaseChannel object for test output
|
||||
* @return A failure boolean value.
|
||||
*/
|
||||
msg_t TestThread(void *p) {
|
||||
int i, j;
|
||||
|
||||
chp = p;
|
||||
test_println("");
|
||||
test_println("*** ChibiOS/RT test suite");
|
||||
test_println("***");
|
||||
test_print("*** Kernel: ");
|
||||
test_println(CH_KERNEL_VERSION);
|
||||
test_print("*** Compiled: ");
|
||||
test_println(__DATE__ " - " __TIME__);
|
||||
#ifdef CH_COMPILER_NAME
|
||||
test_print("*** Compiler: ");
|
||||
test_println(CH_COMPILER_NAME);
|
||||
#endif
|
||||
test_print("*** Architecture: ");
|
||||
test_println(CH_ARCHITECTURE_NAME);
|
||||
#ifdef CH_CORE_VARIANT_NAME
|
||||
test_print("*** Core Variant: ");
|
||||
test_println(CH_CORE_VARIANT_NAME);
|
||||
#endif
|
||||
#ifdef CH_PORT_INFO
|
||||
test_print("*** Port Info: ");
|
||||
test_println(CH_PORT_INFO);
|
||||
#endif
|
||||
#ifdef PLATFORM_NAME
|
||||
test_print("*** Platform: ");
|
||||
test_println(PLATFORM_NAME);
|
||||
#endif
|
||||
#ifdef BOARD_NAME
|
||||
test_print("*** Test Board: ");
|
||||
test_println(BOARD_NAME);
|
||||
#endif
|
||||
test_println("");
|
||||
|
||||
global_fail = FALSE;
|
||||
i = 0;
|
||||
while (patterns[i]) {
|
||||
j = 0;
|
||||
while (patterns[i][j]) {
|
||||
print_line();
|
||||
test_print("--- Test Case ");
|
||||
test_printn(i + 1);
|
||||
test_print(".");
|
||||
test_printn(j + 1);
|
||||
test_print(" (");
|
||||
test_print(patterns[i][j]->name);
|
||||
test_println(")");
|
||||
#if DELAY_BETWEEN_TESTS > 0
|
||||
chThdSleepMilliseconds(DELAY_BETWEEN_TESTS);
|
||||
#endif
|
||||
execute_test(patterns[i][j]);
|
||||
if (local_fail) {
|
||||
test_print("--- Result: FAILURE (#");
|
||||
test_printn(failpoint);
|
||||
test_print(" [");
|
||||
print_tokens();
|
||||
test_println("])");
|
||||
}
|
||||
else
|
||||
test_println("--- Result: SUCCESS");
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
print_line();
|
||||
test_println("");
|
||||
test_print("Final result: ");
|
||||
if (global_fail)
|
||||
test_println("FAILURE");
|
||||
else
|
||||
test_println("SUCCESS");
|
||||
|
||||
return (msg_t)global_fail;
|
||||
}
|
||||
|
||||
/** @} */
|
20
Software/portapack-mayhem/firmware/chibios/test/test.cmake
Normal file
20
Software/portapack-mayhem/firmware/chibios/test/test.cmake
Normal file
@ -0,0 +1,20 @@
|
||||
# List of all the ChibiOS/RT test files.
|
||||
set(TESTSRC
|
||||
${CHIBIOS}/test/test.c
|
||||
${CHIBIOS}/test/testthd.c
|
||||
${CHIBIOS}/test/testsem.c
|
||||
${CHIBIOS}/test/testmtx.c
|
||||
${CHIBIOS}/test/testmsg.c
|
||||
${CHIBIOS}/test/testmbox.c
|
||||
${CHIBIOS}/test/testevt.c
|
||||
${CHIBIOS}/test/testheap.c
|
||||
${CHIBIOS}/test/testpools.c
|
||||
${CHIBIOS}/test/testdyn.c
|
||||
${CHIBIOS}/test/testqueues.c
|
||||
${CHIBIOS}/test/testbmk.c
|
||||
)
|
||||
|
||||
# Required include directories
|
||||
set(TESTINC
|
||||
${CHIBIOS}/test
|
||||
)
|
82
Software/portapack-mayhem/firmware/chibios/test/test.dox
Normal file
82
Software/portapack-mayhem/firmware/chibios/test/test.dox
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup test Test Runtime
|
||||
* @details Runtime code for the test suite execution, this code is not part
|
||||
* of the OS and should not be included in user applications.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page testsuite Testing Strategy
|
||||
* <h2>Description</h2>
|
||||
* Most of the ChibiOS/RT demos link a set of software modules (test suite) in
|
||||
* order to verify the proper working of the kernel, the port and the demo
|
||||
* itself.
|
||||
*
|
||||
* <h2>Strategy by Component</h2>
|
||||
* The OS components are tested in various modes depending on their importance:
|
||||
* - <b>Kernel</b>. The kernel code is subject to rigorous testing. The test
|
||||
* suite aims to test <b>all</b> the kernel code and reach a code coverage
|
||||
* as close to 100% as possible. In addition to the code coverage, the kernel
|
||||
* code is tested for <b>functionality</b> and benchmarked for <b>speed</b>
|
||||
* and <b>size</b> before each stable release. In addition to the code
|
||||
* coverage and functional testing a <b>batch compilation test</b> is
|
||||
* performed before each release, the kernel is compiled by alternatively
|
||||
* enabling and disabling all the various configuration options, the
|
||||
* kernel code is expected to compile without errors nor warnings and
|
||||
* execute the test suite without failures (a specific simulator is used
|
||||
* for this execution test, it is done automatically by a script because
|
||||
* the entire sequence can take hours).<br>
|
||||
* All the tests results are included as reports in the OS distribution
|
||||
* under <tt>./docs/reports</tt>.
|
||||
* - <b>Ports</b>. The port code is tested by executing the kernel test
|
||||
* suite on the target hardware. A port is validated only if it passes all
|
||||
* the tests. Speed and size benchmarks for all the supported architectures
|
||||
* are performed, both size and speed regressions are <b>monitored</b>.
|
||||
* - <b>HAL</b>. The HAL high level code and device drivers implementations
|
||||
* are tested through specific test applications under <tt>./testhal</tt>.
|
||||
* - <b>Various</b>. The miscellaneous code is tested by use in the various
|
||||
* demos.
|
||||
* - <b>External Code</b>. Not tested, external libraries or components are
|
||||
* used as-is or with minor patching where required, problems are usually
|
||||
* reported upstream.
|
||||
* .
|
||||
* <h2>Kernel Test Suite</h2>
|
||||
* The kernel test suite is divided in modules or test sequences. Each Test
|
||||
* Module performs a series of tests on a specified kernel subsystem or
|
||||
* subsystems and can report a failure/success status and/or a performance
|
||||
* index as the test suite output.<br>
|
||||
* The test suite is usually activated in the demo applications by pressing a
|
||||
* button on the target board, see the readme file into the various demos
|
||||
* directories. The test suite output is usually sent through a serial port
|
||||
* and can be examined by using a terminal emulator program.
|
||||
*
|
||||
* <h2>Kernel Test Modules</h2>
|
||||
*
|
||||
* - @subpage test_threads
|
||||
* - @subpage test_dynamic
|
||||
* - @subpage test_msg
|
||||
* - @subpage test_sem
|
||||
* - @subpage test_mtx
|
||||
* - @subpage test_events
|
||||
* - @subpage test_mbox
|
||||
* - @subpage test_queues
|
||||
* - @subpage test_heap
|
||||
* - @subpage test_pools
|
||||
* - @subpage test_benchmarks
|
||||
* .
|
||||
*/
|
173
Software/portapack-mayhem/firmware/chibios/test/test.h
Normal file
173
Software/portapack-mayhem/firmware/chibios/test/test.h
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test.h
|
||||
* @brief Tests support header.
|
||||
*
|
||||
* @addtogroup test
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _TEST_H_
|
||||
#define _TEST_H_
|
||||
|
||||
/**
|
||||
* @brief Delay inserted between test cases.
|
||||
*/
|
||||
#if !defined(DELAY_BETWEEN_TESTS) || defined(__DOXYGEN__)
|
||||
#define DELAY_BETWEEN_TESTS 200
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If @p TRUE then benchmarks are not included.
|
||||
*/
|
||||
#if !defined(TEST_NO_BENCHMARKS) || defined(__DOXYGEN__)
|
||||
#define TEST_NO_BENCHMARKS FALSE
|
||||
#endif
|
||||
|
||||
#define MAX_THREADS 5
|
||||
#define MAX_TOKENS 16
|
||||
|
||||
#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430)
|
||||
#define THREADS_STACK_SIZE 48
|
||||
#elif defined(CH_ARCHITECTURE_STM8)
|
||||
#define THREADS_STACK_SIZE 64
|
||||
#elif defined(CH_ARCHITECTURE_SIMIA32)
|
||||
#define THREADS_STACK_SIZE 512
|
||||
#else
|
||||
#define THREADS_STACK_SIZE 128
|
||||
#endif
|
||||
#define WA_SIZE THD_WA_SIZE(THREADS_STACK_SIZE)
|
||||
|
||||
/**
|
||||
* @brief Structure representing a test case.
|
||||
*/
|
||||
struct testcase {
|
||||
const char *name; /**< @brief Test case name. */
|
||||
void (*setup)(void); /**< @brief Test case preparation function. */
|
||||
void (*teardown)(void); /**< @brief Test case clean up function. */
|
||||
void (*execute)(void); /**< @brief Test case execution function. */
|
||||
};
|
||||
|
||||
#ifndef __DOXYGEN__
|
||||
union test_buffers {
|
||||
struct {
|
||||
WORKING_AREA(T0, THREADS_STACK_SIZE);
|
||||
WORKING_AREA(T1, THREADS_STACK_SIZE);
|
||||
WORKING_AREA(T2, THREADS_STACK_SIZE);
|
||||
WORKING_AREA(T3, THREADS_STACK_SIZE);
|
||||
WORKING_AREA(T4, THREADS_STACK_SIZE);
|
||||
} wa;
|
||||
uint8_t buffer[WA_SIZE * 5];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
msg_t TestThread(void *p);
|
||||
void test_printn(uint32_t n);
|
||||
void test_print(const char *msgp);
|
||||
void test_println(const char *msgp);
|
||||
void test_emit_token(char token);
|
||||
bool_t _test_fail(unsigned point);
|
||||
bool_t _test_assert(unsigned point, bool_t condition);
|
||||
bool_t _test_assert_sequence(unsigned point, char *expected);
|
||||
bool_t _test_assert_time_window(unsigned point, systime_t start, systime_t end);
|
||||
void test_terminate_threads(void);
|
||||
void test_wait_threads(void);
|
||||
systime_t test_wait_tick(void);
|
||||
void test_start_timer(unsigned ms);
|
||||
#if CH_DBG_THREADS_PROFILING
|
||||
void test_cpu_pulse(unsigned duration);
|
||||
#endif
|
||||
#if defined(WIN32)
|
||||
void ChkIntSources(void);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Test failure enforcement.
|
||||
*/
|
||||
#define test_fail(point) { \
|
||||
_test_fail(point); \
|
||||
return; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test assertion.
|
||||
*
|
||||
* @param[in] point numeric assertion identifier
|
||||
* @param[in] condition a boolean expression that must be verified to be true
|
||||
* @param[in] msg failure message
|
||||
*/
|
||||
#define test_assert(point, condition, msg) { \
|
||||
if (_test_assert(point, condition)) \
|
||||
return; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test assertion with lock.
|
||||
*
|
||||
* @param[in] point numeric assertion identifier
|
||||
* @param[in] condition a boolean expression that must be verified to be true
|
||||
* @param[in] msg failure message
|
||||
*/
|
||||
#define test_assert_lock(point, condition, msg) { \
|
||||
chSysLock(); \
|
||||
if (_test_assert(point, condition)) { \
|
||||
chSysUnlock(); \
|
||||
return; \
|
||||
} \
|
||||
chSysUnlock(); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test sequence assertion.
|
||||
*
|
||||
* @param[in] point numeric assertion identifier
|
||||
* @param[in] expected string to be matched with the tokens buffer
|
||||
*/
|
||||
#define test_assert_sequence(point, expected) { \
|
||||
if (_test_assert_sequence(point, expected)) \
|
||||
return; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test time window assertion.
|
||||
*
|
||||
* @param[in] point numeric assertion identifier
|
||||
* @param[in] start initial time in the window (included)
|
||||
* @param[in] end final time in the window (not included)
|
||||
*/
|
||||
#define test_assert_time_window(point, start, end) { \
|
||||
if (_test_assert_time_window(point, start, end)) \
|
||||
return; \
|
||||
}
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern Thread *threads[MAX_THREADS];
|
||||
extern union test_buffers test;
|
||||
extern void * ROMCONST wa[];
|
||||
extern bool_t test_timer_done;
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_H_ */
|
||||
|
||||
/** @} */
|
16
Software/portapack-mayhem/firmware/chibios/test/test.mk
Normal file
16
Software/portapack-mayhem/firmware/chibios/test/test.mk
Normal file
@ -0,0 +1,16 @@
|
||||
# List of all the ChibiOS/RT test files.
|
||||
TESTSRC = ${CHIBIOS}/test/test.c \
|
||||
${CHIBIOS}/test/testthd.c \
|
||||
${CHIBIOS}/test/testsem.c \
|
||||
${CHIBIOS}/test/testmtx.c \
|
||||
${CHIBIOS}/test/testmsg.c \
|
||||
${CHIBIOS}/test/testmbox.c \
|
||||
${CHIBIOS}/test/testevt.c \
|
||||
${CHIBIOS}/test/testheap.c \
|
||||
${CHIBIOS}/test/testpools.c \
|
||||
${CHIBIOS}/test/testdyn.c \
|
||||
${CHIBIOS}/test/testqueues.c \
|
||||
${CHIBIOS}/test/testbmk.c
|
||||
|
||||
# Required include directories
|
||||
TESTINC = ${CHIBIOS}/test
|
720
Software/portapack-mayhem/firmware/chibios/test/testbmk.c
Normal file
720
Software/portapack-mayhem/firmware/chibios/test/testbmk.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_benchmarks Kernel Benchmarks
|
||||
*
|
||||
* File: @ref testbmk.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements a series of system benchmarks. The benchmarks are
|
||||
* useful as a stress test and as a reference when comparing ChibiOS/RT
|
||||
* with similar systems.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to provide a performance index for the
|
||||
* most critical system subsystems. The performance numbers allow to
|
||||
* discover performance regressions between successive ChibiOS/RT releases.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* None.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_benchmarks_001
|
||||
* - @subpage test_benchmarks_002
|
||||
* - @subpage test_benchmarks_003
|
||||
* - @subpage test_benchmarks_004
|
||||
* - @subpage test_benchmarks_005
|
||||
* - @subpage test_benchmarks_006
|
||||
* - @subpage test_benchmarks_007
|
||||
* - @subpage test_benchmarks_008
|
||||
* - @subpage test_benchmarks_009
|
||||
* - @subpage test_benchmarks_010
|
||||
* - @subpage test_benchmarks_011
|
||||
* - @subpage test_benchmarks_012
|
||||
* - @subpage test_benchmarks_013
|
||||
* .
|
||||
* @file testbmk.c Kernel Benchmarks
|
||||
* @brief Kernel Benchmarks source file
|
||||
* @file testbmk.h
|
||||
* @brief Kernel Benchmarks header file
|
||||
*/
|
||||
|
||||
static Semaphore sem1;
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
static Mutex mtx1;
|
||||
#endif
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
Thread *tp;
|
||||
msg_t msg;
|
||||
|
||||
(void)p;
|
||||
do {
|
||||
tp = chMsgWait();
|
||||
msg = chMsgGet(tp);
|
||||
chMsgRelease(tp, msg);
|
||||
} while (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noinline))
|
||||
#endif
|
||||
static unsigned int msg_loop_test(Thread *tp) {
|
||||
|
||||
uint32_t n = 0;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
(void)chMsgSend(tp, 1);
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
(void)chMsgSend(tp, 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_001 Messages performance #1
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A message server thread is created with a lower priority than the client
|
||||
* thread, the messages throughput per second is measured and the result
|
||||
* printed in the output log.
|
||||
*/
|
||||
|
||||
static void bmk1_execute(void) {
|
||||
uint32_t n;
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread1, NULL);
|
||||
n = msg_loop_test(threads[0]);
|
||||
test_wait_threads();
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_print(" msgs/S, ");
|
||||
test_printn(n << 1);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk1 = {
|
||||
"Benchmark, messages #1",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk1_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_002 Messages performance #2
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A message server thread is created with an higher priority than the client
|
||||
* thread, the messages throughput per second is measured and the result
|
||||
* printed in the output log.
|
||||
*/
|
||||
|
||||
static void bmk2_execute(void) {
|
||||
uint32_t n;
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL);
|
||||
n = msg_loop_test(threads[0]);
|
||||
test_wait_threads();
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_print(" msgs/S, ");
|
||||
test_printn(n << 1);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk2 = {
|
||||
"Benchmark, messages #2",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk2_execute
|
||||
};
|
||||
|
||||
static msg_t thread2(void *p) {
|
||||
|
||||
return (msg_t)p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_003 Messages performance #3
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A message server thread is created with an higher priority than the client
|
||||
* thread, four lower priority threads crowd the ready list, the messages
|
||||
* throughput per second is measured while the ready list and the result
|
||||
* printed in the output log.
|
||||
*/
|
||||
|
||||
static void bmk3_execute(void) {
|
||||
uint32_t n;
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL);
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-2, thread2, NULL);
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread2, NULL);
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-4, thread2, NULL);
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-5, thread2, NULL);
|
||||
n = msg_loop_test(threads[0]);
|
||||
test_wait_threads();
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_print(" msgs/S, ");
|
||||
test_printn(n << 1);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk3 = {
|
||||
"Benchmark, messages #3",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk3_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_004 Context Switch performance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A thread is created that just performs a @p chSchGoSleepS() into a loop,
|
||||
* the thread is awakened as fast is possible by the tester thread.<br>
|
||||
* The Context Switch performance is calculated by measuring the number of
|
||||
* iterations after a second of continuous operations.
|
||||
*/
|
||||
|
||||
msg_t thread4(void *p) {
|
||||
msg_t msg;
|
||||
Thread *self = chThdSelf();
|
||||
|
||||
(void)p;
|
||||
chSysLock();
|
||||
do {
|
||||
chSchGoSleepS(THD_STATE_SUSPENDED);
|
||||
msg = self->p_u.rdymsg;
|
||||
} while (msg == RDY_OK);
|
||||
chSysUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bmk4_execute(void) {
|
||||
Thread *tp;
|
||||
uint32_t n;
|
||||
|
||||
tp = threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread4, NULL);
|
||||
n = 0;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chSysLock();
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSysUnlock();
|
||||
n += 4;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
chSysLock();
|
||||
chSchWakeupS(tp, RDY_TIMEOUT);
|
||||
chSysUnlock();
|
||||
|
||||
test_wait_threads();
|
||||
test_print("--- Score : ");
|
||||
test_printn(n * 2);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk4 = {
|
||||
"Benchmark, context switch",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk4_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_005 Threads performance, full cycle
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Threads are continuously created and terminated into a loop. A full
|
||||
* @p chThdCreateStatic() / @p chThdExit() / @p chThdWait() cycle is performed
|
||||
* in each iteration.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void bmk5_execute(void) {
|
||||
|
||||
uint32_t n = 0;
|
||||
void *wap = wa[0];
|
||||
tprio_t prio = chThdGetPriority() - 1;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chThdWait(chThdCreateStatic(wap, WA_SIZE, prio, thread2, NULL));
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_println(" threads/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk5 = {
|
||||
"Benchmark, threads, full cycle",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk5_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_006 Threads performance, create/exit only
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Threads are continuously created and terminated into a loop. A partial
|
||||
* @p chThdCreateStatic() / @p chThdExit() cycle is performed in each
|
||||
* iteration, the @p chThdWait() is not necessary because the thread is
|
||||
* created at an higher priority so there is no need to wait for it to
|
||||
* terminate.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void bmk6_execute(void) {
|
||||
|
||||
uint32_t n = 0;
|
||||
void *wap = wa[0];
|
||||
tprio_t prio = chThdGetPriority() + 1;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chThdCreateStatic(wap, WA_SIZE, prio, thread2, NULL);
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_println(" threads/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk6 = {
|
||||
"Benchmark, threads, create only",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk6_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_007 Mass reschedule performance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads are created and atomically rescheduled by resetting the
|
||||
* semaphore where they are waiting on. The operation is performed into a
|
||||
* continuous loop.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static msg_t thread3(void *p) {
|
||||
|
||||
(void)p;
|
||||
while (!chThdShouldTerminate())
|
||||
chSemWait(&sem1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bmk7_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void bmk7_execute(void) {
|
||||
uint32_t n;
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread3, NULL);
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()+4, thread3, NULL);
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()+3, thread3, NULL);
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()+2, thread3, NULL);
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()+1, thread3, NULL);
|
||||
|
||||
n = 0;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chSemReset(&sem1, 0);
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_terminate_threads();
|
||||
chSemReset(&sem1, 0);
|
||||
test_wait_threads();
|
||||
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_print(" reschedules/S, ");
|
||||
test_printn(n * 6);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk7 = {
|
||||
"Benchmark, mass reschedule, 5 threads",
|
||||
bmk7_setup,
|
||||
NULL,
|
||||
bmk7_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_008 I/O Round-Robin voluntary reschedule.
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads are created at equal priority, each thread just increases a
|
||||
* variable and yields.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static msg_t thread8(void *p) {
|
||||
|
||||
do {
|
||||
chThdYield();
|
||||
chThdYield();
|
||||
chThdYield();
|
||||
chThdYield();
|
||||
(*(uint32_t *)p) += 4;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while(!chThdShouldTerminate());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bmk8_execute(void) {
|
||||
uint32_t n;
|
||||
|
||||
n = 0;
|
||||
test_wait_tick();
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
|
||||
|
||||
chThdSleepSeconds(1);
|
||||
test_terminate_threads();
|
||||
test_wait_threads();
|
||||
|
||||
test_print("--- Score : ");
|
||||
test_printn(n);
|
||||
test_println(" ctxswc/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk8 = {
|
||||
"Benchmark, round robin context switching",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk8_execute
|
||||
};
|
||||
|
||||
#if CH_USE_QUEUES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_benchmarks_009 I/O Queues throughput
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Four bytes are written and then read from an @p InputQueue into a continuous
|
||||
* loop.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void bmk9_execute(void) {
|
||||
uint32_t n;
|
||||
static uint8_t ib[16];
|
||||
static InputQueue iq;
|
||||
|
||||
chIQInit(&iq, ib, sizeof(ib), NULL, NULL);
|
||||
n = 0;
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chSysLock();
|
||||
chIQPutI(&iq, 0);
|
||||
chIQPutI(&iq, 1);
|
||||
chIQPutI(&iq, 2);
|
||||
chIQPutI(&iq, 3);
|
||||
chSysUnlock();
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n * 4);
|
||||
test_println(" bytes/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk9 = {
|
||||
"Benchmark, I/O Queues throughput",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk9_execute
|
||||
};
|
||||
#endif /* CH_USE_QUEUES */
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_010 Virtual Timers set/reset performance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A virtual timer is set and immediately reset into a continuous loop.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void tmo(void *param) {(void)param;}
|
||||
|
||||
static void bmk10_execute(void) {
|
||||
static VirtualTimer vt1, vt2;
|
||||
uint32_t n = 0;
|
||||
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chSysLock();
|
||||
chVTSetI(&vt1, 1, tmo, NULL);
|
||||
chVTSetI(&vt2, 10000, tmo, NULL);
|
||||
chVTResetI(&vt1);
|
||||
chVTResetI(&vt2);
|
||||
chSysUnlock();
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n * 2);
|
||||
test_println(" timers/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk10 = {
|
||||
"Benchmark, virtual timers set/reset",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk10_execute
|
||||
};
|
||||
|
||||
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_benchmarks_011 Semaphores wait/signal performance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A counting semaphore is taken/released into a continuous loop, no Context
|
||||
* Switch happens because the counter is always non negative.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void bmk11_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 1);
|
||||
}
|
||||
|
||||
static void bmk11_execute(void) {
|
||||
uint32_t n = 0;
|
||||
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n * 4);
|
||||
test_println(" wait+signal/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk11 = {
|
||||
"Benchmark, semaphores wait/signal",
|
||||
bmk11_setup,
|
||||
NULL,
|
||||
bmk11_execute
|
||||
};
|
||||
#endif /* CH_USE_SEMAPHORES */
|
||||
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_benchmarks_012 Mutexes lock/unlock performance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A mutex is locked/unlocked into a continuous loop, no Context Switch happens
|
||||
* because there are no other threads asking for the mutex.<br>
|
||||
* The performance is calculated by measuring the number of iterations after
|
||||
* a second of continuous operations.
|
||||
*/
|
||||
|
||||
static void bmk12_setup(void) {
|
||||
|
||||
chMtxInit(&mtx1);
|
||||
}
|
||||
|
||||
static void bmk12_execute(void) {
|
||||
uint32_t n = 0;
|
||||
|
||||
test_wait_tick();
|
||||
test_start_timer(1000);
|
||||
do {
|
||||
chMtxLock(&mtx1);
|
||||
chMtxUnlock();
|
||||
chMtxLock(&mtx1);
|
||||
chMtxUnlock();
|
||||
chMtxLock(&mtx1);
|
||||
chMtxUnlock();
|
||||
chMtxLock(&mtx1);
|
||||
chMtxUnlock();
|
||||
n++;
|
||||
#if defined(SIMULATOR)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
} while (!test_timer_done);
|
||||
test_print("--- Score : ");
|
||||
test_printn(n * 4);
|
||||
test_println(" lock+unlock/S");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk12 = {
|
||||
"Benchmark, mutexes lock/unlock",
|
||||
bmk12_setup,
|
||||
NULL,
|
||||
bmk12_execute
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page test_benchmarks_013 RAM Footprint
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The memory size of the various kernel objects is printed.
|
||||
*/
|
||||
|
||||
static void bmk13_execute(void) {
|
||||
|
||||
test_print("--- System: ");
|
||||
test_printn(sizeof(ReadyList) + sizeof(VTList) +
|
||||
PORT_IDLE_THREAD_STACK_SIZE +
|
||||
(sizeof(Thread) + sizeof(struct intctx) +
|
||||
sizeof(struct extctx) +
|
||||
PORT_INT_REQUIRED_STACK) * 2);
|
||||
test_println(" bytes");
|
||||
test_print("--- Thread: ");
|
||||
test_printn(sizeof(Thread));
|
||||
test_println(" bytes");
|
||||
test_print("--- Timer : ");
|
||||
test_printn(sizeof(VirtualTimer));
|
||||
test_println(" bytes");
|
||||
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
|
||||
test_print("--- Semaph: ");
|
||||
test_printn(sizeof(Semaphore));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
#if CH_USE_EVENTS || defined(__DOXYGEN__)
|
||||
test_print("--- EventS: ");
|
||||
test_printn(sizeof(EventSource));
|
||||
test_println(" bytes");
|
||||
test_print("--- EventL: ");
|
||||
test_printn(sizeof(EventListener));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
test_print("--- Mutex : ");
|
||||
test_printn(sizeof(Mutex));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
#if CH_USE_CONDVARS || defined(__DOXYGEN__)
|
||||
test_print("--- CondV.: ");
|
||||
test_printn(sizeof(CondVar));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
#if CH_USE_QUEUES || defined(__DOXYGEN__)
|
||||
test_print("--- Queue : ");
|
||||
test_printn(sizeof(GenericQueue));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
#if CH_USE_MAILBOXES || defined(__DOXYGEN__)
|
||||
test_print("--- MailB.: ");
|
||||
test_printn(sizeof(Mailbox));
|
||||
test_println(" bytes");
|
||||
#endif
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testbmk13 = {
|
||||
"Benchmark, RAM footprint",
|
||||
NULL,
|
||||
NULL,
|
||||
bmk13_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Test sequence for benchmarks.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternbmk[] = {
|
||||
#if !TEST_NO_BENCHMARKS
|
||||
&testbmk1,
|
||||
&testbmk2,
|
||||
&testbmk3,
|
||||
&testbmk4,
|
||||
&testbmk5,
|
||||
&testbmk6,
|
||||
&testbmk7,
|
||||
&testbmk8,
|
||||
#if CH_USE_QUEUES || defined(__DOXYGEN__)
|
||||
&testbmk9,
|
||||
#endif
|
||||
&testbmk10,
|
||||
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
|
||||
&testbmk11,
|
||||
#endif
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
&testbmk12,
|
||||
#endif
|
||||
&testbmk13,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testbmk.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testbmk.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTBMK_H_
|
||||
#define _TESTBMK_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternbmk[];
|
||||
|
||||
#endif /* _TESTBMK_H_ */
|
264
Software/portapack-mayhem/firmware/chibios/test/testdyn.c
Normal file
264
Software/portapack-mayhem/firmware/chibios/test/testdyn.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_dynamic Dynamic APIs test
|
||||
*
|
||||
* File: @ref testdyn.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the dynamic thread creation
|
||||
* APIs.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the dynamic APIs code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_DYNAMIC
|
||||
* - @p CH_USE_HEAP
|
||||
* - @p CH_USE_MEMPOOLS
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_dynamic_001
|
||||
* - @subpage test_dynamic_002
|
||||
* - @subpage test_dynamic_003
|
||||
* .
|
||||
* @file testdyn.c
|
||||
* @brief Dynamic thread APIs test source file
|
||||
* @file testdyn.h
|
||||
* @brief Dynamic thread APIs test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_DYNAMIC || defined(__DOXYGEN__)
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
static MemoryHeap heap1;
|
||||
#endif
|
||||
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
|
||||
static MemoryPool mp1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page test_dynamic_001 Threads creation from Memory Heap
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Two threads are started by allocating the memory from the Memory Heap then
|
||||
* the remaining heap space is arbitrarily allocated and a third tread startup
|
||||
* is attempted.<br>
|
||||
* The test expects the first two threads to successfully start and the last
|
||||
* one to fail.
|
||||
*/
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
static void dyn1_setup(void) {
|
||||
|
||||
chHeapInit(&heap1, test.buffer, sizeof(union test_buffers));
|
||||
}
|
||||
|
||||
static void dyn1_execute(void) {
|
||||
size_t n, sz;
|
||||
void *p1;
|
||||
tprio_t prio = chThdGetPriority();
|
||||
|
||||
(void)chHeapStatus(&heap1, &sz);
|
||||
/* Starting threads from the heap. */
|
||||
threads[0] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
|
||||
prio-1, thread, "A");
|
||||
threads[1] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
|
||||
prio-2, thread, "B");
|
||||
/* Allocating the whole heap in order to make the thread creation fail.*/
|
||||
(void)chHeapStatus(&heap1, &n);
|
||||
p1 = chHeapAlloc(&heap1, n);
|
||||
threads[2] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
|
||||
prio-3, thread, "C");
|
||||
chHeapFree(p1);
|
||||
|
||||
test_assert(1, (threads[0] != NULL) &&
|
||||
(threads[1] != NULL) &&
|
||||
(threads[2] == NULL) &&
|
||||
(threads[3] == NULL) &&
|
||||
(threads[4] == NULL),
|
||||
"thread creation failed");
|
||||
|
||||
/* Claiming the memory from terminated threads. */
|
||||
test_wait_threads();
|
||||
test_assert_sequence(2, "AB");
|
||||
|
||||
/* Heap status checked again.*/
|
||||
test_assert(3, chHeapStatus(&heap1, &n) == 1, "heap fragmented");
|
||||
test_assert(4, n == sz, "heap size changed");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testdyn1 = {
|
||||
"Dynamic APIs, threads creation from heap",
|
||||
dyn1_setup,
|
||||
NULL,
|
||||
dyn1_execute
|
||||
};
|
||||
#endif /* (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) */
|
||||
|
||||
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_dynamic_002 Threads creation from Memory Pool
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five thread creation are attempted from a pool containing only four
|
||||
* elements.<br>
|
||||
* The test expects the first four threads to successfully start and the last
|
||||
* one to fail.
|
||||
*/
|
||||
|
||||
static void dyn2_setup(void) {
|
||||
|
||||
chPoolInit(&mp1, THD_WA_SIZE(THREADS_STACK_SIZE), NULL);
|
||||
}
|
||||
|
||||
static void dyn2_execute(void) {
|
||||
int i;
|
||||
tprio_t prio = chThdGetPriority();
|
||||
|
||||
/* Adding the WAs to the pool. */
|
||||
for (i = 0; i < 4; i++)
|
||||
chPoolFree(&mp1, wa[i]);
|
||||
|
||||
/* Starting threads from the memory pool. */
|
||||
threads[0] = chThdCreateFromMemoryPool(&mp1, prio-1, thread, "A");
|
||||
threads[1] = chThdCreateFromMemoryPool(&mp1, prio-2, thread, "B");
|
||||
threads[2] = chThdCreateFromMemoryPool(&mp1, prio-3, thread, "C");
|
||||
threads[3] = chThdCreateFromMemoryPool(&mp1, prio-4, thread, "D");
|
||||
threads[4] = chThdCreateFromMemoryPool(&mp1, prio-5, thread, "E");
|
||||
|
||||
test_assert(1, (threads[0] != NULL) &&
|
||||
(threads[1] != NULL) &&
|
||||
(threads[2] != NULL) &&
|
||||
(threads[3] != NULL) &&
|
||||
(threads[4] == NULL),
|
||||
"thread creation failed");
|
||||
|
||||
/* Claiming the memory from terminated threads. */
|
||||
test_wait_threads();
|
||||
test_assert_sequence(2, "ABCD");
|
||||
|
||||
/* Now the pool must be full again. */
|
||||
for (i = 0; i < 4; i++)
|
||||
test_assert(3, chPoolAlloc(&mp1) != NULL, "pool list empty");
|
||||
test_assert(4, chPoolAlloc(&mp1) == NULL, "pool list not empty");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testdyn2 = {
|
||||
"Dynamic APIs, threads creation from memory pool",
|
||||
dyn2_setup,
|
||||
NULL,
|
||||
dyn2_execute
|
||||
};
|
||||
#endif /* CH_USE_MEMPOOLS */
|
||||
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP && CH_USE_REGISTRY) || \
|
||||
defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_dynamic_003 Registry and References test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Registry and Thread References APIs are tested for functionality and
|
||||
* coverage.
|
||||
*/
|
||||
|
||||
static bool_t regfind(Thread *tp) {
|
||||
Thread *ftp;
|
||||
bool_t found = FALSE;
|
||||
|
||||
ftp = chRegFirstThread();
|
||||
do {
|
||||
found |= ftp == tp;
|
||||
ftp = chRegNextThread(ftp);
|
||||
} while (ftp != NULL);
|
||||
return found;
|
||||
}
|
||||
|
||||
static void dyn3_setup(void) {
|
||||
|
||||
chHeapInit(&heap1, test.buffer, sizeof(union test_buffers));
|
||||
}
|
||||
|
||||
static void dyn3_execute(void) {
|
||||
Thread *tp;
|
||||
tprio_t prio = chThdGetPriority();
|
||||
|
||||
/* Testing references increase/decrease and final detach.*/
|
||||
tp = chThdCreateFromHeap(&heap1, WA_SIZE, prio-1, thread, "A");
|
||||
test_assert(1, tp->p_refs == 1, "wrong initial reference counter");
|
||||
chThdAddRef(tp);
|
||||
test_assert(2, tp->p_refs == 2, "references increase failure");
|
||||
chThdRelease(tp);
|
||||
test_assert(3, tp->p_refs == 1, "references decrease failure");
|
||||
|
||||
/* Verify the new threads count.*/
|
||||
test_assert(4, regfind(tp), "thread missing from registry");
|
||||
test_assert(5, regfind(tp), "thread disappeared");
|
||||
|
||||
/* Detach and let the thread execute and terminate.*/
|
||||
chThdRelease(tp);
|
||||
test_assert(6, tp->p_refs == 0, "detach failure");
|
||||
test_assert(7, tp->p_state == THD_STATE_READY, "invalid state");
|
||||
test_assert(8, regfind(tp), "thread disappeared");
|
||||
test_assert(9, regfind(tp), "thread disappeared");
|
||||
chThdSleepMilliseconds(50); /* The thread just terminates. */
|
||||
test_assert(10, tp->p_state == THD_STATE_FINAL, "invalid state");
|
||||
|
||||
/* Clearing the zombie by scanning the registry.*/
|
||||
test_assert(11, regfind(tp), "thread disappeared");
|
||||
test_assert(12, !regfind(tp), "thread still in registry");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testdyn3 = {
|
||||
"Dynamic APIs, registry and references",
|
||||
dyn3_setup,
|
||||
NULL,
|
||||
dyn3_execute
|
||||
};
|
||||
#endif /* CH_USE_HEAP && CH_USE_REGISTRY */
|
||||
#endif /* CH_USE_DYNAMIC */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for dynamic APIs.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patterndyn[] = {
|
||||
#if CH_USE_DYNAMIC || defined(__DOXYGEN__)
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
&testdyn1,
|
||||
#endif
|
||||
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
|
||||
&testdyn2,
|
||||
#endif
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP && CH_USE_REGISTRY) || \
|
||||
defined(__DOXYGEN__)
|
||||
&testdyn3,
|
||||
#endif
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testdyn.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testdyn.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTDYN_H_
|
||||
#define _TESTDYN_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patterndyn[];
|
||||
|
||||
#endif /* _TESTDYN_H_ */
|
296
Software/portapack-mayhem/firmware/chibios/test/testevt.c
Normal file
296
Software/portapack-mayhem/firmware/chibios/test/testevt.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_events Events test
|
||||
*
|
||||
* File: @ref testevt.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref events subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref events subsystem.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_EVENTS
|
||||
* - @p CH_USE_EVENTS_TIMEOUT
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_events_001
|
||||
* - @subpage test_events_002
|
||||
* - @subpage test_events_003
|
||||
* .
|
||||
* @file testevt.c
|
||||
* @brief Events test source file
|
||||
* @file testevt.h
|
||||
* @brief Events test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_EVENTS || defined(__DOXYGEN__)
|
||||
|
||||
#define ALLOWED_DELAY MS2ST(5)
|
||||
|
||||
/*
|
||||
* Note, the static initializers are not really required because the
|
||||
* variables are explicitly initialized in each test case. It is done in order
|
||||
* to test the macros.
|
||||
*/
|
||||
static EVENTSOURCE_DECL(es1);
|
||||
static EVENTSOURCE_DECL(es2);
|
||||
|
||||
/**
|
||||
* @page test_events_001 Events registration and dispatch
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Two event listeners are registered on an event source and then unregistered
|
||||
* in the same order.<br>
|
||||
* The test expects that the even source has listeners after the registrations
|
||||
* and after the first unregistration, then, after the second unegistration,
|
||||
* the test expects no more listeners.<br>
|
||||
* In the second part the test dispatches three event flags and verifies that
|
||||
* the associated event handlers are invoked in LSb-first order.
|
||||
*/
|
||||
|
||||
static void evt1_setup(void) {
|
||||
|
||||
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
}
|
||||
|
||||
static void h1(eventid_t id) {(void)id;test_emit_token('A');}
|
||||
static void h2(eventid_t id) {(void)id;test_emit_token('B');}
|
||||
static void h3(eventid_t id) {(void)id;test_emit_token('C');}
|
||||
static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
|
||||
|
||||
static void evt1_execute(void) {
|
||||
EventListener el1, el2;
|
||||
|
||||
/*
|
||||
* Testing chEvtRegisterMask() and chEvtUnregister().
|
||||
*/
|
||||
chEvtInit(&es1);
|
||||
chEvtRegisterMask(&es1, &el1, 1);
|
||||
chEvtRegisterMask(&es1, &el2, 2);
|
||||
test_assert(1, chEvtIsListeningI(&es1), "no listener");
|
||||
chEvtUnregister(&es1, &el1);
|
||||
test_assert(2, chEvtIsListeningI(&es1), "no listener");
|
||||
chEvtUnregister(&es1, &el2);
|
||||
test_assert(3, !chEvtIsListeningI(&es1), "stuck listener");
|
||||
|
||||
/*
|
||||
* Testing chEvtDispatch().
|
||||
*/
|
||||
chEvtDispatch(evhndl, 7);
|
||||
test_assert_sequence(4, "ABC");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testevt1 = {
|
||||
"Events, registration and dispatch",
|
||||
evt1_setup,
|
||||
NULL,
|
||||
evt1_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_events_002 Events wait and broadcast
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* In this test the following APIs are indipently tested by starting threads
|
||||
* that signal/broadcast events after fixed delays:
|
||||
* - @p chEvtWaitOne()
|
||||
* - @p chEvtWaitAny()
|
||||
* - @p chEvtWaitAll()
|
||||
* .
|
||||
* After each test phase the test verifies that the events have been served at
|
||||
* the expected time and that there are no stuck event flags.
|
||||
*/
|
||||
|
||||
static void evt2_setup(void) {
|
||||
|
||||
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
}
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
|
||||
chThdSleepMilliseconds(50);
|
||||
chEvtSignal((Thread *)p, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread2(void *p) {
|
||||
|
||||
(void)p;
|
||||
chEvtBroadcast(&es1);
|
||||
chThdSleepMilliseconds(50);
|
||||
chEvtBroadcast(&es2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void evt2_execute(void) {
|
||||
eventmask_t m;
|
||||
EventListener el1, el2;
|
||||
systime_t target_time;
|
||||
|
||||
/*
|
||||
* Test on chEvtWaitOne() without wait.
|
||||
*/
|
||||
chEvtAddEvents(7);
|
||||
m = chEvtWaitOne(ALL_EVENTS);
|
||||
test_assert(1, m == 1, "single event error");
|
||||
m = chEvtWaitOne(ALL_EVENTS);
|
||||
test_assert(2, m == 2, "single event error");
|
||||
m = chEvtWaitOne(ALL_EVENTS);
|
||||
test_assert(3, m == 4, "single event error");
|
||||
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
test_assert(4, m == 0, "stuck event");
|
||||
|
||||
/*
|
||||
* Test on chEvtWaitOne() with wait.
|
||||
*/
|
||||
test_wait_tick();
|
||||
target_time = chTimeNow() + MS2ST(50);
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
|
||||
thread1, chThdSelf());
|
||||
m = chEvtWaitOne(ALL_EVENTS);
|
||||
test_assert_time_window(5, target_time, target_time + ALLOWED_DELAY);
|
||||
test_assert(6, m == 1, "single event error");
|
||||
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
test_assert(7, m == 0, "stuck event");
|
||||
test_wait_threads();
|
||||
|
||||
/*
|
||||
* Test on chEvtWaitAny() without wait.
|
||||
*/
|
||||
chEvtAddEvents(5);
|
||||
m = chEvtWaitAny(ALL_EVENTS);
|
||||
test_assert(8, m == 5, "unexpected pending bit");
|
||||
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
test_assert(9, m == 0, "stuck event");
|
||||
|
||||
/*
|
||||
* Test on chEvtWaitAny() with wait.
|
||||
*/
|
||||
test_wait_tick();
|
||||
target_time = chTimeNow() + MS2ST(50);
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
|
||||
thread1, chThdSelf());
|
||||
m = chEvtWaitAny(ALL_EVENTS);
|
||||
test_assert_time_window(10, target_time, target_time + ALLOWED_DELAY);
|
||||
test_assert(11, m == 1, "single event error");
|
||||
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
test_assert(12, m == 0, "stuck event");
|
||||
test_wait_threads();
|
||||
|
||||
/*
|
||||
* Test on chEvtWaitAll().
|
||||
*/
|
||||
chEvtInit(&es1);
|
||||
chEvtInit(&es2);
|
||||
chEvtRegisterMask(&es1, &el1, 1);
|
||||
chEvtRegisterMask(&es2, &el2, 4);
|
||||
test_wait_tick();
|
||||
target_time = chTimeNow() + MS2ST(50);
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
|
||||
thread2, "A");
|
||||
m = chEvtWaitAll(5);
|
||||
test_assert_time_window(13, target_time, target_time + ALLOWED_DELAY);
|
||||
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
test_assert(14, m == 0, "stuck event");
|
||||
test_wait_threads();
|
||||
chEvtUnregister(&es1, &el1);
|
||||
chEvtUnregister(&es2, &el2);
|
||||
test_assert(15, !chEvtIsListeningI(&es1), "stuck listener");
|
||||
test_assert(16, !chEvtIsListeningI(&es2), "stuck listener");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testevt2 = {
|
||||
"Events, wait and broadcast",
|
||||
evt2_setup,
|
||||
NULL,
|
||||
evt2_execute
|
||||
};
|
||||
|
||||
#if CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_events_003 Events timeout
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* In this test the following APIs are let to timeout twice: immediatly and
|
||||
* after 10ms:
|
||||
* In this test the following APIs are indipently tested by starting threads
|
||||
* that broadcast events after fixed delays:
|
||||
* - @p chEvtWaitOneTimeout()
|
||||
* - @p chEvtWaitAnyTimeout()
|
||||
* - @p chEvtWaitAllTimeout()
|
||||
* .
|
||||
* After each test phase the test verifies that there are no stuck event flags.
|
||||
*/
|
||||
|
||||
static void evt3_setup(void) {
|
||||
|
||||
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||
}
|
||||
|
||||
static void evt3_execute(void) {
|
||||
eventmask_t m;
|
||||
|
||||
/*
|
||||
* Tests various timeout situations.
|
||||
*/
|
||||
m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
||||
test_assert(1, m == 0, "spurious event");
|
||||
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
||||
test_assert(2, m == 0, "spurious event");
|
||||
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
||||
test_assert(3, m == 0, "spurious event");
|
||||
m = chEvtWaitOneTimeout(ALL_EVENTS, 10);
|
||||
test_assert(4, m == 0, "spurious event");
|
||||
m = chEvtWaitAnyTimeout(ALL_EVENTS, 10);
|
||||
test_assert(5, m == 0, "spurious event");
|
||||
m = chEvtWaitAllTimeout(ALL_EVENTS, 10);
|
||||
test_assert(6, m == 0, "spurious event");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testevt3 = {
|
||||
"Events, timeouts",
|
||||
evt3_setup,
|
||||
NULL,
|
||||
evt3_execute
|
||||
};
|
||||
#endif /* CH_USE_EVENTS_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for events.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternevt[] = {
|
||||
#if CH_USE_EVENTS || defined(__DOXYGEN__)
|
||||
&testevt1,
|
||||
&testevt2,
|
||||
#if CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
|
||||
&testevt3,
|
||||
#endif
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_USE_EVENTS */
|
22
Software/portapack-mayhem/firmware/chibios/test/testevt.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testevt.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTEVT_H_
|
||||
#define _TESTEVT_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternevt[];
|
||||
|
||||
#endif /* _TESTEVT_H_ */
|
159
Software/portapack-mayhem/firmware/chibios/test/testheap.c
Normal file
159
Software/portapack-mayhem/firmware/chibios/test/testheap.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_heap Memory Heap test
|
||||
*
|
||||
* File: @ref testheap.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref heaps subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref heaps subsystem.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_HEAP
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_heap_001
|
||||
* .
|
||||
* @file testheap.c
|
||||
* @brief Heap test source file
|
||||
* @file testheap.h
|
||||
* @brief Heap header file
|
||||
*/
|
||||
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
|
||||
#define SIZE 16
|
||||
|
||||
static MemoryHeap test_heap;
|
||||
|
||||
/**
|
||||
* @page test_heap_001 Allocation and fragmentation test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Series of allocations/deallocations are performed in carefully designed
|
||||
* sequences in order to stimulate all the possible code paths inside the
|
||||
* allocator.<br>
|
||||
* The test expects to find the heap back to the initial status after each
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
static void heap1_setup(void) {
|
||||
|
||||
chHeapInit(&test_heap, test.buffer, sizeof(union test_buffers));
|
||||
}
|
||||
|
||||
static void heap1_execute(void) {
|
||||
void *p1, *p2, *p3;
|
||||
size_t n, sz;
|
||||
|
||||
/* Unrelated, for coverage only.*/
|
||||
(void)chCoreStatus();
|
||||
|
||||
/*
|
||||
* Test on the default heap in order to cover the core allocator at
|
||||
* least one time.
|
||||
*/
|
||||
(void)chHeapStatus(NULL, &sz);
|
||||
p1 = chHeapAlloc(NULL, SIZE);
|
||||
test_assert(1, p1 != NULL, "allocation failed");
|
||||
chHeapFree(p1);
|
||||
p1 = chHeapAlloc(NULL, (size_t)-256);
|
||||
test_assert(2, p1 == NULL, "allocation not failed");
|
||||
|
||||
/* Initial local heap state.*/
|
||||
(void)chHeapStatus(&test_heap, &sz);
|
||||
|
||||
/* Same order.*/
|
||||
p1 = chHeapAlloc(&test_heap, SIZE);
|
||||
p2 = chHeapAlloc(&test_heap, SIZE);
|
||||
p3 = chHeapAlloc(&test_heap, SIZE);
|
||||
chHeapFree(p1); /* Does not merge.*/
|
||||
chHeapFree(p2); /* Merges backward.*/
|
||||
chHeapFree(p3); /* Merges both sides.*/
|
||||
test_assert(3, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
|
||||
|
||||
/* Reverse order.*/
|
||||
p1 = chHeapAlloc(&test_heap, SIZE);
|
||||
p2 = chHeapAlloc(&test_heap, SIZE);
|
||||
p3 = chHeapAlloc(&test_heap, SIZE);
|
||||
chHeapFree(p3); /* Merges forward.*/
|
||||
chHeapFree(p2); /* Merges forward.*/
|
||||
chHeapFree(p1); /* Merges forward.*/
|
||||
test_assert(4, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
|
||||
|
||||
/* Small fragments handling.*/
|
||||
p1 = chHeapAlloc(&test_heap, SIZE + 1);
|
||||
p2 = chHeapAlloc(&test_heap, SIZE);
|
||||
chHeapFree(p1);
|
||||
test_assert(5, chHeapStatus(&test_heap, &n) == 2, "invalid state");
|
||||
p1 = chHeapAlloc(&test_heap, SIZE);
|
||||
/* Note, the first situation happens when the alignment size is smaller
|
||||
than the header size, the second in the other cases.*/
|
||||
test_assert(6, (chHeapStatus(&test_heap, &n) == 1) ||
|
||||
(chHeapStatus(&test_heap, &n) == 2), "heap fragmented");
|
||||
chHeapFree(p2);
|
||||
chHeapFree(p1);
|
||||
test_assert(7, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
|
||||
|
||||
/* Skip fragment handling.*/
|
||||
p1 = chHeapAlloc(&test_heap, SIZE);
|
||||
p2 = chHeapAlloc(&test_heap, SIZE);
|
||||
chHeapFree(p1);
|
||||
test_assert(8, chHeapStatus(&test_heap, &n) == 2, "invalid state");
|
||||
p1 = chHeapAlloc(&test_heap, SIZE * 2); /* Skips first fragment.*/
|
||||
chHeapFree(p1);
|
||||
chHeapFree(p2);
|
||||
test_assert(9, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
|
||||
|
||||
/* Allocate all handling.*/
|
||||
(void)chHeapStatus(&test_heap, &n);
|
||||
p1 = chHeapAlloc(&test_heap, n);
|
||||
test_assert(10, chHeapStatus(&test_heap, &n) == 0, "not empty");
|
||||
chHeapFree(p1);
|
||||
|
||||
test_assert(11, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
|
||||
test_assert(12, n == sz, "size changed");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testheap1 = {
|
||||
"Heap, allocation and fragmentation test",
|
||||
heap1_setup,
|
||||
NULL,
|
||||
heap1_execute
|
||||
};
|
||||
|
||||
#endif /* CH_USE_HEAP.*/
|
||||
|
||||
/**
|
||||
* @brief Test sequence for heap.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternheap[] = {
|
||||
#if (CH_USE_HEAP && !CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
|
||||
&testheap1,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testheap.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testheap.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTHEAP_H_
|
||||
#define _TESTHEAP_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternheap[];
|
||||
|
||||
#endif /* _TESTHEAP_H_ */
|
239
Software/portapack-mayhem/firmware/chibios/test/testmbox.c
Normal file
239
Software/portapack-mayhem/firmware/chibios/test/testmbox.c
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_mbox Mailboxes test
|
||||
*
|
||||
* File: @ref testmbox.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref mailboxes subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref mailboxes
|
||||
* subsystem code.<br>
|
||||
* Note that the @ref mailboxes subsystem depends on the @ref semaphores
|
||||
* subsystem that has to met its testing objectives as well.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_MAILBOXES
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_mbox_001
|
||||
* .
|
||||
* @file testmbox.c
|
||||
* @brief Mailboxes test source file
|
||||
* @file testmbox.h
|
||||
* @brief Mailboxes header file
|
||||
*/
|
||||
|
||||
#if CH_USE_MAILBOXES || defined(__DOXYGEN__)
|
||||
|
||||
#define ALLOWED_DELAY MS2ST(5)
|
||||
#define MB_SIZE 5
|
||||
|
||||
/*
|
||||
* Note, the static initializers are not really required because the
|
||||
* variables are explicitly initialized in each test case. It is done in order
|
||||
* to test the macros.
|
||||
*/
|
||||
static MAILBOX_DECL(mb1, test.wa.T0, MB_SIZE);
|
||||
|
||||
/**
|
||||
* @page test_mbox_001 Queuing and timeouts
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Messages are posted/fetched from a mailbox in carefully designed sequences
|
||||
* in order to stimulate all the possible code paths inside the mailbox.<br>
|
||||
* The test expects to find a consistent mailbox status after each operation.
|
||||
*/
|
||||
|
||||
static void mbox1_setup(void) {
|
||||
|
||||
chMBInit(&mb1, (msg_t *)test.wa.T0, MB_SIZE);
|
||||
}
|
||||
|
||||
static void mbox1_execute(void) {
|
||||
msg_t msg1, msg2;
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
* Testing initial space.
|
||||
*/
|
||||
test_assert(1, chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
||||
|
||||
/*
|
||||
* Testing enqueuing and backward circularity.
|
||||
*/
|
||||
for (i = 0; i < MB_SIZE - 1; i++) {
|
||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||
test_assert(2, msg1 == RDY_OK, "wrong wake-up message");
|
||||
}
|
||||
msg1 = chMBPostAhead(&mb1, 'A', TIME_INFINITE);
|
||||
test_assert(3, msg1 == RDY_OK, "wrong wake-up message");
|
||||
|
||||
/*
|
||||
* Testing post timeout.
|
||||
*/
|
||||
msg1 = chMBPost(&mb1, 'X', 1);
|
||||
test_assert(4, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
chSysLock();
|
||||
msg1 = chMBPostI(&mb1, 'X');
|
||||
chSysUnlock();
|
||||
test_assert(5, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
msg1 = chMBPostAhead(&mb1, 'X', 1);
|
||||
test_assert(6, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
chSysLock();
|
||||
msg1 = chMBPostAheadI(&mb1, 'X');
|
||||
chSysUnlock();
|
||||
test_assert(7, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
|
||||
/*
|
||||
* Testing final conditions.
|
||||
*/
|
||||
test_assert_lock(8, chMBGetFreeCountI(&mb1) == 0, "still empty");
|
||||
test_assert_lock(9, chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
|
||||
test_assert_lock(10, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
|
||||
/*
|
||||
* Testing dequeuing.
|
||||
*/
|
||||
for (i = 0; i < MB_SIZE; i++) {
|
||||
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
||||
test_assert(11, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_emit_token(msg2);
|
||||
}
|
||||
test_assert_sequence(12, "ABCDE");
|
||||
|
||||
/*
|
||||
* Testing buffer circularity.
|
||||
*/
|
||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||
test_assert(13, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
||||
test_assert(14, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_assert(15, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base");
|
||||
test_assert(16, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base");
|
||||
|
||||
/*
|
||||
* Testing fetch timeout.
|
||||
*/
|
||||
msg1 = chMBFetch(&mb1, &msg2, 1);
|
||||
test_assert(17, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
chSysLock();
|
||||
msg1 = chMBFetchI(&mb1, &msg2);
|
||||
chSysUnlock();
|
||||
test_assert(18, msg1 == RDY_TIMEOUT, "wrong wake-up message");
|
||||
|
||||
/*
|
||||
* Testing final conditions.
|
||||
*/
|
||||
test_assert_lock(19, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||
test_assert_lock(20, chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||
test_assert_lock(21, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
|
||||
/*
|
||||
* Testing I-Class.
|
||||
*/
|
||||
chSysLock();
|
||||
msg1 = chMBPostI(&mb1, 'A');
|
||||
test_assert(22, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostI(&mb1, 'B');
|
||||
test_assert(23, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostI(&mb1, 'C');
|
||||
test_assert(24, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostI(&mb1, 'D');
|
||||
test_assert(25, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostI(&mb1, 'E');
|
||||
chSysUnlock();
|
||||
test_assert(26, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_assert(27, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
for (i = 0; i < MB_SIZE; i++) {
|
||||
chSysLock();
|
||||
msg1 = chMBFetchI(&mb1, &msg2);
|
||||
chSysUnlock();
|
||||
test_assert(28, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_emit_token(msg2);
|
||||
}
|
||||
test_assert_sequence(29, "ABCDE");
|
||||
test_assert_lock(30, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||
test_assert_lock(31, chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||
test_assert(32, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
|
||||
chSysLock();
|
||||
msg1 = chMBPostAheadI(&mb1, 'E');
|
||||
test_assert(33, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostAheadI(&mb1, 'D');
|
||||
test_assert(34, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostAheadI(&mb1, 'C');
|
||||
test_assert(35, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostAheadI(&mb1, 'B');
|
||||
test_assert(36, msg1 == RDY_OK, "wrong wake-up message");
|
||||
msg1 = chMBPostAheadI(&mb1, 'A');
|
||||
chSysUnlock();
|
||||
test_assert(37, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_assert(38, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
for (i = 0; i < MB_SIZE; i++) {
|
||||
chSysLock();
|
||||
msg1 = chMBFetchI(&mb1, &msg2);
|
||||
chSysUnlock();
|
||||
test_assert(39, msg1 == RDY_OK, "wrong wake-up message");
|
||||
test_emit_token(msg2);
|
||||
}
|
||||
test_assert_sequence(40, "ABCDE");
|
||||
test_assert_lock(41, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||
test_assert_lock(42, chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||
test_assert(43, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
|
||||
|
||||
/*
|
||||
* Testing reset.
|
||||
*/
|
||||
chMBReset(&mb1);
|
||||
|
||||
/*
|
||||
* Re-testing final conditions.
|
||||
*/
|
||||
test_assert_lock(44, chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||
test_assert_lock(45, chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||
test_assert_lock(46, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base");
|
||||
test_assert_lock(47, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmbox1 = {
|
||||
"Mailboxes, queuing and timeouts",
|
||||
mbox1_setup,
|
||||
NULL,
|
||||
mbox1_execute
|
||||
};
|
||||
|
||||
#endif /* CH_USE_MAILBOXES */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for mailboxes.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternmbox[] = {
|
||||
#if CH_USE_MAILBOXES || defined(__DOXYGEN__)
|
||||
&testmbox1,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testmbox.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testmbox.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTMBOX_H_
|
||||
#define _TESTMBOX_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternmbox[];
|
||||
|
||||
#endif /* _TESTMBOX_H_ */
|
108
Software/portapack-mayhem/firmware/chibios/test/testmsg.c
Normal file
108
Software/portapack-mayhem/firmware/chibios/test/testmsg.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_msg Messages test
|
||||
*
|
||||
* File: @ref testmsg.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref messages subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref messages
|
||||
* subsystem code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_MESSAGES
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_msg_001
|
||||
* .
|
||||
* @file testmsg.c
|
||||
* @brief Messages test source file
|
||||
* @file testmsg.h
|
||||
* @brief Messages header file
|
||||
*/
|
||||
|
||||
#if CH_USE_MESSAGES || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
* @page test_msg_001 Messages Server loop
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A thread is spawned that sends four messages back to the tester thread.<br>
|
||||
* The test expect to receive the messages in the correct sequence and to
|
||||
* not find a fifth message waiting.
|
||||
*/
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
|
||||
chMsgSend(p, 'A');
|
||||
chMsgSend(p, 'B');
|
||||
chMsgSend(p, 'C');
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msg1_execute(void) {
|
||||
Thread *tp;
|
||||
msg_t msg;
|
||||
|
||||
/*
|
||||
* Testing the whole messages loop.
|
||||
*/
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() + 1,
|
||||
thread, chThdSelf());
|
||||
tp = chMsgWait();
|
||||
msg = chMsgGet(tp);
|
||||
chMsgRelease(tp, msg);
|
||||
test_emit_token(msg);
|
||||
tp = chMsgWait();
|
||||
msg = chMsgGet(tp);
|
||||
chMsgRelease(tp, msg);
|
||||
test_emit_token(msg);
|
||||
tp = chMsgWait();
|
||||
msg = chMsgGet(tp);
|
||||
chMsgRelease(tp, msg);
|
||||
test_emit_token(msg);
|
||||
test_assert_sequence(1, "ABC");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmsg1 = {
|
||||
"Messages, loop",
|
||||
NULL,
|
||||
NULL,
|
||||
msg1_execute
|
||||
};
|
||||
|
||||
#endif /* CH_USE_MESSAGES */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for messages.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternmsg[] = {
|
||||
#if CH_USE_MESSAGES || defined(__DOXYGEN__)
|
||||
&testmsg1,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testmsg.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testmsg.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTMSG_H_
|
||||
#define _TESTMSG_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternmsg[];
|
||||
|
||||
#endif /* _TESTMSG_H_ */
|
636
Software/portapack-mayhem/firmware/chibios/test/testmtx.c
Normal file
636
Software/portapack-mayhem/firmware/chibios/test/testmtx.c
Normal file
@ -0,0 +1,636 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_mtx Mutexes test
|
||||
*
|
||||
* File: @ref testmtx.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref mutexes and
|
||||
* @ref condvars subsystems.<br>
|
||||
* Tests on those subsystems are particularly critical because the system-wide
|
||||
* implications of the Priority Inheritance mechanism.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the subsystems code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_MUTEXES
|
||||
* - @p CH_USE_CONDVARS
|
||||
* - @p CH_DBG_THREADS_PROFILING
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_mtx_001
|
||||
* - @subpage test_mtx_002
|
||||
* - @subpage test_mtx_003
|
||||
* - @subpage test_mtx_004
|
||||
* - @subpage test_mtx_005
|
||||
* - @subpage test_mtx_006
|
||||
* - @subpage test_mtx_007
|
||||
* - @subpage test_mtx_008
|
||||
* .
|
||||
* @file testmtx.c
|
||||
* @brief Mutexes and CondVars test source file
|
||||
* @file testmtx.h
|
||||
* @brief Mutexes and CondVars test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
|
||||
#define ALLOWED_DELAY 5
|
||||
|
||||
/*
|
||||
* Note, the static initializers are not really required because the
|
||||
* variables are explicitly initialized in each test case. It is done in order
|
||||
* to test the macros.
|
||||
*/
|
||||
static MUTEX_DECL(m1);
|
||||
static MUTEX_DECL(m2);
|
||||
#if CH_USE_CONDVARS || defined(__DOXYGEN__)
|
||||
static CONDVAR_DECL(c1);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page test_mtx_001 Priority enqueuing test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads, with increasing priority, are enqueued on a locked mutex then
|
||||
* the mutex is unlocked.<br>
|
||||
* The test expects the threads to perform their operations in increasing
|
||||
* priority order regardless of the initial order.
|
||||
*/
|
||||
|
||||
static void mtx1_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
test_emit_token(*(char *)p);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx1_execute(void) {
|
||||
|
||||
tprio_t prio = chThdGetPriority(); /* Because priority inheritance.*/
|
||||
chMtxLock(&m1);
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread1, "E");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread1, "D");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");
|
||||
chMtxUnlock();
|
||||
test_wait_threads();
|
||||
test_assert(1, prio == chThdGetPriority(), "wrong priority level");
|
||||
test_assert_sequence(2, "ABCDE");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx1 = {
|
||||
"Mutexes, priority enqueuing test",
|
||||
mtx1_setup,
|
||||
NULL,
|
||||
mtx1_execute
|
||||
};
|
||||
|
||||
#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_mtx_002 Priority inheritance, simple case
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Three threads are involved in the classic priority inversion scenario, a
|
||||
* medium priority thread tries to starve an high priority thread by
|
||||
* blocking a low priority thread into a mutex lock zone.<br>
|
||||
* The test expects the threads to reach their goal in increasing priority
|
||||
* order by rearranging their priorities in order to avoid the priority
|
||||
* inversion trap.
|
||||
*
|
||||
* <h2>Scenario</h2>
|
||||
* This weird looking diagram should explain what happens in the test case:
|
||||
* @code
|
||||
* Time ----> 0 10 20 30 40 50 60 70 80 90 100
|
||||
* 0 ......AL++++++++++............2+++++++++++AU0---------------++++++G...
|
||||
* 1 ..................++++++++++++------------------++++++++++++G.........
|
||||
* 2 .............................AL..........++++++AUG...................
|
||||
* ^ ^
|
||||
* Legend:
|
||||
* 0..2 - Priority levels
|
||||
* +++ - Running
|
||||
* --- - Ready
|
||||
* ... - Waiting or Terminated
|
||||
* xL - Lock operation on mutex 'x'
|
||||
* xUn - Unlock operation on mutex 'x' with priority returning to level 'n'
|
||||
* G - Goal
|
||||
* ^ - Priority transition (boost or return).
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
static void mtx2_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
/* Low priority thread */
|
||||
static msg_t thread2L(void *p) {
|
||||
|
||||
(void)p;
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(40);
|
||||
chMtxUnlock();
|
||||
test_cpu_pulse(10);
|
||||
test_emit_token('C');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Medium priority thread */
|
||||
static msg_t thread2M(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(20);
|
||||
test_cpu_pulse(40);
|
||||
test_emit_token('B');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* High priority thread */
|
||||
static msg_t thread2H(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(40);
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(10);
|
||||
chMtxUnlock();
|
||||
test_emit_token('A');
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx2_execute(void) {
|
||||
systime_t time;
|
||||
|
||||
test_wait_tick();
|
||||
time = chTimeNow();
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread2H, 0);
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-2, thread2M, 0);
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread2L, 0);
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABC");
|
||||
test_assert_time_window(2, time + MS2ST(100), time + MS2ST(100) + ALLOWED_DELAY);
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx2 = {
|
||||
"Mutexes, priority inheritance, simple case",
|
||||
mtx2_setup,
|
||||
NULL,
|
||||
mtx2_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_mtx_003 Priority inheritance, complex case
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads are involved in the complex priority inversion scenario,
|
||||
* please refer to the diagram below for the complete scenario.<br>
|
||||
* The test expects the threads to perform their operations in increasing
|
||||
* priority order by rearranging their priorities in order to avoid the
|
||||
* priority inversion trap.
|
||||
*
|
||||
* <h2>Scenario</h2>
|
||||
* This weird looking diagram should explain what happens in the test case:
|
||||
* @code
|
||||
* Time ----> 0 10 20 30 40 50 60 70 80 90 100 110
|
||||
* 0 ......BL++++------------2+++++------4+++++BU0---------------------------G.....
|
||||
* 1 ............AL++++2+++++BL----------4-----++++++BU4+++AU1---------------G.....
|
||||
* 2 ..................AL----------------------------------------------++++++AUG...
|
||||
* 3 ..............................+++++++-----------------------++++++G...........
|
||||
* 4 ....................................AL................++++++AUG...............
|
||||
* ^ ^ ^ ^ ^ ^
|
||||
* Legend:
|
||||
* 0..4 - Priority levels
|
||||
* +++ - Running
|
||||
* --- - Ready
|
||||
* ... - Waiting or Terminated
|
||||
* xL - Lock operation on mutex 'x'
|
||||
* xUn - Unlock operation on mutex 'x' with priority returning to level 'n'
|
||||
* ^ - Priority transition (boost or return).
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
static void mtx3_setup(void) {
|
||||
|
||||
chMtxInit(&m1); /* Mutex B.*/
|
||||
chMtxInit(&m2); /* Mutex A.*/
|
||||
}
|
||||
|
||||
/* Lowest priority thread */
|
||||
static msg_t thread3LL(void *p) {
|
||||
|
||||
(void)p;
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(30);
|
||||
chMtxUnlock();
|
||||
test_emit_token('E');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Low priority thread */
|
||||
static msg_t thread3L(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(10);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(20);
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(10);
|
||||
chMtxUnlock();
|
||||
test_cpu_pulse(10);
|
||||
chMtxUnlock();
|
||||
test_emit_token('D');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Medium priority thread */
|
||||
static msg_t thread3M(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(20);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(10);
|
||||
chMtxUnlock();
|
||||
test_emit_token('C');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* High priority thread */
|
||||
static msg_t thread3H(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(40);
|
||||
test_cpu_pulse(20);
|
||||
test_emit_token('B');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Highest priority thread */
|
||||
static msg_t thread3HH(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(50);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(10);
|
||||
chMtxUnlock();
|
||||
test_emit_token('A');
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx3_execute(void) {
|
||||
systime_t time;
|
||||
|
||||
test_wait_tick();
|
||||
time = chTimeNow();
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread3LL, 0);
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread3L, 0);
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread3M, 0);
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-2, thread3H, 0);
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread3HH, 0);
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
test_assert_time_window(2, time + MS2ST(110), time + MS2ST(110) + ALLOWED_DELAY);
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx3 = {
|
||||
"Mutexes, priority inheritance, complex case",
|
||||
mtx3_setup,
|
||||
NULL,
|
||||
mtx3_execute
|
||||
};
|
||||
#endif /* CH_DBG_THREADS_PROFILING */
|
||||
|
||||
/**
|
||||
* @page test_mtx_004 Priority return verification
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Two threads are spawned that try to lock the mutexes locked by the tester
|
||||
* thread with precise timing.<br>
|
||||
* The test expects that the priority changes caused by the priority
|
||||
* inheritance algorithm happen at the right moment and with the right values.
|
||||
*/
|
||||
|
||||
static void mtx4_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
chMtxInit(&m2);
|
||||
}
|
||||
|
||||
static msg_t thread4a(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(50);
|
||||
chMtxLock(&m2);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread4b(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(150);
|
||||
chMtxLock(&m1);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx4_execute(void) {
|
||||
tprio_t p, p1, p2;
|
||||
|
||||
p = chThdGetPriority();
|
||||
p1 = p + 1;
|
||||
p2 = p + 2;
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, p1, thread4a, "B");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, p2, thread4b, "A");
|
||||
chMtxLock(&m2);
|
||||
test_assert(1, chThdGetPriority() == p, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(2, chThdGetPriority() == p1, "wrong priority level");
|
||||
chMtxLock(&m1);
|
||||
test_assert(3, chThdGetPriority() == p1, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(4, chThdGetPriority() == p2, "wrong priority level");
|
||||
chMtxUnlock();
|
||||
test_assert(5, chThdGetPriority() == p1, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(6, chThdGetPriority() == p1, "wrong priority level");
|
||||
chMtxUnlockAll();
|
||||
test_assert(7, chThdGetPriority() == p, "wrong priority level");
|
||||
test_wait_threads();
|
||||
|
||||
/* Test repeated in order to cover chMtxUnlockS().*/
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, p1, thread4a, "D");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, p2, thread4b, "C");
|
||||
chMtxLock(&m2);
|
||||
test_assert(8, chThdGetPriority() == p, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(9, chThdGetPriority() == p1, "wrong priority level");
|
||||
chMtxLock(&m1);
|
||||
test_assert(10, chThdGetPriority() == p1, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(11, chThdGetPriority() == p2, "wrong priority level");
|
||||
chSysLock();
|
||||
chMtxUnlockS();
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
test_assert(12, chThdGetPriority() == p1, "wrong priority level");
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert(13, chThdGetPriority() == p1, "wrong priority level");
|
||||
chMtxUnlockAll();
|
||||
test_assert(14, chThdGetPriority() == p, "wrong priority level");
|
||||
test_wait_threads();
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx4 = {
|
||||
"Mutexes, priority return",
|
||||
mtx4_setup,
|
||||
NULL,
|
||||
mtx4_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_mtx_005 Mutex status
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Various tests on the mutex structure status after performing some lock and
|
||||
* unlock operations.<br>
|
||||
* The test expects that the internal mutex status is consistent after each
|
||||
* operation.
|
||||
*/
|
||||
|
||||
static void mtx5_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static void mtx5_execute(void) {
|
||||
bool_t b;
|
||||
tprio_t prio;
|
||||
|
||||
prio = chThdGetPriority();
|
||||
|
||||
b = chMtxTryLock(&m1);
|
||||
test_assert(1, b, "already locked");
|
||||
|
||||
b = chMtxTryLock(&m1);
|
||||
test_assert(2, !b, "not locked");
|
||||
|
||||
chSysLock();
|
||||
chMtxUnlockS();
|
||||
chSysUnlock();
|
||||
|
||||
test_assert(3, isempty(&m1.m_queue), "queue not empty");
|
||||
test_assert(4, m1.m_owner == NULL, "still owned");
|
||||
test_assert(5, chThdGetPriority() == prio, "wrong priority level");
|
||||
|
||||
chMtxLock(&m1);
|
||||
chMtxUnlockAll();
|
||||
test_assert(6, isempty(&m1.m_queue), "queue not empty");
|
||||
test_assert(7, m1.m_owner == NULL, "still owned");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx5 = {
|
||||
"Mutexes, status",
|
||||
mtx5_setup,
|
||||
NULL,
|
||||
mtx5_execute
|
||||
};
|
||||
|
||||
#if CH_USE_CONDVARS || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_mtx_006 Condition Variable signal test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads take a mutex and then enter a conditional variable queue, the
|
||||
* tester thread then proceeds to signal the conditional variable five times
|
||||
* atomically.<br>
|
||||
* The test expects the threads to reach their goal in increasing priority
|
||||
* order regardless of the initial order.
|
||||
*/
|
||||
|
||||
static void mtx6_setup(void) {
|
||||
|
||||
chCondInit(&c1);
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static msg_t thread10(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
chCondWait(&c1);
|
||||
test_emit_token(*(char *)p);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx6_execute(void) {
|
||||
|
||||
tprio_t prio = chThdGetPriority();
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread10, "E");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread10, "D");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread10, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread10, "B");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread10, "A");
|
||||
chSysLock();
|
||||
chCondSignalI(&c1);
|
||||
chCondSignalI(&c1);
|
||||
chCondSignalI(&c1);
|
||||
chCondSignalI(&c1);
|
||||
chCondSignalI(&c1);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx6 = {
|
||||
"CondVar, signal test",
|
||||
mtx6_setup,
|
||||
NULL,
|
||||
mtx6_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_mtx_007 Condition Variable broadcast test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads take a mutex and then enter a conditional variable queue, the
|
||||
* tester thread then proceeds to broadcast the conditional variable.<br>
|
||||
* The test expects the threads to reach their goal in increasing priority
|
||||
* order regardless of the initial order.
|
||||
*/
|
||||
|
||||
static void mtx7_setup(void) {
|
||||
|
||||
chCondInit(&c1);
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static void mtx7_execute(void) {
|
||||
|
||||
tprio_t prio = chThdGetPriority();
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread10, "E");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread10, "D");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread10, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread10, "B");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread10, "A");
|
||||
chCondBroadcast(&c1);
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx7 = {
|
||||
"CondVar, broadcast test",
|
||||
mtx7_setup,
|
||||
NULL,
|
||||
mtx7_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_mtx_008 Condition Variable priority boost test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case verifies the priority boost of a thread waiting on a
|
||||
* conditional variable queue. It tests this very specific situation in order
|
||||
* to complete the code coverage.
|
||||
*/
|
||||
|
||||
static void mtx8_setup(void) {
|
||||
|
||||
chCondInit(&c1);
|
||||
chMtxInit(&m1);
|
||||
chMtxInit(&m2);
|
||||
}
|
||||
|
||||
static msg_t thread11(void *p) {
|
||||
|
||||
chMtxLock(&m2);
|
||||
chMtxLock(&m1);
|
||||
#if CH_USE_CONDVARS_TIMEOUT || defined(__DOXYGEN__)
|
||||
chCondWaitTimeout(&c1, TIME_INFINITE);
|
||||
#else
|
||||
chCondWait(&c1);
|
||||
#endif
|
||||
test_emit_token(*(char *)p);
|
||||
chMtxUnlock();
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread12(void *p) {
|
||||
|
||||
chMtxLock(&m2);
|
||||
test_emit_token(*(char *)p);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx8_execute(void) {
|
||||
|
||||
tprio_t prio = chThdGetPriority();
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread11, "A");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread10, "C");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread12, "B");
|
||||
chCondSignal(&c1);
|
||||
chCondSignal(&c1);
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABC");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testmtx8 = {
|
||||
"CondVar, boost test",
|
||||
mtx8_setup,
|
||||
NULL,
|
||||
mtx8_execute
|
||||
};
|
||||
#endif /* CH_USE_CONDVARS */
|
||||
#endif /* CH_USE_MUTEXES */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for mutexes.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternmtx[] = {
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
&testmtx1,
|
||||
#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__)
|
||||
&testmtx2,
|
||||
&testmtx3,
|
||||
#endif
|
||||
&testmtx4,
|
||||
&testmtx5,
|
||||
#if CH_USE_CONDVARS || defined(__DOXYGEN__)
|
||||
&testmtx6,
|
||||
&testmtx7,
|
||||
&testmtx8,
|
||||
#endif
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testmtx.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testmtx.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTMTX_H_
|
||||
#define _TESTMTX_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternmtx[];
|
||||
|
||||
#endif /* _TESTMTX_H_ */
|
117
Software/portapack-mayhem/firmware/chibios/test/testpools.c
Normal file
117
Software/portapack-mayhem/firmware/chibios/test/testpools.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_pools Memory Pools test
|
||||
*
|
||||
* File: @ref testpools.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref pools subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref pools code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_MEMPOOLS
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_pools_001
|
||||
* .
|
||||
* @file testpools.c
|
||||
* @brief Memory Pools test source file
|
||||
* @file testpools.h
|
||||
* @brief Memory Pools test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
|
||||
|
||||
static MEMORYPOOL_DECL(mp1, THD_WA_SIZE(THREADS_STACK_SIZE), NULL);
|
||||
|
||||
/**
|
||||
* @page test_pools_001 Allocation and enqueuing test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five memory blocks are added to a memory pool then removed.<br>
|
||||
* The test expects to find the pool queue in the proper status after each
|
||||
* operation.
|
||||
*/
|
||||
|
||||
static void *null_provider(size_t size) {
|
||||
|
||||
(void)size;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pools1_setup(void) {
|
||||
|
||||
chPoolInit(&mp1, THD_WA_SIZE(THREADS_STACK_SIZE), NULL);
|
||||
}
|
||||
|
||||
static void pools1_execute(void) {
|
||||
int i;
|
||||
|
||||
/* Adding the WAs to the pool.*/
|
||||
chPoolLoadArray(&mp1, wa[0], MAX_THREADS);
|
||||
|
||||
/* Emptying the pool.*/
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
test_assert(1, chPoolAlloc(&mp1) != NULL, "list empty");
|
||||
|
||||
/* Now must be empty.*/
|
||||
test_assert(2, chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||
|
||||
/* Adding the WAs to the pool, one by one this time.*/
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
chPoolFree(&mp1, wa[i]);
|
||||
|
||||
/* Emptying the pool again.*/
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
test_assert(3, chPoolAlloc(&mp1) != NULL, "list empty");
|
||||
|
||||
/* Now must be empty again.*/
|
||||
test_assert(4, chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||
|
||||
/* Covering the case where a provider is unable to return more memory.*/
|
||||
chPoolInit(&mp1, 16, null_provider);
|
||||
test_assert(5, chPoolAlloc(&mp1) == NULL, "provider returned memory");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testpools1 = {
|
||||
"Memory Pools, queue/dequeue",
|
||||
pools1_setup,
|
||||
NULL,
|
||||
pools1_execute
|
||||
};
|
||||
|
||||
#endif /* CH_USE_MEMPOOLS */
|
||||
|
||||
/*
|
||||
* @brief Test sequence for pools.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternpools[] = {
|
||||
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
|
||||
&testpools1,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testpools.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testpools.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTPOOLS_H_
|
||||
#define _TESTPOOLS_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternpools[];
|
||||
|
||||
#endif /* _TESTPOOLS_H_ */
|
244
Software/portapack-mayhem/firmware/chibios/test/testqueues.c
Normal file
244
Software/portapack-mayhem/firmware/chibios/test/testqueues.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_queues I/O Queues test
|
||||
*
|
||||
* File: @ref testqueues.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref io_queues subsystem.
|
||||
* The tests are performed by inserting and removing data from queues and by
|
||||
* checking both the queues status and the correct sequence of the extracted
|
||||
* data.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref io_queues code.<br>
|
||||
* Note that the @ref io_queues subsystem depends on the @ref semaphores
|
||||
* subsystem that has to met its testing objectives as well.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_QUEUES (and dependent options)
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_queues_001
|
||||
* - @subpage test_queues_002
|
||||
* .
|
||||
* @file testqueues.c
|
||||
* @brief I/O Queues test source file
|
||||
* @file testqueues.h
|
||||
* @brief I/O Queues test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_QUEUES || defined(__DOXYGEN__)
|
||||
|
||||
#define TEST_QUEUES_SIZE 4
|
||||
|
||||
static void notify(GenericQueue *qp) {
|
||||
(void)qp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, the static initializers are not really required because the
|
||||
* variables are explicitly initialized in each test case. It is done in order
|
||||
* to test the macros.
|
||||
*/
|
||||
static INPUTQUEUE_DECL(iq, test.wa.T0, TEST_QUEUES_SIZE, notify, NULL);
|
||||
static OUTPUTQUEUE_DECL(oq, test.wa.T1, TEST_QUEUES_SIZE, notify, NULL);
|
||||
|
||||
/**
|
||||
* @page test_queues_001 Input Queues functionality and APIs
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case tests sysnchronos and asynchronous operations on an
|
||||
* @p InputQueue object including timeouts. The queue state must remain
|
||||
* consistent through the whole test.
|
||||
*/
|
||||
|
||||
static void queues1_setup(void) {
|
||||
|
||||
chIQInit(&iq, wa[0], TEST_QUEUES_SIZE, notify, NULL);
|
||||
}
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
|
||||
(void)p;
|
||||
chIQGetTimeout(&iq, MS2ST(200));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void queues1_execute(void) {
|
||||
unsigned i;
|
||||
size_t n;
|
||||
|
||||
/* Initial empty state */
|
||||
test_assert_lock(1, chIQIsEmptyI(&iq), "not empty");
|
||||
|
||||
/* Queue filling */
|
||||
chSysLock();
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++)
|
||||
chIQPutI(&iq, 'A' + i);
|
||||
chSysUnlock();
|
||||
test_assert_lock(2, chIQIsFullI(&iq), "still has space");
|
||||
test_assert_lock(3, chIQPutI(&iq, 0) == Q_FULL, "failed to report Q_FULL");
|
||||
|
||||
/* Queue emptying */
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++)
|
||||
test_emit_token(chIQGet(&iq));
|
||||
test_assert_lock(4, chIQIsEmptyI(&iq), "still full");
|
||||
test_assert_sequence(5, "ABCD");
|
||||
|
||||
/* Queue filling again */
|
||||
chSysLock();
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++)
|
||||
chIQPutI(&iq, 'A' + i);
|
||||
chSysUnlock();
|
||||
|
||||
/* Reading the whole thing */
|
||||
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
|
||||
test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
|
||||
test_assert_lock(7, chIQIsEmptyI(&iq), "still full");
|
||||
|
||||
/* Queue filling again */
|
||||
chSysLock();
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++)
|
||||
chIQPutI(&iq, 'A' + i);
|
||||
chSysUnlock();
|
||||
|
||||
/* Partial reads */
|
||||
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
|
||||
test_assert(8, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
|
||||
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
|
||||
test_assert(9, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
|
||||
test_assert_lock(10, chIQIsEmptyI(&iq), "still full");
|
||||
|
||||
/* Testing reset */
|
||||
chSysLock();
|
||||
chIQPutI(&iq, 0);
|
||||
chIQResetI(&iq);
|
||||
chSysUnlock();
|
||||
test_assert_lock(11, chIQGetFullI(&iq) == 0, "still full");
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL);
|
||||
test_assert_lock(12, chIQGetFullI(&iq) == 0, "not empty");
|
||||
test_wait_threads();
|
||||
|
||||
/* Timeout */
|
||||
test_assert(13, chIQGetTimeout(&iq, 10) == Q_TIMEOUT, "wrong timeout return");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testqueues1 = {
|
||||
"Queues, input queues",
|
||||
queues1_setup,
|
||||
NULL,
|
||||
queues1_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_queues_002 Output Queues functionality and APIs
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case tests sysnchronos and asynchronous operations on an
|
||||
* @p OutputQueue object including timeouts. The queue state must remain
|
||||
* consistent through the whole test.
|
||||
*/
|
||||
|
||||
static void queues2_setup(void) {
|
||||
|
||||
chOQInit(&oq, wa[0], TEST_QUEUES_SIZE, notify, NULL);
|
||||
}
|
||||
|
||||
static msg_t thread2(void *p) {
|
||||
|
||||
(void)p;
|
||||
chOQPutTimeout(&oq, 0, MS2ST(200));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void queues2_execute(void) {
|
||||
unsigned i;
|
||||
size_t n;
|
||||
|
||||
/* Initial empty state */
|
||||
test_assert_lock(1, chOQIsEmptyI(&oq), "not empty");
|
||||
|
||||
/* Queue filling */
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++)
|
||||
chOQPut(&oq, 'A' + i);
|
||||
test_assert_lock(2, chOQIsFullI(&oq), "still has space");
|
||||
|
||||
/* Queue emptying */
|
||||
for (i = 0; i < TEST_QUEUES_SIZE; i++) {
|
||||
char c;
|
||||
|
||||
chSysLock();
|
||||
c = chOQGetI(&oq);
|
||||
chSysUnlock();
|
||||
test_emit_token(c);
|
||||
}
|
||||
test_assert_lock(3, chOQIsEmptyI(&oq), "still full");
|
||||
test_assert_sequence(4, "ABCD");
|
||||
test_assert_lock(5, chOQGetI(&oq) == Q_EMPTY, "failed to report Q_EMPTY");
|
||||
|
||||
/* Writing the whole thing */
|
||||
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
|
||||
test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
|
||||
test_assert_lock(7, chOQIsFullI(&oq), "not full");
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread2, NULL);
|
||||
test_assert_lock(8, chOQGetFullI(&oq) == TEST_QUEUES_SIZE, "not empty");
|
||||
test_wait_threads();
|
||||
|
||||
/* Testing reset */
|
||||
chSysLock();
|
||||
chOQResetI(&oq);
|
||||
chSysUnlock();
|
||||
test_assert_lock(9, chOQGetFullI(&oq) == 0, "still full");
|
||||
|
||||
/* Partial writes */
|
||||
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
|
||||
test_assert(10, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
|
||||
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
|
||||
test_assert(11, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
|
||||
test_assert_lock(12, chOQIsFullI(&oq), "not full");
|
||||
|
||||
/* Timeout */
|
||||
test_assert(13, chOQPutTimeout(&oq, 0, 10) == Q_TIMEOUT, "wrong timeout return");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testqueues2 = {
|
||||
"Queues, output queues",
|
||||
queues2_setup,
|
||||
NULL,
|
||||
queues2_execute
|
||||
};
|
||||
#endif /* CH_USE_QUEUES */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for queues.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternqueues[] = {
|
||||
#if CH_USE_QUEUES || defined(__DOXYGEN__)
|
||||
&testqueues1,
|
||||
&testqueues2,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testqueues.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testqueues.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTQUEUES_H_
|
||||
#define _TESTQUEUES_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternqueues[];
|
||||
|
||||
#endif /* _TESTQUEUES_H_ */
|
303
Software/portapack-mayhem/firmware/chibios/test/testsem.c
Normal file
303
Software/portapack-mayhem/firmware/chibios/test/testsem.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_sem Semaphores test
|
||||
*
|
||||
* File: @ref testsem.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref semaphores subsystem.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the @ref semaphores code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* The module requires the following kernel options:
|
||||
* - @p CH_USE_SEMAPHORES
|
||||
* .
|
||||
* In case some of the required options are not enabled then some or all tests
|
||||
* may be skipped.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_sem_001
|
||||
* - @subpage test_sem_002
|
||||
* - @subpage test_sem_003
|
||||
* - @subpage test_sem_004
|
||||
* .
|
||||
* @file testsem.c
|
||||
* @brief Semaphores test source file
|
||||
* @file testsem.h
|
||||
* @brief Semaphores test header file
|
||||
*/
|
||||
|
||||
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
|
||||
|
||||
#define ALLOWED_DELAY MS2ST(5)
|
||||
|
||||
/*
|
||||
* Note, the static initializers are not really required because the
|
||||
* variables are explicitly initialized in each test case. It is done in order
|
||||
* to test the macros.
|
||||
*/
|
||||
static SEMAPHORE_DECL(sem1, 0);
|
||||
|
||||
/**
|
||||
* @page test_sem_001 Enqueuing test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads with randomized priorities are enqueued to a semaphore then
|
||||
* awakened one at time.<br>
|
||||
* The test expects that the threads reach their goal in FIFO order or
|
||||
* priority order depending on the CH_USE_SEMAPHORES_PRIORITY configuration
|
||||
* setting.
|
||||
*/
|
||||
|
||||
static void sem1_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
|
||||
chSemWait(&sem1);
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sem1_execute(void) {
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread1, "A");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()+1, thread1, "B");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()+3, thread1, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()+4, thread1, "D");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()+2, thread1, "E");
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
test_wait_threads();
|
||||
#if CH_USE_SEMAPHORES_PRIORITY
|
||||
test_assert_sequence(1, "ADCEB");
|
||||
#else
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
#endif
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread1, "A");
|
||||
chSysLock();
|
||||
chSemAddCounterI(&sem1, 2);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
test_wait_threads();
|
||||
test_assert(2, chSemGetCounterI(&sem1) == 1, "invalid counter");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testsem1 = {
|
||||
"Semaphores, enqueuing",
|
||||
sem1_setup,
|
||||
NULL,
|
||||
sem1_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_sem_002 Timeout test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The three possible semaphore waiting modes (do not wait, wait with timeout,
|
||||
* wait without timeout) are explored.<br>
|
||||
* The test expects that the semaphore wait function returns the correct value
|
||||
* in each of the above scenario and that the semaphore structure status is
|
||||
* correct after each operation.
|
||||
*/
|
||||
|
||||
static void sem2_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static msg_t thread2(void *p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(50);
|
||||
chSysLock();
|
||||
chSemSignalI(&sem1); /* For coverage reasons */
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sem2_execute(void) {
|
||||
int i;
|
||||
systime_t target_time;
|
||||
msg_t msg;
|
||||
|
||||
/*
|
||||
* Testing special case TIME_IMMEDIATE.
|
||||
*/
|
||||
msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE);
|
||||
test_assert(1, msg == RDY_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(2, isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(3, sem1.s_cnt == 0, "counter not zero");
|
||||
|
||||
/*
|
||||
* Testing not timeout condition.
|
||||
*/
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
|
||||
thread2, 0);
|
||||
msg = chSemWaitTimeout(&sem1, MS2ST(500));
|
||||
test_wait_threads();
|
||||
test_assert(4, msg == RDY_OK, "wrong wake-up message");
|
||||
test_assert(5, isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(6, sem1.s_cnt == 0, "counter not zero");
|
||||
|
||||
/*
|
||||
* Testing timeout condition.
|
||||
*/
|
||||
test_wait_tick();
|
||||
target_time = chTimeNow() + MS2ST(5 * 500);
|
||||
for (i = 0; i < 5; i++) {
|
||||
test_emit_token('A' + i);
|
||||
msg = chSemWaitTimeout(&sem1, MS2ST(500));
|
||||
test_assert(7, msg == RDY_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(8, isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(9, sem1.s_cnt == 0, "counter not zero");
|
||||
}
|
||||
test_assert_sequence(10, "ABCDE");
|
||||
test_assert_time_window(11, target_time, target_time + ALLOWED_DELAY);
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testsem2 = {
|
||||
"Semaphores, timeout",
|
||||
sem2_setup,
|
||||
NULL,
|
||||
sem2_execute
|
||||
};
|
||||
|
||||
#if CH_USE_SEMSW || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_sem_003 Atomic signal-wait test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case explicitly addresses the @p chSemWaitSignal() function. A
|
||||
* thread is created that performs a wait and a signal operations.
|
||||
* The tester thread is awakened from an atomic wait/signal operation.<br>
|
||||
* The test expects that the semaphore wait function returns the correct value
|
||||
* in each of the above scenario and that the semaphore structure status is
|
||||
* correct after each operation.
|
||||
*/
|
||||
|
||||
static void sem3_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static msg_t thread3(void *p) {
|
||||
|
||||
(void)p;
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sem3_execute(void) {
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread3, 0);
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(1, isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(2, sem1.s_cnt == 0, "counter not zero");
|
||||
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(3, isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(4, sem1.s_cnt == 0, "counter not zero");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testsem3 = {
|
||||
"Semaphores, atomic signal-wait",
|
||||
sem3_setup,
|
||||
NULL,
|
||||
sem3_execute
|
||||
};
|
||||
#endif /* CH_USE_SEMSW */
|
||||
|
||||
/**
|
||||
* @page test_sem_004 Binary Wait and Signal
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case tests the binary semaphores functionality. The test both
|
||||
* checks the binary semaphore status and the expected status of the underlying
|
||||
* counting semaphore.
|
||||
*/
|
||||
static msg_t thread4(void *p) {
|
||||
|
||||
chBSemSignal((BinarySemaphore *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sem4_execute(void) {
|
||||
BinarySemaphore bsem;
|
||||
|
||||
/* Creates a taken binary semaphore.*/
|
||||
chBSemInit(&bsem, TRUE);
|
||||
chBSemReset(&bsem, TRUE);
|
||||
test_assert(1, chBSemGetStateI(&bsem) == TRUE, "not taken");
|
||||
|
||||
/* Starts a signaler thread at a lower priority.*/
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE,
|
||||
chThdGetPriority()-1, thread4, &bsem);
|
||||
|
||||
/* Waits to be signaled.*/
|
||||
chBSemWait(&bsem);
|
||||
|
||||
/* The binary semaphore is expected to be taken.*/
|
||||
test_assert(2, chBSemGetStateI(&bsem) == TRUE, "not taken");
|
||||
|
||||
/* Releasing it, check both the binary semaphore state and the underlying
|
||||
counter semaphore state..*/
|
||||
chBSemSignal(&bsem);
|
||||
test_assert(3, chBSemGetStateI(&bsem) == FALSE, "still taken");
|
||||
test_assert(4, chSemGetCounterI(&bsem.bs_sem) == 1, "unexpected counter");
|
||||
|
||||
/* Checking signaling overflow, the counter must not go beyond 1.*/
|
||||
chBSemSignal(&bsem);
|
||||
test_assert(3, chBSemGetStateI(&bsem) == FALSE, "taken");
|
||||
test_assert(5, chSemGetCounterI(&bsem.bs_sem) == 1, "unexpected counter");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testsem4 = {
|
||||
"Binary Semaphores, functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
sem4_execute
|
||||
};
|
||||
#endif /* CH_USE_SEMAPHORES */
|
||||
|
||||
/**
|
||||
* @brief Test sequence for semaphores.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternsem[] = {
|
||||
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
|
||||
&testsem1,
|
||||
&testsem2,
|
||||
#if CH_USE_SEMSW || defined(__DOXYGEN__)
|
||||
&testsem3,
|
||||
#endif
|
||||
&testsem4,
|
||||
#endif
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testsem.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testsem.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTSEM_H_
|
||||
#define _TESTSEM_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternsem[];
|
||||
|
||||
#endif /* _TESTSEM_H_ */
|
231
Software/portapack-mayhem/firmware/chibios/test/testthd.c
Normal file
231
Software/portapack-mayhem/firmware/chibios/test/testthd.c
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
/**
|
||||
* @page test_threads Threads and Scheduler test
|
||||
*
|
||||
* File: @ref testthd.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This module implements the test sequence for the @ref scheduler,
|
||||
* @ref threads and @ref time subsystems.<br>
|
||||
* Note that the tests on those subsystems are formally required but most of
|
||||
* their functionality is already demonstrated because the test suite itself
|
||||
* depends on them, anyway double check is good.
|
||||
*
|
||||
* <h2>Objective</h2>
|
||||
* Objective of the test module is to cover 100% of the subsystems code.
|
||||
*
|
||||
* <h2>Preconditions</h2>
|
||||
* None.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_threads_001
|
||||
* - @subpage test_threads_002
|
||||
* - @subpage test_threads_003
|
||||
* - @subpage test_threads_004
|
||||
* .
|
||||
* @file testthd.c
|
||||
* @brief Threads and Scheduler test source file
|
||||
* @file testthd.h
|
||||
* @brief Threads and Scheduler test header file
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page test_threads_001 Ready List functionality #1
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads, with increasing priority, are enqueued in the ready list
|
||||
* and atomically executed.<br>
|
||||
* The test expects the threads to perform their operations in increasing
|
||||
* priority order regardless of the initial order.
|
||||
*/
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thd1_execute(void) {
|
||||
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread, "E");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread, "D");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-2, thread, "B");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread, "A");
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testthd1 = {
|
||||
"Threads, enqueuing test #1",
|
||||
NULL,
|
||||
NULL,
|
||||
thd1_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_threads_002 Ready List functionality #2
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads, with pseudo-random priority, are enqueued in the ready list
|
||||
* and atomically executed.<br>
|
||||
* The test expects the threads to perform their operations in increasing
|
||||
* priority order regardless of the initial order.
|
||||
*/
|
||||
|
||||
static void thd2_execute(void) {
|
||||
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread, "D");
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread, "E");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread, "A");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-2, thread, "B");
|
||||
/* Done this way for coverage of chThdCreateI() and chThdResume().*/
|
||||
chSysLock();
|
||||
threads[2] = chThdCreateI(wa[2], WA_SIZE, chThdGetPriority()-3, thread, "C");
|
||||
chSysUnlock();
|
||||
chThdResume(threads[2]);
|
||||
test_wait_threads();
|
||||
test_assert_sequence(1, "ABCDE");
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testthd2 = {
|
||||
"Threads, enqueuing test #2",
|
||||
NULL,
|
||||
NULL,
|
||||
thd2_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_threads_003 Threads priority change test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A series of priority changes are performed on the current thread in order
|
||||
* to verify that the priority change happens as expected.<br>
|
||||
* If the @p CH_USE_MUTEXES option is enabled then the priority changes are
|
||||
* also tested under priority inheritance boosted priority state.
|
||||
*/
|
||||
|
||||
static void thd3_execute(void) {
|
||||
tprio_t prio, p1;
|
||||
|
||||
prio = chThdGetPriority();
|
||||
p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(1, p1 == prio,
|
||||
"unexpected returned priority level");
|
||||
test_assert(2, chThdGetPriority() == prio + 1,
|
||||
"unexpected priority level");
|
||||
p1 = chThdSetPriority(p1);
|
||||
test_assert(3, p1 == prio + 1,
|
||||
"unexpected returned priority level");
|
||||
test_assert(4, chThdGetPriority() == prio,
|
||||
"unexpected priority level");
|
||||
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/* Simulates a priority boost situation (p_prio > p_realprio).*/
|
||||
chSysLock();
|
||||
chThdSelf()->p_prio += 2;
|
||||
chSysUnlock();
|
||||
test_assert(5, chThdGetPriority() == prio + 2,
|
||||
"unexpected priority level");
|
||||
|
||||
/* Tries to raise but below the boost level. */
|
||||
p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(6, p1 == prio,
|
||||
"unexpected returned priority level");
|
||||
test_assert(7, chThdSelf()->p_prio == prio + 2,
|
||||
"unexpected priority level");
|
||||
test_assert(8, chThdSelf()->p_realprio == prio + 1,
|
||||
"unexpected returned real priority level");
|
||||
|
||||
/* Tries to raise above the boost level. */
|
||||
p1 = chThdSetPriority(prio + 3);
|
||||
test_assert(9, p1 == prio + 1,
|
||||
"unexpected returned priority level");
|
||||
test_assert(10, chThdSelf()->p_prio == prio + 3,
|
||||
"unexpected priority level");
|
||||
test_assert(11, chThdSelf()->p_realprio == prio + 3,
|
||||
"unexpected real priority level");
|
||||
|
||||
chSysLock();
|
||||
chThdSelf()->p_prio = prio;
|
||||
chThdSelf()->p_realprio = prio;
|
||||
chSysUnlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testthd3 = {
|
||||
"Threads, priority change",
|
||||
NULL,
|
||||
NULL,
|
||||
thd3_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_threads_004 Threads delays test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Delay APIs and associated macros are tested, the invoking thread is verified
|
||||
* to wake up at the exact expected time.
|
||||
*/
|
||||
|
||||
static void thd4_execute(void) {
|
||||
systime_t time;
|
||||
|
||||
test_wait_tick();
|
||||
|
||||
/* Timeouts in microseconds.*/
|
||||
time = chTimeNow();
|
||||
chThdSleepMicroseconds(100000);
|
||||
test_assert_time_window(1, time + US2ST(100000), time + US2ST(100000) + 1);
|
||||
|
||||
/* Timeouts in milliseconds.*/
|
||||
time = chTimeNow();
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert_time_window(2, time + MS2ST(100), time + MS2ST(100) + 1);
|
||||
|
||||
/* Timeouts in seconds.*/
|
||||
time = chTimeNow();
|
||||
chThdSleepSeconds(1);
|
||||
test_assert_time_window(3, time + S2ST(1), time + S2ST(1) + 1);
|
||||
|
||||
/* Absolute timelines.*/
|
||||
time = chTimeNow() + MS2ST(100);
|
||||
chThdSleepUntil(time);
|
||||
test_assert_time_window(4, time, time + 1);
|
||||
}
|
||||
|
||||
ROMCONST struct testcase testthd4 = {
|
||||
"Threads, delays",
|
||||
NULL,
|
||||
NULL,
|
||||
thd4_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Test sequence for threads.
|
||||
*/
|
||||
ROMCONST struct testcase * ROMCONST patternthd[] = {
|
||||
&testthd1,
|
||||
&testthd2,
|
||||
&testthd3,
|
||||
&testthd4,
|
||||
NULL
|
||||
};
|
22
Software/portapack-mayhem/firmware/chibios/test/testthd.h
Normal file
22
Software/portapack-mayhem/firmware/chibios/test/testthd.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 _TESTRDY_H_
|
||||
#define _TESTRDY_H_
|
||||
|
||||
extern ROMCONST struct testcase * ROMCONST patternthd[];
|
||||
|
||||
#endif /* _TESTRDY_H_ */
|
Reference in New Issue
Block a user