2186 lines
80 KiB
XML
2186 lines
80 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<SPC5-Config version="1.0.0">
|
|
<application name="ChibiOS/NIL Test Suite" version="1.0.0" standalone="true" locked="false">
|
|
<description>Test Specification for ChibiOS/NIL.</description>
|
|
<component id="org.chibios.spc5.components.portable.generic_startup">
|
|
<component id="org.chibios.spc5.components.portable.chibios_unitary_tests_engine" />
|
|
</component>
|
|
<instances>
|
|
<instance locked="false" id="org.chibios.spc5.components.portable.generic_startup" />
|
|
<instance locked="false" id="org.chibios.spc5.components.portable.chibios_unitary_tests_engine">
|
|
<description>
|
|
<brief>
|
|
<value>ChibiOS/NIL Test Suite.</value>
|
|
</brief>
|
|
<copyright>
|
|
<value><![CDATA[/*
|
|
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/]]></value>
|
|
</copyright>
|
|
<introduction>
|
|
<value>Test suite for ChibiOS/NIL. The purpose of this suite is to perform unit tests on the NIL modules and to converge to 100% code coverage through successive improvements.</value>
|
|
</introduction>
|
|
</description>
|
|
<global_data_and_code>
|
|
<code_prefix>
|
|
<value>nil_</value>
|
|
</code_prefix>
|
|
<global_definitions>
|
|
<value><![CDATA[#define TEST_SUITE_NAME "ChibiOS/NIL Test Suite"
|
|
|
|
/*
|
|
* Allowed delay in timeout checks.
|
|
*/
|
|
#define ALLOWED_DELAY TIME_MS2I(2)
|
|
|
|
extern THD_WORKING_AREA(wa_common, 128);
|
|
systime_t test_wait_tick(void);]]></value>
|
|
</global_definitions>
|
|
<global_code>
|
|
<value><![CDATA[THD_WORKING_AREA(wa_common, 128);
|
|
|
|
/*
|
|
* Delays execution until next system time tick.
|
|
*/
|
|
systime_t test_wait_tick(void) {
|
|
|
|
chThdSleep(1);
|
|
return chVTGetSystemTimeX();
|
|
}]]></value>
|
|
</global_code>
|
|
</global_data_and_code>
|
|
<sequences>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Information.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This sequence reports configuration and version information about the NIL kernel.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[#include "ch.h"]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Port Info.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Port-related info are reported.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Prints the version string.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[#if defined(PORT_ARCHITECTURE_NAME)
|
|
test_print("--- Architecture: ");
|
|
test_println(PORT_ARCHITECTURE_NAME);
|
|
#endif
|
|
#if defined(PORT_CORE_VARIANT_NAME)
|
|
test_print("--- Core Variant: ");
|
|
test_println(PORT_CORE_VARIANT_NAME);
|
|
#endif
|
|
#if defined(PORT_COMPILER_NAME)
|
|
test_print("--- Compiler: ");
|
|
test_println(PORT_COMPILER_NAME);
|
|
#endif
|
|
#if defined(PORT_INFO)
|
|
test_print("--- Port Info: ");
|
|
test_println(PORT_INFO);
|
|
#endif
|
|
#if defined(PORT_NATURAL_ALIGN)
|
|
test_print("--- Natural alignment: ");
|
|
test_printn(PORT_NATURAL_ALIGN);
|
|
test_println("");
|
|
#endif
|
|
#if defined(PORT_STACK_ALIGN)
|
|
test_print("--- Stack alignment: ");
|
|
test_printn(PORT_STACK_ALIGN);
|
|
test_println("");
|
|
#endif
|
|
#if defined(PORT_WORKING_AREA_ALIGN)
|
|
test_print("--- Working area alignment: ");
|
|
test_printn(PORT_WORKING_AREA_ALIGN);
|
|
test_println("");
|
|
#endif]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Kernel Info.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The version numbers are reported.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Prints the version string.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_println("--- Product: ChibiOS/NIL");
|
|
test_print("--- Stable Flag: ");
|
|
test_printn(CH_KERNEL_STABLE);
|
|
test_println("");
|
|
test_print("--- Version String: ");
|
|
test_println(CH_KERNEL_VERSION);
|
|
test_print("--- Major Number: ");
|
|
test_printn(CH_KERNEL_MAJOR);
|
|
test_println("");
|
|
test_print("--- Minor Number: ");
|
|
test_printn(CH_KERNEL_MINOR);
|
|
test_println("");
|
|
test_print("--- Patch Number: ");
|
|
test_printn(CH_KERNEL_PATCH);
|
|
test_println("");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Kernel Settings.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The static kernel settings are reported.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Prints the configuration options settings.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- CH_CFG_MAX_THREADS: ");
|
|
test_printn(CH_CFG_MAX_THREADS);
|
|
test_println("");
|
|
test_print("--- CH_CFG_AUTOSTART_THREADS: ");
|
|
test_printn(CH_CFG_AUTOSTART_THREADS);
|
|
test_println("");
|
|
test_print("--- CH_CFG_ST_RESOLUTION: ");
|
|
test_printn(CH_CFG_ST_RESOLUTION);
|
|
test_println("");
|
|
test_print("--- CH_CFG_ST_FREQUENCY: ");
|
|
test_printn(CH_CFG_ST_FREQUENCY);
|
|
test_println("");
|
|
test_print("--- CH_CFG_ST_TIMEDELTA: ");
|
|
test_printn(CH_CFG_ST_TIMEDELTA);
|
|
test_println("");
|
|
test_print("--- CH_CFG_USE_WAITEXIT: ");
|
|
test_printn(CH_CFG_USE_WAITEXIT);
|
|
test_println("");
|
|
test_print("--- CH_CFG_USE_SEMAPHORES: ");
|
|
test_printn(CH_CFG_USE_SEMAPHORES);
|
|
test_println("");
|
|
test_print("--- CH_CFG_USE_MUTEXES: ");
|
|
test_printn(CH_CFG_USE_MUTEXES);
|
|
test_println("");
|
|
test_print("--- CH_CFG_USE_EVENTS: ");
|
|
test_printn(CH_CFG_USE_EVENTS);
|
|
test_println("");
|
|
test_print("--- CH_CFG_USE_MESSAGES: ");
|
|
test_printn(CH_CFG_USE_MESSAGES);
|
|
test_println("");
|
|
test_print("--- CH_DBG_STATISTICS: ");
|
|
test_printn(CH_DBG_STATISTICS);
|
|
test_println("");
|
|
test_print("--- CH_DBG_SYSTEM_STATE_CHECK: ");
|
|
test_printn(CH_DBG_SYSTEM_STATE_CHECK);
|
|
test_println("");
|
|
test_print("--- CH_DBG_ENABLE_CHECKS: ");
|
|
test_printn(CH_DBG_ENABLE_CHECKS);
|
|
test_println("");
|
|
test_print("--- CH_DBG_ENABLE_ASSERTS: ");
|
|
test_printn(CH_DBG_ENABLE_ASSERTS);
|
|
test_println("");
|
|
test_print("--- CH_DBG_ENABLE_STACK_CHECK: ");
|
|
test_printn(CH_DBG_ENABLE_STACK_CHECK);
|
|
test_println("");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Time and Intervals Functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This sequence tests the ChibiOS/NIL functionalities related to time and intervals management.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[#include "ch.h"]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>System Tick Counter functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The functionality of the API @p chVTGetSystemTimeX() is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>A System Tick Counter increment is expected, the test simply hangs if it does not happen.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[systime_t time = chVTGetSystemTimeX();
|
|
while (time == chVTGetSystemTimeX()) {
|
|
}]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Time ranges functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The functionality of the API @p chTimeIsInRangeX() is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Checking case where start == end, it must always evaluate as not in range.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
bool b;
|
|
|
|
b = chTimeIsInRangeX((systime_t)0, (systime_t)0, (systime_t)0);
|
|
test_assert(b == false, "in range");
|
|
b = chTimeIsInRangeX((systime_t)-1, (systime_t)0, (systime_t)0);
|
|
test_assert(b == false, "in range");
|
|
b = chTimeIsInRangeX((systime_t)0, (systime_t)-1, (systime_t)-1);
|
|
test_assert(b == false, "in range");
|
|
b = chTimeIsInRangeX((systime_t)-1, (systime_t)-1, (systime_t)-1);
|
|
test_assert(b == false, "in range");
|
|
]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Checking boundaries for start < end.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
bool b;
|
|
|
|
b = chTimeIsInRangeX((systime_t)10, (systime_t)10, (systime_t)100);
|
|
test_assert(b == true, "not in range");
|
|
b = chTimeIsInRangeX((systime_t)9, (systime_t)10, (systime_t)100);
|
|
test_assert(b == false, "in range");
|
|
b = chTimeIsInRangeX((systime_t)99, (systime_t)10, (systime_t)100);
|
|
test_assert(b == true, "not in range");
|
|
b = chTimeIsInRangeX((systime_t)100, (systime_t)10, (systime_t)100);
|
|
test_assert(b == false, "in range");
|
|
]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Checking boundaries for start > end.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
bool b;
|
|
|
|
b = chTimeIsInRangeX((systime_t)100, (systime_t)100, (systime_t)10);
|
|
test_assert(b == true, "not in range");
|
|
b = chTimeIsInRangeX((systime_t)99, (systime_t)100, (systime_t)10);
|
|
test_assert(b == false, "in range");
|
|
b = chTimeIsInRangeX((systime_t)9, (systime_t)100, (systime_t)10);
|
|
test_assert(b == true, "not in range");
|
|
b = chTimeIsInRangeX((systime_t)10, (systime_t)100, (systime_t)10);
|
|
test_assert(b == false, "in range");
|
|
]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Threads Functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This sequence tests the ChibiOS/NIL functionalities related to threading.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[#include "ch.h"]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Thread Sleep functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The functionality of @p chThdSleep() and derivatives is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[systime_t time;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The current system time is read then a sleep is performed for 100 system ticks and on exit the system time is verified again.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
chThdSleep(100);
|
|
test_assert_time_window(chTimeAddX(time, 100),
|
|
chTimeAddX(time, 100 + 1),
|
|
"out of time window");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The current system time is read then a sleep is performed for 100000 microseconds and on exit the system time is verified again.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
chThdSleepMicroseconds(100000);
|
|
test_assert_time_window(chTimeAddX(time, TIME_US2I(100000)),
|
|
chTimeAddX(time, TIME_US2I(100000) + 1),
|
|
"out of time window");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The current system time is read then a sleep is performed for 100 milliseconds and on exit the system time is verified again.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
chThdSleepMilliseconds(100);
|
|
test_assert_time_window(chTimeAddX(time, TIME_MS2I(100)),
|
|
chTimeAddX(time, TIME_MS2I(100) + 1),
|
|
"out of time window");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The current system time is read then a sleep is performed for 1 second and on exit the system time is verified again.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
chThdSleepSeconds(1);
|
|
test_assert_time_window(chTimeAddX(time, TIME_S2I(1)),
|
|
chTimeAddX(time, TIME_S2I(1) + 1),
|
|
"out of time window");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Function chThdSleepUntil() is tested with a timeline of "now" + 100 ticks.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
chThdSleepUntil(chTimeAddX(time, 100));
|
|
test_assert_time_window(chTimeAddX(time, 100),
|
|
chTimeAddX(time, 100 + 1),
|
|
"out of time window");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Semaphores.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This sequence tests the ChibiOS/NIL functionalities related to counter semaphores.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_SEMAPHORES</value>
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[#include "ch.h"
|
|
|
|
static thread_t *tp1;
|
|
static bool terminate;
|
|
static semaphore_t sem1, sem2;
|
|
|
|
/*
|
|
* Signaler thread.
|
|
*/
|
|
static THD_FUNCTION(signaler, arg) {
|
|
|
|
(void)arg;
|
|
|
|
/* Initializing global resources.*/
|
|
terminate = false;
|
|
chSemObjectInit(&sem1, 0);
|
|
chSemObjectInit(&sem2, 0);
|
|
|
|
while (!terminate) {
|
|
chSysLock();
|
|
if (chSemGetCounterI(&sem1) < 0)
|
|
chSemSignalI(&sem1);
|
|
chSemResetI(&sem2, 0);
|
|
chSchRescheduleS();
|
|
chSysUnlock();
|
|
|
|
chThdSleepMilliseconds(250);
|
|
}
|
|
}]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Semaphore primitives, no state change.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Wait, Signal and Reset primitives are tested. The testing thread does not trigger a state change.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chSemObjectInit(&sem1, 1);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value><![CDATA[chSemReset(&sem1, 0);]]></value>
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemWait() is invoked, after return the counter and the returned message are tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[msg_t msg;
|
|
|
|
msg = chSemWait(&sem1);
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
|
|
test_assert(MSG_OK == msg, "wrong returned message");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemSignal() is invoked, after return the counter is tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chSemSignal(&sem1);
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemReset() is invoked, after return the counter is tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chSemReset(&sem1, 2);
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Semaphore primitives, with state change.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Wait, Signal and Reset primitives are tested. The testing thread triggers a state change.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[thread_descriptor_t td = {
|
|
.name = "signaler",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = signaler,
|
|
.arg = NULL
|
|
};
|
|
tp1 = chThdCreate(&td);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value><![CDATA[terminate = true;
|
|
chThdWait(tp1);]]></value>
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemWait() is invoked, after return the counter and the returned message are tested. The semaphore is signaled by another thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[msg_t msg;
|
|
|
|
msg = chSemWait(&sem1);
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
|
|
test_assert(MSG_OK == msg, "wrong returned message");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemWait() is invoked, after return the counter and the returned message are tested. The semaphore is reset by another thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[msg_t msg;
|
|
|
|
msg = chSemWait(&sem2);
|
|
test_assert_lock(chSemGetCounterI(&sem2) == 0,"wrong counter value");
|
|
test_assert(MSG_RESET == msg, "wrong returned message");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Semaphores timeout.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Timeout on semaphores is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chSemObjectInit(&sem1, 0);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value><![CDATA[chSemReset(&sem1, 0);]]></value>
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[systime_t time;
|
|
msg_t msg;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemWaitTimeout() is invoked a first time, after return the system time, the counter and the returned message are tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
msg = chSemWaitTimeout(&sem1, TIME_MS2I(1000));
|
|
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
|
|
chTimeAddX(time, TIME_MS2I(1000) + 1),
|
|
"out of time window");
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
|
|
test_assert(MSG_TIMEOUT == msg, "wrong timeout message");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The function chSemWaitTimeout() is invoked again, after return the system time, the counter and the returned message are tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[time = chVTGetSystemTimeX();
|
|
msg = chSemWaitTimeout(&sem1, TIME_MS2I(1000));
|
|
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
|
|
chTimeAddX(time, TIME_MS2I(1000) + 1),
|
|
"out of time window");
|
|
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
|
|
test_assert(MSG_TIMEOUT == msg, "wrong timeout message");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Suspend/Resume.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This sequence tests the ChibiOS/NIL functionalities related to threads suspend/resume.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[static thread_t *tp1;
|
|
static bool terminate;
|
|
static thread_reference_t tr1;
|
|
|
|
/*
|
|
* Resumer thread.
|
|
*/
|
|
static THD_FUNCTION(resumer, arg) {
|
|
|
|
(void)arg;
|
|
|
|
/* Initializing global resources.*/
|
|
terminate = false;
|
|
tr1 = NULL;
|
|
|
|
while (!terminate) {
|
|
chThdResume(&tr1, MSG_OK);
|
|
chThdSleepMilliseconds(250);
|
|
}
|
|
}]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Suspend and Resume functionality.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The functionality of chThdSuspendTimeoutS() and chThdResumeI() is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[thread_descriptor_t td = {
|
|
.name = "resumer",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = resumer,
|
|
.arg = NULL
|
|
};
|
|
tp1 = chThdCreate(&td);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value><![CDATA[terminate = true;
|
|
chThdWait(tp1);]]></value>
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[systime_t time;
|
|
msg_t msg;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The function chThdSuspendTimeoutS() is invoked, the thread is remotely resumed with message @p MSG_OK. On return the message and the state of the reference are tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chSysLock();
|
|
msg = chThdSuspendTimeoutS(&tr1, TIME_INFINITE);
|
|
chSysUnlock();
|
|
test_assert(NULL == tr1, "not NULL");
|
|
test_assert(MSG_OK == msg,"wrong returned message");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The function chThdSuspendTimeoutS() is invoked, the thread is not resumed so a timeout must occur. On return the message and the state of the reference are tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[thread_reference_t tr = NULL;
|
|
|
|
chSysLock();
|
|
time = chVTGetSystemTimeX();
|
|
msg = chThdSuspendTimeoutS(&tr, TIME_MS2I(1000));
|
|
chSysUnlock();
|
|
test_assert_time_window(chTimeAddX(time, TIME_MS2I(1000)),
|
|
chTimeAddX(time, TIME_MS2I(1000) + 1),
|
|
"out of time window");
|
|
test_assert(NULL == tr, "not NULL");
|
|
test_assert(MSG_TIMEOUT == msg, "wrong returned message");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Event Sources and Event Flags.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This module implements the test sequence for the Events subsystem.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_EVENTS</value>
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[static EVENTSOURCE_DECL(es1);
|
|
static EVENTSOURCE_DECL(es2);
|
|
|
|
static void h1(eventid_t id) {(void)id;test_emit_token('A');}
|
|
static void h2(eventid_t id) {(void)id;test_emit_token('B');}
|
|
static void h3(eventid_t id) {(void)id;test_emit_token('C');}
|
|
static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
|
|
|
|
/*
|
|
* Direct events thread.
|
|
*/
|
|
static THD_FUNCTION(evtthd1, p) {
|
|
|
|
chThdSleepMilliseconds(50);
|
|
chEvtSignal((thread_t *)p, 1);
|
|
}
|
|
|
|
/*
|
|
* Broadcaster thread.
|
|
*/
|
|
static THD_FUNCTION(evtthd2, p) {
|
|
|
|
(void)p;
|
|
chEvtBroadcast(&es1);
|
|
chThdSleepMilliseconds(50);
|
|
chEvtBroadcast(&es2);
|
|
}]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Events registration.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[event_listener_t el1, el2;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>An Event Source is initialized.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtObjectInit(&es1);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Two Event Listeners are registered on the Event Source, the Event Source is tested to have listeners.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtRegisterMask(&es1, &el1, 1);
|
|
chEvtRegisterMask(&es1, &el2, 2);
|
|
test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>An Event Listener is unregistered, the Event Source must still have listeners.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtUnregister(&es1, &el1);
|
|
test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>An Event Listener is unregistered, the Event Source must not have listeners.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtUnregister(&es1, &el2);
|
|
test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Event Flags dispatching.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The test dispatches three event flags and verifies that the associated event handlers are invoked in LSb-first order.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Three evenf flag bits are raised then chEvtDispatch() is invoked, the sequence of handlers calls is tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtDispatch(evhndl, 7);
|
|
test_assert_sequence("ABC", "invalid sequence");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Events Flags wait using chEvtWaitOne().</value>
|
|
</brief>
|
|
<description>
|
|
<value>Functionality of chEvtWaitOne() is tested under various scenarios.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[eventmask_t m;
|
|
systime_t target_time;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Setting three event flags.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtAddEvents(7);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitOne() three times, each time a single flag must be returned in order of priority.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
|
|
test_assert(m == 1, "single event error");
|
|
m = chEvtWaitOne(ALL_EVENTS);
|
|
test_assert(m == 2, "single event error");
|
|
m = chEvtWaitOne(ALL_EVENTS);
|
|
test_assert(m == 4, "single event error");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Getting current time and starting a signaler thread, the thread will set an event flag after 50mS.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
|
|
thread_descriptor_t td = {
|
|
.name = "event1",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = evtthd1,
|
|
.arg = chThdGetSelfX()
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitOne() then verifying that the event has been received after 50mS and that the event flags mask has been emptied.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
|
|
test_assert_time_window(target_time,
|
|
chTimeAddX(target_time, ALLOWED_DELAY),
|
|
"out of time window");
|
|
test_assert(m == 1, "event flag error");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Events Flags wait using chEvtWaitAny().</value>
|
|
</brief>
|
|
<description>
|
|
<value>Functionality of chEvtWaitAny() is tested under various scenarios.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[eventmask_t m;
|
|
systime_t target_time;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Setting two, non contiguous, event flags.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtAddEvents(5);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitAny() one time, the two flags must be returned.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
|
|
test_assert(m == 5, "unexpected pending bit");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Getting current time and starting a signaler thread, the thread will set an event flag after 50mS.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
|
|
thread_descriptor_t td = {
|
|
.name = "event1",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = evtthd1,
|
|
.arg = chThdGetSelfX()
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitAny() then verifying that the event has been received after 50mS and that the event flags mask has been emptied.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
|
|
test_assert_time_window(target_time,
|
|
chTimeAddX(target_time, ALLOWED_DELAY),
|
|
"out of time window");
|
|
test_assert(m == 1, "event flag error");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Events Flags wait using chEvtWaitAll().</value>
|
|
</brief>
|
|
<description>
|
|
<value>Functionality of chEvtWaitAll() is tested under various scenarios.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[eventmask_t m;
|
|
systime_t target_time;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Setting two, non contiguous, event flags.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtAddEvents(5);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitAll() one time, the two flags must be returned.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitAll(5);
|
|
test_assert(m == 5, "unexpected pending bit");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Setting one event flag.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtAddEvents(4);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Getting current time and starting a signaler thread, the thread will set another event flag after 50mS.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
|
|
thread_descriptor_t td = {
|
|
.name = "event1",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = evtthd1,
|
|
.arg = chThdGetSelfX()
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitAll() then verifying that both event flags have been received after 50mS and that the event flags mask has been emptied.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitAll(5);
|
|
test_assert_time_window(target_time,
|
|
chTimeAddX(target_time, ALLOWED_DELAY),
|
|
"out of time window");
|
|
test_assert(m == 5, "event flags error");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Events Flags wait timeouts.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Timeout functionality is tested for chEvtWaitOneTimeout(), chEvtWaitAnyTimeout() and chEvtWaitAllTimeout().</value>
|
|
</description>
|
|
<condition>
|
|
<value></value>
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>F
|
|
<local_variables>
|
|
<value><![CDATA[eventmask_t m;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The functions are invoked first with TIME_IMMEDIATE timeout, the timeout condition is tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
|
test_assert(m == 0, "spurious event");
|
|
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
|
test_assert(m == 0, "spurious event");
|
|
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE);
|
|
test_assert(m == 0, "spurious event");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The functions are invoked first with a 50mS timeout, the timeout condition is tested.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_MS2I(50));
|
|
test_assert(m == 0, "spurious event");
|
|
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(50));
|
|
test_assert(m == 0, "spurious event");
|
|
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_MS2I(50));
|
|
test_assert(m == 0, "spurious event");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Broadcasting using chEvtBroadcast().</value>
|
|
</brief>
|
|
<description>
|
|
<value>Functionality of chEvtBroadcast() is tested.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);
|
|
chEvtObjectInit(&es1);
|
|
chEvtObjectInit(&es2);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[eventmask_t m;
|
|
event_listener_t el1, el2;
|
|
systime_t target_time;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Registering on two event sources associating them with flags 1 and 4.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtRegisterMask(&es1, &el1, 1);
|
|
chEvtRegisterMask(&es2, &el2, 4);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Getting current time and starting a broadcaster thread, the thread broadcast the first Event Source immediately and the other after 50mS.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[target_time = chTimeAddX(test_wait_tick(), TIME_MS2I(50));
|
|
thread_descriptor_t td = {
|
|
.name = "event2",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = evtthd2,
|
|
.arg = NULL
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Calling chEvtWaitAll() then verifying that both event flags have been received after 50mS and that the event flags mask has been emptied.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[m = chEvtWaitAll(5);
|
|
test_assert_time_window(target_time,
|
|
chTimeAddX(target_time, ALLOWED_DELAY),
|
|
"out of time window");
|
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
|
test_assert(m == 0, "stuck event");
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Unregistering from the Event Sources.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chEvtUnregister(&es1, &el1);
|
|
chEvtUnregister(&es2, &el2);
|
|
test_assert(!chEvtIsListeningI(&es1), "stuck listener");
|
|
test_assert(!chEvtIsListeningI(&es2), "stuck listener");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="0">
|
|
<value>Internal Tests</value>
|
|
</type>
|
|
<brief>
|
|
<value>Synchronous Messages.</value>
|
|
</brief>
|
|
<description>
|
|
<value>This module implements the test sequence for the Synchronous Messages subsystem.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_MESSAGES</value>
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[/*
|
|
* Messager thread.
|
|
*/
|
|
static THD_FUNCTION(messenger, p) {
|
|
|
|
chMsgSend(p, 'A');
|
|
chMsgSend(p, 'B');
|
|
chMsgSend(p, 'C');
|
|
chMsgSend(p, 'D');
|
|
}]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Messages Server loop.</value>
|
|
</brief>
|
|
<description>
|
|
<value>A messenger 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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[thread_t *tp, *tp1;
|
|
msg_t msg;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Starting the messenger thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = messenger,
|
|
.arg = chThdGetSelfX()
|
|
};
|
|
tp1 = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Waiting for four messages then testing the receive order.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[unsigned i;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
tp = chMsgWait();
|
|
msg = chMsgGet(tp);
|
|
chMsgRelease(tp, msg);
|
|
test_emit_token(msg);
|
|
}
|
|
chThdWait(tp1);
|
|
test_assert_sequence("ABCD", "invalid sequence");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
<sequence>
|
|
<type index="2">
|
|
<value>Benchmarks</value>
|
|
</type>
|
|
<brief>
|
|
<value>Benchmarks.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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.<br>
|
|
Objective of the test sequence 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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<shared_code>
|
|
<value><![CDATA[#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__)
|
|
static semaphore_t sem1;
|
|
#endif
|
|
#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
|
|
static mutex_t mtx1;
|
|
#endif
|
|
|
|
#if CH_CFG_USE_MESSAGES
|
|
static THD_FUNCTION(bmk_thread1, p) {
|
|
thread_t *tp;
|
|
msg_t msg;
|
|
|
|
(void)p;
|
|
do {
|
|
tp = chMsgWait();
|
|
msg = chMsgGet(tp);
|
|
chMsgRelease(tp, msg);
|
|
} while (msg);
|
|
}
|
|
|
|
NOINLINE static unsigned int msg_loop_test(thread_t *tp) {
|
|
systime_t start, end;
|
|
|
|
uint32_t n = 0;
|
|
start = test_wait_tick();
|
|
end = chTimeAddX(start, TIME_MS2I(1000));
|
|
do {
|
|
(void)chMsgSend(tp, 1);
|
|
n++;
|
|
#if defined(SIMULATOR)
|
|
_sim_check_for_interrupts();
|
|
#endif
|
|
} while (chVTIsSystemTimeWithinX(start, end));
|
|
(void)chMsgSend(tp, 0);
|
|
return n;
|
|
}
|
|
#endif
|
|
|
|
static THD_FUNCTION(bmk_thread3, p) {
|
|
|
|
chThdExit((msg_t)p);
|
|
}
|
|
|
|
static THD_FUNCTION(bmk_thread4, p) {
|
|
msg_t msg;
|
|
thread_t *self = chThdGetSelfX();
|
|
|
|
(void)p;
|
|
chSysLock();
|
|
do {
|
|
chSchGoSleepS(NIL_STATE_SUSPENDED);
|
|
msg = self->u1.msg;
|
|
} while (msg == MSG_OK);
|
|
chSysUnlock();
|
|
}]]></value>
|
|
</shared_code>
|
|
<cases>
|
|
<case>
|
|
<brief>
|
|
<value>Messages performance #1.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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 on the output log.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_MESSAGES</value>
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[uint32_t n;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The messenger thread is started at a lower priority than the current thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = bmk_thread1,
|
|
.arg = NULL
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The number of messages exchanged is counted in a one second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[n = msg_loop_test(tp);
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n);
|
|
test_print(" msgs/S, ");
|
|
test_printn(n << 1);
|
|
test_println(" ctxswc/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Messages performance #2.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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 on the output log.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_MESSAGES</value>
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[uint32_t n;
|
|
thread_t *tp;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The messenger thread is started at an higher priority than the current thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = bmk_thread1,
|
|
.arg = NULL
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The number of messages exchanged is counted in a one second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[n = msg_loop_test(tp);
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n);
|
|
test_print(" msgs/S, ");
|
|
test_printn(n << 1);
|
|
test_println(" ctxswc/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Context Switch performance.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[thread_t *tp;
|
|
uint32_t n;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>Starting the target thread at an higher priority level.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = bmk_thread4,
|
|
.arg = NULL
|
|
};
|
|
tp = chThdCreate(&td);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Waking up the thread as fast as possible in a one second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[systime_t start, end;
|
|
|
|
n = 0;
|
|
start = test_wait_tick();
|
|
end = chTimeAddX(start, TIME_MS2I(1000));
|
|
do {
|
|
chSysLock();
|
|
chSchWakeupS(tp, MSG_OK);
|
|
chSchWakeupS(tp, MSG_OK);
|
|
chSchWakeupS(tp, MSG_OK);
|
|
chSchWakeupS(tp, MSG_OK);
|
|
chSysUnlock();
|
|
n += 4;
|
|
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Stopping the target thread.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[chSysLock();
|
|
chSchWakeupS(tp, MSG_TIMEOUT);
|
|
chSysUnlock();
|
|
chThdWait(tp);]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n * 2);
|
|
test_println(" ctxswc/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Threads performance, full cycle.</value>
|
|
</brief>
|
|
<description>
|
|
<value>Threads are continuously created and terminated into a loop. A full 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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[uint32_t n;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>A thread is created at a lower priority level and its termination detected using @p chThdWait(). The operation is repeated continuously in a one-second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[systime_t start, end;
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() + 1,
|
|
.funcp = bmk_thread3,
|
|
.arg = NULL
|
|
};
|
|
|
|
n = 0;
|
|
start = test_wait_tick();
|
|
end = chTimeAddX(start, TIME_MS2I(1000));
|
|
do {
|
|
chThdWait(chThdCreate(&td));
|
|
n++;
|
|
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n);
|
|
test_println(" threads/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Threads performance, create/exit only.</value>
|
|
</brief>
|
|
<description>
|
|
<value>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.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[uint32_t n;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>A thread is created at an higher priority level and let terminate immediately. The operation is repeated continuously in a one-second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[systime_t start, end;
|
|
thread_descriptor_t td = {
|
|
.name = "messenger",
|
|
.wbase = wa_common,
|
|
.wend = THD_WORKING_AREA_END(wa_common),
|
|
.prio = chThdGetPriorityX() - 1,
|
|
.funcp = bmk_thread3,
|
|
.arg = NULL
|
|
};
|
|
|
|
n = 0;
|
|
start = test_wait_tick();
|
|
end = chTimeAddX(start, TIME_MS2I(1000));
|
|
do {
|
|
chThdWait(chThdCreate(&td));
|
|
n++;
|
|
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>Score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n);
|
|
test_println(" threads/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>Semaphores wait/signal performance</value>
|
|
</brief>
|
|
<description>
|
|
<value>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.</value>
|
|
</description>
|
|
<condition>
|
|
<value>CH_CFG_USE_SEMAPHORES</value>
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value><![CDATA[chSemObjectInit(&sem1, 1);]]></value>
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value><![CDATA[uint32_t n;]]></value>
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>A semaphore is teken and released. The operation is repeated continuously in a one-second time window.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[systime_t start, end;
|
|
|
|
n = 0;
|
|
start = test_wait_tick();
|
|
end = chTimeAddX(start, TIME_MS2I(1000));
|
|
do {
|
|
chSemWait(&sem1);
|
|
chSemSignal(&sem1);
|
|
chSemWait(&sem1);
|
|
chSemSignal(&sem1);
|
|
chSemWait(&sem1);
|
|
chSemSignal(&sem1);
|
|
chSemWait(&sem1);
|
|
chSemSignal(&sem1);
|
|
n++;
|
|
#if defined(SIMULATOR)
|
|
_sim_check_for_interrupts();
|
|
#endif
|
|
} while (chVTIsSystemTimeWithinX(start, end));]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The score is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Score : ");
|
|
test_printn(n * 4);
|
|
test_println(" wait+signal/S");]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
<case>
|
|
<brief>
|
|
<value>RAM Footprint.</value>
|
|
</brief>
|
|
<description>
|
|
<value>The memory size of the various kernel objects is printed.</value>
|
|
</description>
|
|
<condition>
|
|
<value />
|
|
</condition>
|
|
<various_code>
|
|
<setup_code>
|
|
<value />
|
|
</setup_code>
|
|
<teardown_code>
|
|
<value />
|
|
</teardown_code>
|
|
<local_variables>
|
|
<value />
|
|
</local_variables>
|
|
</various_code>
|
|
<steps>
|
|
<step>
|
|
<description>
|
|
<value>The size of the system area is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- System: ");
|
|
test_printn(sizeof(nil_system_t));
|
|
test_println(" bytes");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The size of a thread structure is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[test_print("--- Thread: ");
|
|
test_printn(sizeof(thread_t));
|
|
test_println(" bytes");]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The size of a semaphore structure is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__)
|
|
test_print("--- Semaph: ");
|
|
test_printn(sizeof(semaphore_t));
|
|
test_println(" bytes");
|
|
#endif]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The size of an event source is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
|
|
test_print("--- EventS: ");
|
|
test_printn(sizeof(event_source_t));
|
|
test_println(" bytes");
|
|
#endif]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The size of an event listener is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
|
|
test_print("--- EventL: ");
|
|
test_printn(sizeof(event_listener_t));
|
|
test_println(" bytes");
|
|
#endif]]></value>
|
|
</code>
|
|
</step>
|
|
<step>
|
|
<description>
|
|
<value>The size of a mailbox is printed.</value>
|
|
</description>
|
|
<tags>
|
|
<value />
|
|
</tags>
|
|
<code>
|
|
<value><![CDATA[#if CH_CFG_USE_MAILBOXES || defined(__DOXYGEN__)
|
|
test_print("--- MailB.: ");
|
|
test_printn(sizeof(mailbox_t));
|
|
test_println(" bytes");
|
|
#endif]]></value>
|
|
</code>
|
|
</step>
|
|
</steps>
|
|
</case>
|
|
</cases>
|
|
</sequence>
|
|
</sequences>
|
|
</instance>
|
|
</instances>
|
|
<exportedFeatures />
|
|
</application>
|
|
</SPC5-Config>
|