import ChibiOS 2.0.8

This commit is contained in:
NIIBE Yutaka
2010-11-30 13:54:43 +09:00
parent 27543cfeca
commit c560d0ad0c
1982 changed files with 5318 additions and 4046 deletions

View File

@@ -0,0 +1,150 @@
#
# !!!! 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
#
# 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}/os/hal/hal.mk
include ${CHIBIOS}/os/hal/platforms/Win32/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} \
${CHIBIOS}/os/hal/platforms/Win32/console.c \
main.c
# List ASM source files here
ASRC =
# List all user directories here
UINCDIR = $(PORTINC) $(KERNINC) $(TESTINC) $(HALINC) $(PLATFORMINC) \
${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 ***

View File

@@ -0,0 +1,30 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#endif /* _BOARD_H_ */

View File

@@ -0,0 +1,494 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @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_
/*===========================================================================*/
/* Kernel parameters. */
/*===========================================================================*/
/**
* @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 Nested locks.
* @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
* operations is allowed.<br>
* For performance and code size reasons the recommended setting
* is to leave this option disabled.<br>
* You may use this option if you need to merge ChibiOS/RT with
* external libraries that require nested lock/unlock operations.
*
* @note T he default is @p FALSE.
*/
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
#define CH_USE_NESTED_LOCKS TRUE
#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_COREMEM.
*/
#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_MEMCORE_SIZE 0x20000
#endif
/*===========================================================================*/
/* 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
/**
* @brief Exotic optimization.
* @details If defined then a CPU register is used as storage for the global
* @p currp variable. Caching this variable in a register greatly
* improves both space and time OS efficiency. A side effect is that
* one less register has to be saved during the context switch
* resulting in lower RAM usage and faster context switch.
*
* @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the
* ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for
* documentation only.
*/
#if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg"
#endif
/*===========================================================================*/
/* 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.
* @note Requires @p CH_USE_SEMAPHORES.
*/
#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_COREMEM 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_COREMEM, 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
/*===========================================================================*/
/* Debug options. */
/*===========================================================================*/
/**
* @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 TRUE
#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
/*===========================================================================*/
/* Kernel hooks. */
/*===========================================================================*/
/**
* @brief Threads descriptor structure hook.
* @details User fields added to the end of the @p Thread structure.
*/
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \
struct { \
/* 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 implicitily from all
* the threads creation APIs.
*/
#if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(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) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \
/* Add threads finalization 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
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* _CHCONF_H_ */
/** @} */

View File

@@ -0,0 +1,159 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @addtogroup HAL_CONF
* @{
*/
/*
* 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.
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
/*
* Uncomment the following line in order to include a mcu-related
* settings file. This file can be used to include platform specific
* header files or to override the low level drivers settings.
*/
/*#include "mcuconf.h"*/
/*===========================================================================*/
/* PAL driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(CH_HAL_USE_PAL) || defined(__DOXYGEN__)
#define CH_HAL_USE_PAL FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(CH_HAL_USE_ADC) || defined(__DOXYGEN__)
#define CH_HAL_USE_ADC FALSE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(CH_HAL_USE_CAN) || defined(__DOXYGEN__)
#define CH_HAL_USE_CAN FALSE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(CH_HAL_USE_MAC) || defined(__DOXYGEN__)
#define CH_HAL_USE_MAC FALSE
#endif
/*===========================================================================*/
/* PWM driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(CH_HAL_USE_PWM) || defined(__DOXYGEN__)
#define CH_HAL_USE_PWM FALSE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(CH_HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define CH_HAL_USE_SERIAL FALSE
#endif
/*
* Default SERIAL settings overrides (uncomment to override).
*/
/*#define SERIAL_DEFAULT_BITRATE 38400*/
/*#define SERIAL_BUFFERS_SIZE 64*/
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(CH_HAL_USE_SPI) || defined(__DOXYGEN__)
#define CH_HAL_USE_SPI FALSE
#endif
/*
* Default SPI settings overrides (uncomment to override).
*/
/*#define SPI_USE_MUTUAL_EXCLUSION TRUE*/
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(CH_HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define CH_HAL_USE_MMC_SPI FALSE
#endif
/*
* Default MMC_SPI settings overrides (uncomment to override).
*/
/*#define MMC_SECTOR_SIZE 512*/
/*#define MMC_NICE_WAITING TRUE*/
/*#define MMC_POLLING_INTERVAL 10*/
/*#define MMC_POLLING_DELAY 10*/
#endif /* _HALCONF_H_ */
/** @} */

View File

@@ -0,0 +1,53 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#include <string.h>
#include <stdio.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;
halInit();
conInit();
chSysInit();
result = TestThread(&CD1);
if (result)
exit(1);
else
exit(0);
}

View File

@@ -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

393
ChibiOS_2.0.8/test/test.c Normal file
View File

@@ -0,0 +1,393 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @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 const struct testcase **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 * const wa[5] = {test.wa.T0, test.wa.T1, test.wa.T2,
test.wa.T3, test.wa.T4};
/*
* Console output.
*/
static BaseChannel *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)
chIOPut(chp, '0');
else {
p = buf;
while (n)
*p++ = (n % 10) + '0', n /= 10;
while (p > buf)
chIOPut(chp, *--p);
}
}
/**
* @brief Prints a line without final end-of-line.
*
* @param[in] msgp the message
*/
void test_print(char *msgp) {
while (*msgp)
chIOPut(chp, *msgp++);
}
/**
* @brief Prints a line.
*
* @param[in] msgp the message
*/
void test_println(char *msgp) {
test_print(msgp);
chIOPut(chp, '\r');
chIOPut(chp, '\n');
}
/*
* Tokens.
*/
static void clear_tokens(void) {
tokp = tokens_buffer;
}
static void print_tokens(void) {
char *cp = tokens_buffer;
while (cp < tokp)
chIOPut(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 Pends 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.
*/
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;
chSysLock();
chVTSetI(&vt, duration, tmr, NULL);
chSysUnlock();
}
/*
* 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++)
chIOPut(chp, '-');
chIOPut(chp, '\r');
chIOPut(chp, '\n');
}
/**
* @brief Test execution thread function.
*
* @param[in] p pointer to a @p BaseChannel object for test output
*/
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);
#ifdef __GNUC__
test_print("*** GCC Version: ");
test_println(__VERSION__);
#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 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]->gettest());
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;
}
/** @} */

