ChibiOS/test/nil/configuration.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 &lt; 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 &gt; 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.&lt;br&gt;&#xD;
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.&lt;br&gt;&#xD;
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.&lt;br&gt;&#xD;
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.&lt;br&gt;&#xD;
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.&lt;br&gt;&#xD;
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.&lt;br&gt; 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.&lt;br&gt;&#xD;
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>