View File

@@ -0,0 +1,92 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @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 @p ./docs/reports.
* - <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 by use in the various demos and/or by users.
* - <b>Various</b>. The miscellaneous code is tested by use in the various
* demos and/or by users.
* - <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 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
* .
*/

167
ChibiOS_2.0.8/test/test.h Normal file
View File

@@ -0,0 +1,167 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/**
* @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) || \
defined(CH_ARCHITECTURE_STM8)
#define THREADS_STACK_SIZE 48
#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 {
char *(*gettest)(void); /**< @brief Test case name get function. */
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(char *msgp);
void test_println(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 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 * const wa[];
extern bool_t test_timer_done;
#endif
#endif /* _TEST_H_ */
/** @} */

View 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

View File

@@ -0,0 +1,778 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
static Mutex mtx1;
#endif
static msg_t thread1(void *p) {
msg_t msg;
(void)p;
do {
chMsgRelease(msg = chMsgWait());
} 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 char *bmk1_gettest(void) {
return "Benchmark, messages #1";
}
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");
}
const struct testcase testbmk1 = {
bmk1_gettest,
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 char *bmk2_gettest(void) {
return "Benchmark, messages #2";
}
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");
}
const struct testcase testbmk2 = {
bmk2_gettest,
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 char *bmk3_gettest(void) {
return "Benchmark, messages #3";
}
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");
}
const struct testcase testbmk3 = {
bmk3_gettest,
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.
*/
static char *bmk4_gettest(void) {
return "Benchmark, context switch";
}
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");
}
const struct testcase testbmk4 = {
bmk4_gettest,
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 char *bmk5_gettest(void) {
return "Benchmark, threads, full cycle";
}
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");
}
const struct testcase testbmk5 = {
bmk5_gettest,
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 char *bmk6_gettest(void) {
return "Benchmark, threads, create only";
}
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");
}
const struct testcase testbmk6 = {
bmk6_gettest,
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 char *bmk7_gettest(void) {
return "Benchmark, mass reschedule, 5 threads";
}
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");
}
const struct testcase testbmk7 = {
bmk7_gettest,
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 char *bmk8_gettest(void) {
return "Benchmark, round robin context switching";
}
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");
}
const struct testcase testbmk8 = {
bmk8_gettest,
NULL,
NULL,
bmk8_execute
};
/**
* @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 char *bmk9_gettest(void) {
return "Benchmark, I/O Queues throughput";
}
static void bmk9_execute(void) {
uint32_t n;
static uint8_t ib[16];
static InputQueue iq;
chIQInit(&iq, ib, sizeof(ib), NULL);
n = 0;
test_wait_tick();
test_start_timer(1000);
do {
chIQPutI(&iq, 0);
chIQPutI(&iq, 1);
chIQPutI(&iq, 2);
chIQPutI(&iq, 3);
(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");
}
const struct testcase testbmk9 = {
bmk9_gettest,
NULL,
NULL,
bmk9_execute
};
/**
* @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 char *bmk10_gettest(void) {
return "Benchmark, virtual timers set/reset";
}
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");
}
const struct testcase testbmk10 = {
bmk10_gettest,
NULL,
NULL,
bmk10_execute
};
/**
* @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 char *bmk11_gettest(void) {
return "Benchmark, semaphores wait/signal";
}
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");
}
const struct testcase testbmk11 = {
bmk11_gettest,
bmk11_setup,
NULL,
bmk11_execute
};
#if CH_USE_MUTEXES
/**
* @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 char *bmk12_gettest(void) {
return "Benchmark, mutexes lock/unlock";
}
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");
}
const struct testcase testbmk12 = {
bmk12_gettest,
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 char *bmk13_gettest(void) {
return "Benchmark, RAM footprint";
}
static void bmk13_execute(void) {
test_print("--- System: ");
test_printn(sizeof(ReadyList) + sizeof(VTList) + IDLE_THREAD_STACK_SIZE +
(sizeof(Thread) + sizeof(struct intctx) + sizeof(struct extctx) +
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");
test_print("--- Semaph: ");
test_printn(sizeof(Semaphore));
test_println(" bytes");
#if CH_USE_EVENTS
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
test_print("--- Mutex : ");
test_printn(sizeof(Mutex));
test_println(" bytes");
#endif
#if CH_USE_CONDVARS
test_print("--- CondV.: ");
test_printn(sizeof(CondVar));
test_println(" bytes");
#endif
#if CH_USE_QUEUES
test_print("--- Queue : ");
test_printn(sizeof(GenericQueue));
test_println(" bytes");
#endif
#if CH_USE_MAILBOXES
test_print("--- MailB.: ");
test_printn(sizeof(Mailbox));
test_println(" bytes");
#endif
}
const struct testcase testbmk13 = {
bmk13_gettest,
NULL,
NULL,
bmk13_execute
};
/**
* @brief Test sequence for benchmarks.
*/
const struct testcase * const patternbmk[] = {
#if !TEST_NO_BENCHMARKS
&testbmk1,
&testbmk2,
&testbmk3,
&testbmk4,
&testbmk5,
&testbmk6,
&testbmk7,
&testbmk8,
&testbmk9,
&testbmk10,
&testbmk11,
#if CH_USE_MUTEXES
&testbmk12,
#endif
&testbmk13,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTBMK_H_
#define _TESTBMK_H_
extern const struct testcase *patternbmk[];
#endif /* _TESTBMK_H_ */

View File

@@ -0,0 +1,287 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#if CH_USE_HEAP
static MemoryHeap heap1;
#endif
#if CH_USE_MEMPOOLS
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
static char *dyn1_gettest(void) {
return "Dynamic APIs, threads creation from heap";
}
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");
}
const struct testcase testdyn1 = {
dyn1_gettest,
dyn1_setup,
NULL,
dyn1_execute
};
#endif /* CH_USE_HEAP */
#if CH_USE_MEMPOOLS
/**
* @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 char *dyn2_gettest(void) {
return "Dynamic APIs, threads creation from memory pool";
}
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");
}
const struct testcase testdyn2 = {
dyn2_gettest,
dyn2_setup,
NULL,
dyn2_execute
};
#endif /* CH_USE_MEMPOOLS */
#if CH_USE_HEAP && CH_USE_REGISTRY
/**
* @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 char *dyn3_gettest(void) {
return "Dynamic APIs, registry and references";
}
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");
}
const struct testcase testdyn3 = {
dyn3_gettest,
dyn3_setup,
NULL,
dyn3_execute
};
#endif /* CH_USE_HEAP && CH_USE_REGISTRY */
#endif /* CH_USE_DYNAMIC */
/**
* @brief Test sequence for dynamic APIs.
*/
const struct testcase * const patterndyn[] = {
#if CH_USE_DYNAMIC
#if CH_USE_HEAP
&testdyn1,
#endif
#if CH_USE_MEMPOOLS
&testdyn2,
#endif
#if CH_USE_HEAP && CH_USE_REGISTRY
&testdyn3,
#endif
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTDYN_H_
#define _TESTDYN_H_
extern const struct testcase *patterndyn[];
#endif /* _TESTDYN_H_ */

View File

@@ -0,0 +1,319 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#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 char *evt1_gettest(void) {
return "Events, registration and dispatch";
}
static void evt1_setup(void) {
chEvtClear(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 const 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, chEvtIsListening(&es1), "no listener");
chEvtUnregister(&es1, &el1);
test_assert(2, chEvtIsListening(&es1), "no listener");
chEvtUnregister(&es1, &el2);
test_assert(3, !chEvtIsListening(&es1), "stuck listener");
/*
* Testing chEvtDispatch().
*/
chEvtDispatch(evhndl, 7);
test_assert_sequence(4, "ABC");
}
const struct testcase testevt1 = {
evt1_gettest,
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 char *evt2_gettest(void) {
return "Events, wait and broadcast";
}
static void evt2_setup(void) {
chEvtClear(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.
*/
chEvtPend(5);
m = chEvtWaitOne(ALL_EVENTS);
test_assert(1, m == 1, "single event error");
m = chEvtWaitOne(ALL_EVENTS);
test_assert(2, m == 4, "single event error");
m = chEvtClear(ALL_EVENTS);
test_assert(3, 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(4, target_time, target_time + ALLOWED_DELAY);
test_assert(5, m == 1, "single event error");
m = chEvtClear(ALL_EVENTS);
test_assert(6, m == 0, "stuck event");
test_wait_threads();
/*
* Test on chEvtWaitAny() without wait.
*/
chEvtPend(5);
m = chEvtWaitAny(ALL_EVENTS);
test_assert(7, m == 5, "unexpected pending bit");
m = chEvtClear(ALL_EVENTS);
test_assert(8, 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(9, target_time, target_time + ALLOWED_DELAY);
test_assert(10, m == 1, "single event error");
m = chEvtClear(ALL_EVENTS);
test_assert(11, 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(12, target_time, target_time + ALLOWED_DELAY);
m = chEvtClear(ALL_EVENTS);
test_assert(13, m == 0, "stuck event");
test_wait_threads();
chEvtUnregister(&es1, &el1);
chEvtUnregister(&es2, &el2);
test_assert(14, !chEvtIsListening(&es1), "stuck listener");
test_assert(15, !chEvtIsListening(&es2), "stuck listener");
}
const struct testcase testevt2 = {
evt2_gettest,
evt2_setup,
NULL,
evt2_execute
};
#if CH_USE_EVENTS_TIMEOUT
/**
* @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 char *evt3_gettest(void) {
return "Events, timeouts";
}
static void evt3_setup(void) {
chEvtClear(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");
}
const struct testcase testevt3 = {
evt3_gettest,
evt3_setup,
NULL,
evt3_execute
};
#endif /* CH_USE_EVENTS_TIMEOUT */
/**
* @brief Test sequence for events.
*/
const struct testcase * const patternevt[] = {
#if CH_USE_EVENTS
&testevt1,
&testevt2,
#if CH_USE_EVENTS_TIMEOUT
&testevt3,
#endif
#endif
NULL
};
#endif /* CH_USE_EVENTS */

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTEVT_H_
#define _TESTEVT_H_
extern const struct testcase *patternevt[];
#endif /* _TESTEVT_H_ */

View File

@@ -0,0 +1,174 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#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 char *heap1_gettest(void) {
return "Heap, allocation and fragmentation test";
}
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");
}
const struct testcase testheap1 = {
heap1_gettest,
heap1_setup,
NULL,
heap1_execute
};
#endif /* CH_USE_HEAP.*/
/**
* @brief Test sequence for heap.
*/
const struct testcase * const patternheap[] = {
#if CH_USE_HEAP
&testheap1,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTHEAP_H_
#define _TESTHEAP_H_
extern const struct testcase *patternheap[];
#endif /* _TESTHEAP_H_ */

View File

@@ -0,0 +1,187 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#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 char *mbox1_gettest(void) {
return "Mailboxes, queuing and timeouts";
}
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, chMBGetEmpty(&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");
/*
* Testing final conditions.
*/
test_assert(5, chMBGetEmpty(&mb1) == 0, "still empty");
test_assert(6, chMBGetFull(&mb1) == MB_SIZE, "not full");
test_assert(7, 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(8, msg1 == RDY_OK, "wrong wake-up message");
test_emit_token(msg2);
}
test_assert_sequence(9, "ABCDE");
/*
* Testing buffer circularity.
*/
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
test_assert(10, msg1 == RDY_OK, "wrong wake-up message");
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
test_assert(11, msg1 == RDY_OK, "wrong wake-up message");
test_assert(12, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base");
test_assert(13, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base");
/*
* Testing fetch timeout.
*/
msg1 = chMBFetch(&mb1, &msg2, 1);
test_assert(14, msg1 == RDY_TIMEOUT, "wrong wake-up message");
/*
* Testing final conditions.
*/
test_assert(15, chMBGetEmpty(&mb1) == MB_SIZE, "not empty");
test_assert(16, chMBGetFull(&mb1) == 0, "still full");
test_assert(17, mb1.mb_rdptr == mb1.mb_wrptr, "pointers not aligned");
/*
* Testing reset.
*/
chMBReset(&mb1);
/*
* Re-testing final conditions.
*/
test_assert(18, chMBGetEmpty(&mb1) == MB_SIZE, "not empty");
test_assert(19, chMBGetFull(&mb1) == 0, "still full");
test_assert(20, mb1.mb_buffer == mb1.mb_wrptr, "write pointer not aligned to base");
test_assert(21, mb1.mb_buffer == mb1.mb_rdptr, "read pointer not aligned to base");
}
const struct testcase testmbox1 = {
mbox1_gettest,
mbox1_setup,
NULL,
mbox1_execute
};
#endif /* CH_USE_MAILBOXES */
/**
* @brief Test sequence for mailboxes.
*/
const struct testcase * const patternmbox[] = {
#if CH_USE_MAILBOXES
&testmbox1,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTMBOX_H_
#define _TESTMBOX_H_
extern const struct testcase *patternmbox[];
#endif /* _TESTMBOX_H_ */

View File

@@ -0,0 +1,133 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
/**
* @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 char *msg1_gettest(void) {
return "Messages, loop";
}
static msg_t thread(void *p) {
chMsgSend(p, 'A');
chMsgSend(p, 'B');
chMsgSend(p, 'C');
chMsgSend(p, 'D');
return 0;
}
static void msg1_execute(void) {
msg_t msg;
/*
* Testing the whole messages loop.
*/
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() + 1,
thread, chThdSelf());
chMsgRelease(msg = chMsgWait());
test_emit_token(msg);
chMsgRelease(msg = chMsgWait());
test_emit_token(msg);
chMsgRelease(msg = chMsgWait());
test_emit_token(msg);
test_assert_sequence(1, "ABC");
/*
* Testing message fetch using chMsgGet().
* Note, the following is valid because the sender has higher priority than
* the receiver.
*/
msg = chMsgGet();
test_assert(1, msg != 0, "no message");
chMsgRelease(0);
test_assert(2, msg == 'D', "wrong message");
/*
* Must not have pending messages.
*/
msg = chMsgGet();
test_assert(3, msg == 0, "unknown message");
}
const struct testcase testmsg1 = {
msg1_gettest,
NULL,
NULL,
msg1_execute
};
#endif /* CH_USE_MESSAGES */
/**
* @brief Test sequence for messages.
*/
const struct testcase * const patternmsg[] = {
#if CH_USE_MESSAGES
&testmsg1,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTMSG_H_
#define _TESTMSG_H_
extern const struct testcase *patternmsg[];
#endif /* _TESTMSG_H_ */

View File

@@ -0,0 +1,674 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#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
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 char *mtx1_gettest(void) {
return "Mutexes, priority enqueuing test";
}
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");
}
const struct testcase testmtx1 = {
mtx1_gettest,
mtx1_setup,
NULL,
mtx1_execute
};
#if CH_DBG_THREADS_PROFILING
/**
* @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 char *mtx2_gettest(void) {
return "Mutexes, priority inheritance, simple case";
}
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);
}
const struct testcase testmtx2 = {
mtx2_gettest,
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 char *mtx3_gettest(void) {
return "Mutexes, priority inheritance, complex case";
}
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);
}
const struct testcase testmtx3 = {
mtx3_gettest,
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 char *mtx4_gettest(void) {
return "Mutexes, priority return";
}
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();
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();
}
const struct testcase testmtx4 = {
mtx4_gettest,
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 char *mtx5_gettest(void) {
return "Mutexes, status";
}
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");
}
const struct testcase testmtx5 = {
mtx5_gettest,
mtx5_setup,
NULL,
mtx5_execute
};
#if CH_USE_CONDVARS
/**
* @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 char *mtx6_gettest(void) {
return "CondVar, signal test";
}
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");
}
const struct testcase testmtx6 = {
mtx6_gettest,
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 char *mtx7_gettest(void) {
return "CondVar, broadcast test";
}
static void mtx7_setup(void) {
chCondInit(&c1);
chMtxInit(&m1);
}
static void mtx7_execute(void) {
// Bacause priority inheritance.
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");
}
const struct testcase testmtx7 = {
mtx7_gettest,
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 char *mtx8_gettest(void) {
return "CondVar, boost test";
}
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
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");
}
const struct testcase testmtx8 = {
mtx8_gettest,
mtx8_setup,
NULL,
mtx8_execute
};
#endif /* CH_USE_CONDVARS */
#endif /* CH_USE_MUTEXES */
/**
* @brief Test sequence for mutexes.
*/
const struct testcase * const patternmtx[] = {
#if CH_USE_MUTEXES
&testmtx1,
#if CH_DBG_THREADS_PROFILING
&testmtx2,
&testmtx3,
#endif
&testmtx4,
&testmtx5,
#if CH_USE_CONDVARS
&testmtx6,
&testmtx7,
&testmtx8,
#endif
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTMTX_H_
#define _TESTMTX_H_
extern const struct testcase *patternmtx[];
#endif /* _TESTMTX_H_ */

View File

@@ -0,0 +1,122 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
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 char *pools1_gettest(void) {
return "Memory Pools, queue/dequeue";
}
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. */
for (i = 0; i < MAX_THREADS; i++)
chPoolFree(&mp1, wa[i]);
/* Empting the pool again. */
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");
/* Covering the case where a provider is unable to return more memory.*/
chPoolInit(&mp1, 16, null_provider);
test_assert(3, chPoolAlloc(&mp1) == NULL, "provider returned memory");
}
const struct testcase testpools1 = {
pools1_gettest,
pools1_setup,
NULL,
pools1_execute
};
#endif /* CH_USE_MEMPOOLS */
/*
* @brief Test sequence for pools.
*/
const struct testcase * const patternpools[] = {
#if CH_USE_MEMPOOLS
&testpools1,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTPOOLS_H_
#define _TESTPOOLS_H_
extern const struct testcase *patternpools[];
#endif /* _TESTPOOLS_H_ */

View File

@@ -0,0 +1,225 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
#define TEST_QUEUES_SIZE 4
static void notify(void) {}
/*
* 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);
static OUTPUTQUEUE_DECL(oq, test.wa.T1, TEST_QUEUES_SIZE, notify);
/**
* @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 char *queues1_gettest(void) {
return "Queues, input queues";
}
static void queues1_setup(void) {
chIQInit(&iq, wa[0], TEST_QUEUES_SIZE, notify);
}
static void queues1_execute(void) {
unsigned i;
size_t n;
/* Initial empty state */
test_assert(1, chIQIsEmpty(&iq), "not empty");
/* Queue filling */
for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i);
test_assert(2, chIQIsFull(&iq), "still has space");
test_assert(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(4, chIQIsEmpty(&iq), "still full");
test_assert_sequence(5, "ABCD");
/* Queue filling again */
for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i);
/* 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(7, chIQIsEmpty(&iq), "still full");
/* Queue filling again */
for (i = 0; i < TEST_QUEUES_SIZE; i++)
chIQPutI(&iq, 'A' + i);
/* 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(10, chIQIsEmpty(&iq), "still full");
/* Testing reset */
chIQPutI(&iq, 0);
chIQResetI(&iq);
test_assert(11, chIQIsEmpty(&iq), "still full");
/* Timeout */
test_assert(12, chIQGetTimeout(&iq, 10) == Q_TIMEOUT, "wrong timeout return");
}
const struct testcase testqueues1 = {
queues1_gettest,
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 char *queues2_gettest(void) {
return "Queues, output queues";
}
static void queues2_setup(void) {
chOQInit(&oq, wa[0], TEST_QUEUES_SIZE, notify);
}
static void queues2_execute(void) {
unsigned i;
size_t n;
/* Initial empty state */
test_assert(1, chOQIsEmpty(&oq), "not empty");
/* Queue filling */
for (i = 0; i < TEST_QUEUES_SIZE; i++)
chOQPut(&oq, 'A' + i);
test_assert(2, chOQIsFull(&oq), "still has space");
/* Queue emptying */
for (i = 0; i < TEST_QUEUES_SIZE; i++)
test_emit_token(chOQGetI(&oq));
test_assert(3, chOQIsEmpty(&oq), "still full");
test_assert_sequence(4, "ABCD");
test_assert(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(7, chOQIsFull(&oq), "not full");
/* Testing reset */
chOQResetI(&oq);
test_assert(8, chOQIsEmpty(&oq), "still full");
/* Partial writes */
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(9, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
test_assert(10, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
test_assert(11, chOQIsFull(&oq), "not full");
/* Timeout */
test_assert(12, chOQPutTimeout(&oq, 0, 10) == Q_TIMEOUT, "wrong timeout return");
}
const struct testcase testqueues2 = {
queues2_gettest,
queues2_setup,
NULL,
queues2_execute
};
#endif /* CH_USE_QUEUES */
/**
* @brief Test sequence for queues.
*/
const struct testcase * const patternqueues[] = {
#if CH_USE_QUEUES
&testqueues1,
&testqueues2,
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTQUEUES_H_
#define _TESTQUEUES_H_
extern const struct testcase *patternqueues[];
#endif /* _TESTQUEUES_H_ */

View File

@@ -0,0 +1,266 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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
* .
* @file testsem.c
* @brief Semaphores test source file
* @file testsem.h
* @brief Semaphores test header file
*/
#if CH_USE_SEMAPHORES
#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 char *sem1_gettest(void) {
return "Semaphores, enqueuing";
}
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
}
/**
* @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.
*/
const struct testcase testsem1 = {
sem1_gettest,
sem1_setup,
NULL,
sem1_execute
};
static char *sem2_gettest(void) {
return "Semaphores, timeout";
}
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);
}
const struct testcase testsem2 = {
sem2_gettest,
sem2_setup,
NULL,
sem2_execute
};
#if CH_USE_SEMSW
/**
* @page test_sem_003 Atomic signal-wait test
*
* <h2>Description</h2>
* This test case explicitly address 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 char *sem3_gettest(void) {
return "Semaphores, atomic signal-wait";
}
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");
}
const struct testcase testsem3 = {
sem3_gettest,
sem3_setup,
NULL,
sem3_execute
};
#endif /* CH_USE_SEMSW */
#endif /* CH_USE_SEMAPHORES */
/**
* @brief Test sequence for semaphores.
*/
const struct testcase * const patternsem[] = {
#if CH_USE_SEMAPHORES
&testsem1,
&testsem2,
#if CH_USE_SEMSW
&testsem3,
#endif
#endif
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTSEM_H_
#define _TESTSEM_H_
extern const struct testcase *patternsem[];
#endif /* _TESTSEM_H_ */

View File

@@ -0,0 +1,257 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#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 char *thd1_gettest(void) {
return "Threads, enqueuing test #1";
}
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");
}
const struct testcase testthd1 = {
thd1_gettest,
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 char *thd2_gettest(void) {
return "Threads, enqueuing test #2";
}
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");
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread, "C");
test_wait_threads();
test_assert_sequence(1, "ABCDE");
}
const struct testcase testthd2 = {
thd2_gettest,
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 char *thd3_gettest(void) {
return "Threads, priority change";
}
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
/* 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
}
const struct testcase testthd3 = {
thd3_gettest,
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 char *thd4_gettest(void) {
return "Threads, delays";
}
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);
}
const struct testcase testthd4 = {
thd4_gettest,
NULL,
NULL,
thd4_execute
};
/**
* @brief Test sequence for threads.
*/
const struct testcase * const patternthd[] = {
&testthd1,
&testthd2,
&testthd3,
&testthd4,
NULL
};

View File

@@ -0,0 +1,32 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _TESTRDY_H_
#define _TESTRDY_H_
extern const struct testcase *patternthd[];
#endif /* _TESTRDY_H_ */