git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9189 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
039a6c7349
commit
7c20551c98
|
@ -51,7 +51,7 @@ int main(void) {
|
||||||
chSysInit();
|
chSysInit();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPIOI1 is programmed as output (board LED).
|
* ARD_D13 is programmed as output (board LED).
|
||||||
*/
|
*/
|
||||||
palClearLine(LINE_ARD_D13);
|
palClearLine(LINE_ARD_D13);
|
||||||
palSetLineMode(LINE_ARD_D13, PAL_MODE_OUTPUT_PUSHPULL);
|
palSetLineMode(LINE_ARD_D13, PAL_MODE_OUTPUT_PUSHPULL);
|
||||||
|
|
|
@ -1468,13 +1468,13 @@ static THD_FUNCTION(thread8, p) {
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock(&m1);
|
chMtxUnlock(&m1);
|
||||||
chMtxUnlock(&m2);
|
chMtxUnlock(&m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static THD_FUNCTION(thread9, p) {
|
static THD_FUNCTION(thread9, p) {
|
||||||
|
|
||||||
chMtxLock(&m2);
|
chMtxLock(&m2);
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock(&m2);
|
chMtxUnlock(&m2);
|
||||||
}
|
}
|
||||||
#endif /* CH_CFG_USE_CONDVARS */]]></value>
|
#endif /* CH_CFG_USE_CONDVARS */]]></value>
|
||||||
</shared_code>
|
</shared_code>
|
||||||
|
@ -2374,6 +2374,409 @@ test_assert_sequence("ABCD", "invalid sequence");]]></value>
|
||||||
</case>
|
</case>
|
||||||
</cases>
|
</cases>
|
||||||
</sequence>
|
</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};
|
||||||
|
|
||||||
|
static THD_FUNCTION(evt_thread3, p) {
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(50);
|
||||||
|
chEvtSignal((thread_t *)p, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static THD_FUNCTION(evt_thread4, 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;]]></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 = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());]]></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, 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");
|
||||||
|
test_wait_threads();]]></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;]]></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 = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());]]></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, 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");
|
||||||
|
test_wait_threads();]]></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;]]></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 = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());]]></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, 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");
|
||||||
|
test_wait_threads();]]></value>
|
||||||
|
</code>
|
||||||
|
</step>
|
||||||
|
</steps>
|
||||||
|
</case>
|
||||||
|
</cases>
|
||||||
|
</sequence>
|
||||||
<sequence>
|
<sequence>
|
||||||
<type index="0">
|
<type index="0">
|
||||||
<value>Internal Tests</value>
|
<value>Internal Tests</value>
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* - @subpage test_sequence_007
|
* - @subpage test_sequence_007
|
||||||
* - @subpage test_sequence_008
|
* - @subpage test_sequence_008
|
||||||
* - @subpage test_sequence_009
|
* - @subpage test_sequence_009
|
||||||
|
* - @subpage test_sequence_010
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ const testcase_t * const *test_suite[] = {
|
||||||
test_sequence_007,
|
test_sequence_007,
|
||||||
test_sequence_008,
|
test_sequence_008,
|
||||||
test_sequence_009,
|
test_sequence_009,
|
||||||
|
test_sequence_010,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "test_sequence_007.h"
|
#include "test_sequence_007.h"
|
||||||
#include "test_sequence_008.h"
|
#include "test_sequence_008.h"
|
||||||
#include "test_sequence_009.h"
|
#include "test_sequence_009.h"
|
||||||
|
#include "test_sequence_010.h"
|
||||||
|
|
||||||
#if !defined(__DOXYGEN__)
|
#if !defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
|
|
@ -19,369 +19,402 @@
|
||||||
#include "test_root.h"
|
#include "test_root.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_sequence_007 [7] Mailboxes
|
* @page test_sequence_007 [7] Event Sources and Event Flags
|
||||||
*
|
*
|
||||||
* File: @ref test_sequence_007.c
|
* File: @ref test_sequence_007.c
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* This sequence tests the ChibiOS/RT functionalities related to
|
* This module implements the test sequence for the Events subsystem.
|
||||||
* mailboxes.
|
|
||||||
*
|
*
|
||||||
* <h2>Conditions</h2>
|
* <h2>Conditions</h2>
|
||||||
* This sequence is only executed if the following preprocessor condition
|
* This sequence is only executed if the following preprocessor condition
|
||||||
* evaluates to true:
|
* evaluates to true:
|
||||||
* - CH_CFG_USE_MAILBOXES
|
* - CH_CFG_USE_EVENTS
|
||||||
* .
|
* .
|
||||||
*
|
*
|
||||||
* <h2>Test Cases</h2>
|
* <h2>Test Cases</h2>
|
||||||
* - @subpage test_007_001
|
* - @subpage test_007_001
|
||||||
* - @subpage test_007_002
|
* - @subpage test_007_002
|
||||||
* - @subpage test_007_003
|
* - @subpage test_007_003
|
||||||
|
* - @subpage test_007_004
|
||||||
|
* - @subpage test_007_005
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Shared code.
|
* Shared code.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define MB_SIZE 4
|
static EVENTSOURCE_DECL(es1);
|
||||||
|
static EVENTSOURCE_DECL(es2);
|
||||||
|
|
||||||
static msg_t mb_buffer[MB_SIZE];
|
static void h1(eventid_t id) {(void)id;test_emit_token('A');}
|
||||||
static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE);
|
static void h2(eventid_t id) {(void)id;test_emit_token('B');}
|
||||||
|
static void h3(eventid_t id) {(void)id;test_emit_token('C');}
|
||||||
|
static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
|
||||||
|
|
||||||
|
static THD_FUNCTION(evt_thread3, p) {
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(50);
|
||||||
|
chEvtSignal((thread_t *)p, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static THD_FUNCTION(evt_thread4, p) {
|
||||||
|
|
||||||
|
(void)p;
|
||||||
|
chEvtBroadcast(&es1);
|
||||||
|
chThdSleepMilliseconds(50);
|
||||||
|
chEvtBroadcast(&es2);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Test cases.
|
* Test cases.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_007_001 [7.1] Mailbox normal API, non-blocking tests
|
* @page test_007_001 [7.1] Events registration
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The mailbox normal API is tested without triggering blocking
|
* Two event listeners are registered on an event source and then
|
||||||
* conditions.
|
* 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.
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [7.1.1] Testing the mailbox size.
|
* - [7.1.1] An Event Source is initialized.
|
||||||
* - [7.1.2] Resetting the mailbox, conditions are checked, no errors
|
* - [7.1.2] Two Event Listeners are registered on the Event Source,
|
||||||
* expected.
|
* the Event Source is tested to have listeners.
|
||||||
* - [7.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
* - [7.1.3] An Event Listener is unregistered, the Event Source must
|
||||||
* once, no errors expected.
|
* still have listeners.
|
||||||
* - [7.1.4] Testing intermediate conditions. Data pointers must be
|
* - [7.1.4] An Event Listener is unregistered, the Event Source must
|
||||||
* aligned, semaphore counters are checked.
|
* not have listeners.
|
||||||
* - [7.1.5] Emptying the mailbox using chMBFetch(), no errors
|
|
||||||
* expected.
|
|
||||||
* - [7.1.6] Posting and then fetching one more message, no errors
|
|
||||||
* expected.
|
|
||||||
* - [7.1.7] Testing final conditions. Data pointers must be aligned to
|
|
||||||
* buffer start, semaphore counters are checked.
|
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_007_001_setup(void) {
|
|
||||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_007_001_teardown(void) {
|
|
||||||
chMBReset(&mb1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_007_001_execute(void) {
|
static void test_007_001_execute(void) {
|
||||||
msg_t msg1, msg2;
|
event_listener_t el1, el2;
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
/* [7.1.1] Testing the mailbox size.*/
|
/* [7.1.1] An Event Source is initialized.*/
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
chEvtObjectInit(&es1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.1.2] Resetting the mailbox, conditions are checked, no errors
|
/* [7.1.2] Two Event Listeners are registered on the Event Source,
|
||||||
expected.*/
|
the Event Source is tested to have listeners.*/
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
chMBReset(&mb1);
|
chEvtRegisterMask(&es1, &el1, 1);
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
chEvtRegisterMask(&es1, &el2, 2);
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
test_assert_lock(chEvtIsListeningI(&es1), "no listener");
|
||||||
test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
|
||||||
test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
/* [7.1.3] An Event Listener is unregistered, the Event Source must
|
||||||
once, no errors expected.*/
|
still have listeners.*/
|
||||||
test_set_step(3);
|
test_set_step(3);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MB_SIZE - 1; i++) {
|
chEvtUnregister(&es1, &el1);
|
||||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
test_assert_lock(chEvtIsListeningI(&es1), "no listener");
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
msg1 = chMBPostAhead(&mb1, 'A', TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.1.4] Testing intermediate conditions. Data pointers must be
|
/* [7.1.4] An Event Listener is unregistered, the Event Source must
|
||||||
aligned, semaphore counters are checked.*/
|
not have listeners.*/
|
||||||
test_set_step(4);
|
test_set_step(4);
|
||||||
{
|
{
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty");
|
chEvtUnregister(&es1, &el2);
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
|
test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");
|
||||||
test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.1.5] Emptying the mailbox using chMBFetch(), no errors
|
|
||||||
expected.*/
|
|
||||||
test_set_step(5);
|
|
||||||
{
|
|
||||||
for (i = 0; i < MB_SIZE; i++) {
|
|
||||||
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
test_emit_token(msg2);
|
|
||||||
}
|
|
||||||
test_assert_sequence("ABCD", "wrong get sequence");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.1.6] Posting and then fetching one more message, no errors
|
|
||||||
expected.*/
|
|
||||||
test_set_step(6);
|
|
||||||
{
|
|
||||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.1.7] Testing final conditions. Data pointers must be aligned to
|
|
||||||
buffer start, semaphore counters are checked.*/
|
|
||||||
test_set_step(7);
|
|
||||||
{
|
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
|
||||||
test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
|
||||||
test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_007_001 = {
|
static const testcase_t test_007_001 = {
|
||||||
"Mailbox normal API, non-blocking tests",
|
"Events registration",
|
||||||
test_007_001_setup,
|
NULL,
|
||||||
test_007_001_teardown,
|
NULL,
|
||||||
test_007_001_execute
|
test_007_001_execute
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_007_002 [7.2] Mailbox I-Class API, non-blocking tests
|
* @page test_007_002 [7.2] Event Flags dispatching
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The mailbox I-Class API is tested without triggering blocking
|
* The test dispatches three event flags and verifies that the
|
||||||
* conditions.
|
* associated event handlers are invoked in LSb-first order.
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [7.2.1] Testing the mailbox size.
|
* - [7.2.1] Three evenf flag bits are raised then chEvtDispatch() is
|
||||||
* - [7.2.2] Resetting the mailbox, conditions are checked, no errors
|
* invoked, the sequence of handlers calls is tested.
|
||||||
* expected.
|
|
||||||
* - [7.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
|
||||||
* once, no errors expected.
|
|
||||||
* - [7.2.4] Testing intermediate conditions. Data pointers must be
|
|
||||||
* aligned, semaphore counters are checked.
|
|
||||||
* - [7.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
|
||||||
* expected.
|
|
||||||
* - [7.2.6] Posting and then fetching one more message, no errors
|
|
||||||
* expected.
|
|
||||||
* - [7.2.7] Testing final conditions. Data pointers must be aligned to
|
|
||||||
* buffer start, semaphore counters are checked.
|
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_007_002_setup(void) {
|
static void test_007_002_setup(void) {
|
||||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
}
|
|
||||||
|
|
||||||
static void test_007_002_teardown(void) {
|
|
||||||
chMBReset(&mb1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_007_002_execute(void) {
|
static void test_007_002_execute(void) {
|
||||||
msg_t msg1, msg2;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
/* [7.2.1] Testing the mailbox size.*/
|
/* [7.2.1] Three evenf flag bits are raised then chEvtDispatch() is
|
||||||
|
invoked, the sequence of handlers calls is tested.*/
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
chEvtDispatch(evhndl, 7);
|
||||||
}
|
test_assert_sequence("ABC", "invalid sequence");
|
||||||
|
|
||||||
/* [7.2.2] Resetting the mailbox, conditions are checked, no errors
|
|
||||||
expected.*/
|
|
||||||
test_set_step(2);
|
|
||||||
{
|
|
||||||
chSysLock();
|
|
||||||
chMBResetI(&mb1);
|
|
||||||
chSysUnlock();
|
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
|
||||||
test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
|
||||||
test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
|
||||||
once, no errors expected.*/
|
|
||||||
test_set_step(3);
|
|
||||||
{
|
|
||||||
for (i = 0; i < MB_SIZE - 1; i++) {
|
|
||||||
chSysLock();
|
|
||||||
msg1 = chMBPostI(&mb1, 'B' + i);
|
|
||||||
chSysUnlock();
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
chSysLock();
|
|
||||||
msg1 = chMBPostAheadI(&mb1, 'A');
|
|
||||||
chSysUnlock();
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.2.4] Testing intermediate conditions. Data pointers must be
|
|
||||||
aligned, semaphore counters are checked.*/
|
|
||||||
test_set_step(4);
|
|
||||||
{
|
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty");
|
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
|
|
||||||
test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
|
||||||
expected.*/
|
|
||||||
test_set_step(5);
|
|
||||||
{
|
|
||||||
for (i = 0; i < MB_SIZE; i++) {
|
|
||||||
chSysLock();
|
|
||||||
msg1 = chMBFetchI(&mb1, &msg2);
|
|
||||||
chSysUnlock();
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
test_emit_token(msg2);
|
|
||||||
}
|
|
||||||
test_assert_sequence("ABCD", "wrong get sequence");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.2.6] Posting and then fetching one more message, no errors
|
|
||||||
expected.*/
|
|
||||||
test_set_step(6);
|
|
||||||
{
|
|
||||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [7.2.7] Testing final conditions. Data pointers must be aligned to
|
|
||||||
buffer start, semaphore counters are checked.*/
|
|
||||||
test_set_step(7);
|
|
||||||
{
|
|
||||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
|
||||||
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
|
||||||
test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
|
||||||
test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_007_002 = {
|
static const testcase_t test_007_002 = {
|
||||||
"Mailbox I-Class API, non-blocking tests",
|
"Event Flags dispatching",
|
||||||
test_007_002_setup,
|
test_007_002_setup,
|
||||||
test_007_002_teardown,
|
NULL,
|
||||||
test_007_002_execute
|
test_007_002_execute
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_007_003 [7.3] Mailbox timeouts
|
* @page test_007_003 [7.3] Events Flags wait using chEvtWaitOne()
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The mailbox API is tested for timeouts.
|
* Functionality of chEvtWaitOne() is tested under various scenarios.
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [7.3.1] Filling the mailbox.
|
* - [7.3.1] Setting three event flags.
|
||||||
* - [7.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
|
* - [7.3.2] Calling chEvtWaitOne() three times, each time a single
|
||||||
* chMBPostAheadI() timeout.
|
* flag must be returned in order of priority.
|
||||||
* - [7.3.3] Resetting the mailbox.
|
* - [7.3.3] Getting current time and starting a signaler thread, the
|
||||||
* - [7.3.4] Testing chMBFetch() and chMBFetchI() timeout.
|
* thread will set an event flag after 50mS.
|
||||||
|
* - [7.3.4] Calling chEvtWaitOne() then verifying that the event has
|
||||||
|
* been received after 50mS and that the event flags mask has been
|
||||||
|
* emptied.
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_007_003_setup(void) {
|
static void test_007_003_setup(void) {
|
||||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
}
|
|
||||||
|
|
||||||
static void test_007_003_teardown(void) {
|
|
||||||
chMBReset(&mb1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_007_003_execute(void) {
|
static void test_007_003_execute(void) {
|
||||||
msg_t msg1, msg2;
|
eventmask_t m;
|
||||||
unsigned i;
|
systime_t target_time;
|
||||||
|
|
||||||
/* [7.3.1] Filling the mailbox.*/
|
/* [7.3.1] Setting three event flags.*/
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MB_SIZE; i++) {
|
chEvtAddEvents(7);
|
||||||
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
|
||||||
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
|
/* [7.3.2] Calling chEvtWaitOne() three times, each time a single
|
||||||
chMBPostAheadI() timeout.*/
|
flag must be returned in order of priority.*/
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
msg1 = chMBPost(&mb1, 'X', 1);
|
m = chEvtWaitOne(ALL_EVENTS);
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
test_assert(m == 1, "single event error");
|
||||||
chSysLock();
|
m = chEvtWaitOne(ALL_EVENTS);
|
||||||
msg1 = chMBPostI(&mb1, 'X');
|
test_assert(m == 2, "single event error");
|
||||||
chSysUnlock();
|
m = chEvtWaitOne(ALL_EVENTS);
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
test_assert(m == 4, "single event error");
|
||||||
msg1 = chMBPostAhead(&mb1, 'X', 1);
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
test_assert(m == 0, "stuck event");
|
||||||
chSysLock();
|
|
||||||
msg1 = chMBPostAheadI(&mb1, 'X');
|
|
||||||
chSysUnlock();
|
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.3.3] Resetting the mailbox.*/
|
/* [7.3.3] Getting current time and starting a signaler thread, the
|
||||||
|
thread will set an event flag after 50mS.*/
|
||||||
test_set_step(3);
|
test_set_step(3);
|
||||||
{
|
{
|
||||||
chMBReset(&mb1);
|
target_time = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [7.3.4] Testing chMBFetch() and chMBFetchI() timeout.*/
|
/* [7.3.4] Calling chEvtWaitOne() then verifying that the event has
|
||||||
|
been received after 50mS and that the event flags mask has been
|
||||||
|
emptied.*/
|
||||||
test_set_step(4);
|
test_set_step(4);
|
||||||
{
|
{
|
||||||
msg1 = chMBFetch(&mb1, &msg2, 1);
|
m = chEvtWaitOne(ALL_EVENTS);
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
|
||||||
chSysLock();
|
"out of time window");
|
||||||
msg1 = chMBFetchI(&mb1, &msg2);
|
test_assert(m == 1, "event flag error");
|
||||||
chSysUnlock();
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
test_assert(m == 0, "stuck event");
|
||||||
|
test_wait_threads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_007_003 = {
|
static const testcase_t test_007_003 = {
|
||||||
"Mailbox timeouts",
|
"Events Flags wait using chEvtWaitOne()",
|
||||||
test_007_003_setup,
|
test_007_003_setup,
|
||||||
test_007_003_teardown,
|
NULL,
|
||||||
test_007_003_execute
|
test_007_003_execute
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page test_007_004 [7.4] Events Flags wait using chEvtWaitAny()
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* Functionality of chEvtWaitAny() is tested under various scenarios.
|
||||||
|
*
|
||||||
|
* <h2>Test Steps</h2>
|
||||||
|
* - [7.4.1] Setting two, non contiguous, event flags.
|
||||||
|
* - [7.4.2] Calling chEvtWaitAny() one time, the two flags must be
|
||||||
|
* returned.
|
||||||
|
* - [7.4.3] Getting current time and starting a signaler thread, the
|
||||||
|
* thread will set an event flag after 50mS.
|
||||||
|
* - [7.4.4] Calling chEvtWaitAny() then verifying that the event has
|
||||||
|
* been received after 50mS and that the event flags mask has been
|
||||||
|
* emptied.
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_007_004_setup(void) {
|
||||||
|
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_007_004_execute(void) {
|
||||||
|
eventmask_t m;
|
||||||
|
systime_t target_time;
|
||||||
|
|
||||||
|
/* [7.4.1] Setting two, non contiguous, event flags.*/
|
||||||
|
test_set_step(1);
|
||||||
|
{
|
||||||
|
chEvtAddEvents(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.4.2] Calling chEvtWaitAny() one time, the two flags must be
|
||||||
|
returned.*/
|
||||||
|
test_set_step(2);
|
||||||
|
{
|
||||||
|
m = chEvtWaitAny(ALL_EVENTS);
|
||||||
|
test_assert(m == 5, "unexpected pending bit");
|
||||||
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
|
test_assert(m == 0, "stuck event");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.4.3] Getting current time and starting a signaler thread, the
|
||||||
|
thread will set an event flag after 50mS.*/
|
||||||
|
test_set_step(3);
|
||||||
|
{
|
||||||
|
target_time = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.4.4] Calling chEvtWaitAny() then verifying that the event has
|
||||||
|
been received after 50mS and that the event flags mask has been
|
||||||
|
emptied.*/
|
||||||
|
test_set_step(4);
|
||||||
|
{
|
||||||
|
m = chEvtWaitAny(ALL_EVENTS);
|
||||||
|
test_assert_time_window(target_time, 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");
|
||||||
|
test_wait_threads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const testcase_t test_007_004 = {
|
||||||
|
"Events Flags wait using chEvtWaitAny()",
|
||||||
|
test_007_004_setup,
|
||||||
|
NULL,
|
||||||
|
test_007_004_execute
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page test_007_005 [7.5] Events Flags wait using chEvtWaitAll()
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* Functionality of chEvtWaitAll() is tested under various scenarios.
|
||||||
|
*
|
||||||
|
* <h2>Test Steps</h2>
|
||||||
|
* - [7.5.1] Setting two, non contiguous, event flags.
|
||||||
|
* - [7.5.2] Calling chEvtWaitAll() one time, the two flags must be
|
||||||
|
* returned.
|
||||||
|
* - [7.5.3] Setting one event flag.
|
||||||
|
* - [7.5.4] Getting current time and starting a signaler thread, the
|
||||||
|
* thread will set another event flag after 50mS.
|
||||||
|
* - [7.5.5] Calling chEvtWaitAll() then verifying that both event
|
||||||
|
* flags have been received after 50mS and that the event flags mask
|
||||||
|
* has been emptied.
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_007_005_setup(void) {
|
||||||
|
chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_007_005_execute(void) {
|
||||||
|
eventmask_t m;
|
||||||
|
systime_t target_time;
|
||||||
|
|
||||||
|
/* [7.5.1] Setting two, non contiguous, event flags.*/
|
||||||
|
test_set_step(1);
|
||||||
|
{
|
||||||
|
chEvtAddEvents(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.5.2] Calling chEvtWaitAll() one time, the two flags must be
|
||||||
|
returned.*/
|
||||||
|
test_set_step(2);
|
||||||
|
{
|
||||||
|
m = chEvtWaitAll(5);
|
||||||
|
test_assert(m == 5, "unexpected pending bit");
|
||||||
|
m = chEvtGetAndClearEvents(ALL_EVENTS);
|
||||||
|
test_assert(m == 0, "stuck event");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.5.3] Setting one event flag.*/
|
||||||
|
test_set_step(3);
|
||||||
|
{
|
||||||
|
chEvtAddEvents(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.5.4] Getting current time and starting a signaler thread, the
|
||||||
|
thread will set another event flag after 50mS.*/
|
||||||
|
test_set_step(4);
|
||||||
|
{
|
||||||
|
target_time = test_wait_tick() + MS2ST(50);
|
||||||
|
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||||
|
evt_thread3, chThdGetSelfX());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [7.5.5] Calling chEvtWaitAll() then verifying that both event
|
||||||
|
flags have been received after 50mS and that the event flags mask
|
||||||
|
has been emptied.*/
|
||||||
|
test_set_step(5);
|
||||||
|
{
|
||||||
|
m = chEvtWaitAll(5);
|
||||||
|
test_assert_time_window(target_time, 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");
|
||||||
|
test_wait_threads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const testcase_t test_007_005 = {
|
||||||
|
"Events Flags wait using chEvtWaitAll()",
|
||||||
|
test_007_005_setup,
|
||||||
|
NULL,
|
||||||
|
test_007_005_execute
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Exported data.
|
* Exported data.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mailboxes.
|
* @brief Event Sources and Event Flags.
|
||||||
*/
|
*/
|
||||||
const testcase_t * const test_sequence_007[] = {
|
const testcase_t * const test_sequence_007[] = {
|
||||||
&test_007_001,
|
&test_007_001,
|
||||||
&test_007_002,
|
&test_007_002,
|
||||||
&test_007_003,
|
&test_007_003,
|
||||||
|
&test_007_004,
|
||||||
|
&test_007_005,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CH_CFG_USE_MAILBOXES */
|
#endif /* CH_CFG_USE_EVENTS */
|
||||||
|
|
|
@ -19,18 +19,18 @@
|
||||||
#include "test_root.h"
|
#include "test_root.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_sequence_008 [8] Memory Pools
|
* @page test_sequence_008 [8] Mailboxes
|
||||||
*
|
*
|
||||||
* File: @ref test_sequence_008.c
|
* File: @ref test_sequence_008.c
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* This sequence tests the ChibiOS/RT functionalities related to memory
|
* This sequence tests the ChibiOS/RT functionalities related to
|
||||||
* pools.
|
* mailboxes.
|
||||||
*
|
*
|
||||||
* <h2>Conditions</h2>
|
* <h2>Conditions</h2>
|
||||||
* This sequence is only executed if the following preprocessor condition
|
* This sequence is only executed if the following preprocessor condition
|
||||||
* evaluates to true:
|
* evaluates to true:
|
||||||
* - CH_CFG_USE_MEMPOOLS
|
* - CH_CFG_USE_MAILBOXES
|
||||||
* .
|
* .
|
||||||
*
|
*
|
||||||
* <h2>Test Cases</h2>
|
* <h2>Test Cases</h2>
|
||||||
|
@ -40,251 +40,348 @@
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Shared code.
|
* Shared code.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define MEMORY_POOL_SIZE 4
|
#define MB_SIZE 4
|
||||||
|
|
||||||
static uint32_t objects[MEMORY_POOL_SIZE];
|
static msg_t mb_buffer[MB_SIZE];
|
||||||
static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), NULL);
|
static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE);
|
||||||
static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t));
|
|
||||||
|
|
||||||
static void *null_provider(size_t size, unsigned align) {
|
|
||||||
|
|
||||||
(void)size;
|
|
||||||
(void)align;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Test cases.
|
* Test cases.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_008_001 [8.1] Loading and emptying a memory pool
|
* @page test_008_001 [8.1] Mailbox normal API, non-blocking tests
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The memory pool functionality is tested by loading and emptying it,
|
* The mailbox normal API is tested without triggering blocking
|
||||||
* all conditions are tested.
|
* conditions.
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [8.1.1] Adding the objects to the pool using chPoolLoadArray().
|
* - [8.1.1] Testing the mailbox size.
|
||||||
* - [8.1.2] Emptying the pool using chPoolAlloc().
|
* - [8.1.2] Resetting the mailbox, conditions are checked, no errors
|
||||||
* - [8.1.3] Now must be empty.
|
* expected.
|
||||||
* - [8.1.4] Adding the objects to the pool using chPoolFree().
|
* - [8.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
||||||
* - [8.1.5] Emptying the pool using chPoolAlloc() again.
|
* once, no errors expected.
|
||||||
* - [8.1.6] Now must be empty again.
|
* - [8.1.4] Testing intermediate conditions. Data pointers must be
|
||||||
* - [8.1.7] Covering the case where a provider is unable to return
|
* aligned, semaphore counters are checked.
|
||||||
* more memory.
|
* - [8.1.5] Emptying the mailbox using chMBFetch(), no errors
|
||||||
|
* expected.
|
||||||
|
* - [8.1.6] Posting and then fetching one more message, no errors
|
||||||
|
* expected.
|
||||||
|
* - [8.1.7] Testing final conditions. Data pointers must be aligned to
|
||||||
|
* buffer start, semaphore counters are checked.
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_008_001_setup(void) {
|
static void test_008_001_setup(void) {
|
||||||
chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
|
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_008_001_teardown(void) {
|
||||||
|
chMBReset(&mb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_008_001_execute(void) {
|
static void test_008_001_execute(void) {
|
||||||
|
msg_t msg1, msg2;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
/* [8.1.1] Adding the objects to the pool using chPoolLoadArray().*/
|
/* [8.1.1] Testing the mailbox size.*/
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.2] Emptying the pool using chPoolAlloc().*/
|
/* [8.1.2] Resetting the mailbox, conditions are checked, no errors
|
||||||
|
expected.*/
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
chMBReset(&mb1);
|
||||||
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||||
|
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||||
|
test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
||||||
|
test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.3] Now must be empty.*/
|
/* [8.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
||||||
|
once, no errors expected.*/
|
||||||
test_set_step(3);
|
test_set_step(3);
|
||||||
{
|
{
|
||||||
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
for (i = 0; i < MB_SIZE - 1; i++) {
|
||||||
|
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
}
|
||||||
|
msg1 = chMBPostAhead(&mb1, 'A', TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.4] Adding the objects to the pool using chPoolFree().*/
|
/* [8.1.4] Testing intermediate conditions. Data pointers must be
|
||||||
|
aligned, semaphore counters are checked.*/
|
||||||
test_set_step(4);
|
test_set_step(4);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty");
|
||||||
chPoolFree(&mp1, &objects[i]);
|
test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
|
||||||
|
test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.5] Emptying the pool using chPoolAlloc() again.*/
|
/* [8.1.5] Emptying the mailbox using chMBFetch(), no errors
|
||||||
|
expected.*/
|
||||||
test_set_step(5);
|
test_set_step(5);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
for (i = 0; i < MB_SIZE; i++) {
|
||||||
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
test_emit_token(msg2);
|
||||||
|
}
|
||||||
|
test_assert_sequence("ABCD", "wrong get sequence");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.6] Now must be empty again.*/
|
/* [8.1.6] Posting and then fetching one more message, no errors
|
||||||
|
expected.*/
|
||||||
test_set_step(6);
|
test_set_step(6);
|
||||||
{
|
{
|
||||||
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.1.7] Covering the case where a provider is unable to return
|
/* [8.1.7] Testing final conditions. Data pointers must be aligned to
|
||||||
more memory.*/
|
buffer start, semaphore counters are checked.*/
|
||||||
test_set_step(7);
|
test_set_step(7);
|
||||||
{
|
{
|
||||||
chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||||
test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
|
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||||
|
test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
||||||
|
test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_008_001 = {
|
static const testcase_t test_008_001 = {
|
||||||
"Loading and emptying a memory pool",
|
"Mailbox normal API, non-blocking tests",
|
||||||
test_008_001_setup,
|
test_008_001_setup,
|
||||||
NULL,
|
test_008_001_teardown,
|
||||||
test_008_001_execute
|
test_008_001_execute
|
||||||
};
|
};
|
||||||
|
|
||||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
|
||||||
/**
|
/**
|
||||||
* @page test_008_002 [8.2] Loading and emptying a guarded memory pool without waiting
|
* @page test_008_002 [8.2] Mailbox I-Class API, non-blocking tests
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The memory pool functionality is tested by loading and emptying it,
|
* The mailbox I-Class API is tested without triggering blocking
|
||||||
* all conditions are tested.
|
* conditions.
|
||||||
*
|
|
||||||
* <h2>Conditions</h2>
|
|
||||||
* This test is only executed if the following preprocessor condition
|
|
||||||
* evaluates to true:
|
|
||||||
* - CH_CFG_USE_SEMAPHORES
|
|
||||||
* .
|
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [8.2.1] Adding the objects to the pool using
|
* - [8.2.1] Testing the mailbox size.
|
||||||
* chGuardedPoolLoadArray().
|
* - [8.2.2] Resetting the mailbox, conditions are checked, no errors
|
||||||
* - [8.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
|
* expected.
|
||||||
* - [8.2.3] Now must be empty.
|
* - [8.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
||||||
* - [8.2.4] Adding the objects to the pool using chGuardedPoolFree().
|
* once, no errors expected.
|
||||||
* - [8.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
|
* - [8.2.4] Testing intermediate conditions. Data pointers must be
|
||||||
* - [8.2.6] Now must be empty again.
|
* aligned, semaphore counters are checked.
|
||||||
|
* - [8.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
||||||
|
* expected.
|
||||||
|
* - [8.2.6] Posting and then fetching one more message, no errors
|
||||||
|
* expected.
|
||||||
|
* - [8.2.7] Testing final conditions. Data pointers must be aligned to
|
||||||
|
* buffer start, semaphore counters are checked.
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_008_002_setup(void) {
|
static void test_008_002_setup(void) {
|
||||||
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_008_002_teardown(void) {
|
||||||
|
chMBReset(&mb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_008_002_execute(void) {
|
static void test_008_002_execute(void) {
|
||||||
|
msg_t msg1, msg2;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
/* [8.2.1] Adding the objects to the pool using
|
/* [8.2.1] Testing the mailbox size.*/
|
||||||
chGuardedPoolLoadArray().*/
|
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
|
/* [8.2.2] Resetting the mailbox, conditions are checked, no errors
|
||||||
|
expected.*/
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
chSysLock();
|
||||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
|
chMBResetI(&mb1);
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||||
|
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||||
|
test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
||||||
|
test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.2.3] Now must be empty.*/
|
/* [8.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
||||||
|
once, no errors expected.*/
|
||||||
test_set_step(3);
|
test_set_step(3);
|
||||||
{
|
{
|
||||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
|
for (i = 0; i < MB_SIZE - 1; i++) {
|
||||||
|
chSysLock();
|
||||||
|
msg1 = chMBPostI(&mb1, 'B' + i);
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
}
|
||||||
|
chSysLock();
|
||||||
|
msg1 = chMBPostAheadI(&mb1, 'A');
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.2.4] Adding the objects to the pool using
|
/* [8.2.4] Testing intermediate conditions. Data pointers must be
|
||||||
chGuardedPoolFree().*/
|
aligned, semaphore counters are checked.*/
|
||||||
test_set_step(4);
|
test_set_step(4);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty");
|
||||||
chGuardedPoolFree(&gmp1, &objects[i]);
|
test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full");
|
||||||
|
test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.2.5] Emptying the pool using chGuardedPoolAllocTimeout()
|
/* [8.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
||||||
again.*/
|
expected.*/
|
||||||
test_set_step(5);
|
test_set_step(5);
|
||||||
{
|
{
|
||||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
for (i = 0; i < MB_SIZE; i++) {
|
||||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
|
chSysLock();
|
||||||
|
msg1 = chMBFetchI(&mb1, &msg2);
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
test_emit_token(msg2);
|
||||||
|
}
|
||||||
|
test_assert_sequence("ABCD", "wrong get sequence");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [8.2.6] Now must be empty again.*/
|
/* [8.2.6] Posting and then fetching one more message, no errors
|
||||||
|
expected.*/
|
||||||
test_set_step(6);
|
test_set_step(6);
|
||||||
{
|
{
|
||||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
|
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [8.2.7] Testing final conditions. Data pointers must be aligned to
|
||||||
|
buffer start, semaphore counters are checked.*/
|
||||||
|
test_set_step(7);
|
||||||
|
{
|
||||||
|
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty");
|
||||||
|
test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full");
|
||||||
|
test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base");
|
||||||
|
test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_008_002 = {
|
static const testcase_t test_008_002 = {
|
||||||
"Loading and emptying a guarded memory pool without waiting",
|
"Mailbox I-Class API, non-blocking tests",
|
||||||
test_008_002_setup,
|
test_008_002_setup,
|
||||||
NULL,
|
test_008_002_teardown,
|
||||||
test_008_002_execute
|
test_008_002_execute
|
||||||
};
|
};
|
||||||
#endif /* CH_CFG_USE_SEMAPHORES */
|
|
||||||
|
|
||||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
|
||||||
/**
|
/**
|
||||||
* @page test_008_003 [8.3] Guarded Memory Pools timeout
|
* @page test_008_003 [8.3] Mailbox timeouts
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The timeout features for the Guarded Memory Pools is tested.
|
* The mailbox API is tested for timeouts.
|
||||||
*
|
|
||||||
* <h2>Conditions</h2>
|
|
||||||
* This test is only executed if the following preprocessor condition
|
|
||||||
* evaluates to true:
|
|
||||||
* - CH_CFG_USE_SEMAPHORES
|
|
||||||
* .
|
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [8.3.1] Trying to allocate with 100mS timeout, must fail because
|
* - [8.3.1] Filling the mailbox.
|
||||||
* the pool is empty.
|
* - [8.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
|
||||||
|
* chMBPostAheadI() timeout.
|
||||||
|
* - [8.3.3] Resetting the mailbox.
|
||||||
|
* - [8.3.4] Testing chMBFetch() and chMBFetchI() timeout.
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_008_003_setup(void) {
|
static void test_008_003_setup(void) {
|
||||||
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_008_003_teardown(void) {
|
||||||
|
chMBReset(&mb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_008_003_execute(void) {
|
static void test_008_003_execute(void) {
|
||||||
|
msg_t msg1, msg2;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
/* [8.3.1] Trying to allocate with 100mS timeout, must fail because
|
/* [8.3.1] Filling the mailbox.*/
|
||||||
the pool is empty.*/
|
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, MS2ST(100)) == NULL, "list not empty");
|
for (i = 0; i < MB_SIZE; i++) {
|
||||||
|
msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE);
|
||||||
|
test_assert(msg1 == MSG_OK, "wrong wake-up message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [8.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
|
||||||
|
chMBPostAheadI() timeout.*/
|
||||||
|
test_set_step(2);
|
||||||
|
{
|
||||||
|
msg1 = chMBPost(&mb1, 'X', 1);
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
|
chSysLock();
|
||||||
|
msg1 = chMBPostI(&mb1, 'X');
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
|
msg1 = chMBPostAhead(&mb1, 'X', 1);
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
|
chSysLock();
|
||||||
|
msg1 = chMBPostAheadI(&mb1, 'X');
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [8.3.3] Resetting the mailbox.*/
|
||||||
|
test_set_step(3);
|
||||||
|
{
|
||||||
|
chMBReset(&mb1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [8.3.4] Testing chMBFetch() and chMBFetchI() timeout.*/
|
||||||
|
test_set_step(4);
|
||||||
|
{
|
||||||
|
msg1 = chMBFetch(&mb1, &msg2, 1);
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
|
chSysLock();
|
||||||
|
msg1 = chMBFetchI(&mb1, &msg2);
|
||||||
|
chSysUnlock();
|
||||||
|
test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_008_003 = {
|
static const testcase_t test_008_003 = {
|
||||||
"Guarded Memory Pools timeout",
|
"Mailbox timeouts",
|
||||||
test_008_003_setup,
|
test_008_003_setup,
|
||||||
NULL,
|
test_008_003_teardown,
|
||||||
test_008_003_execute
|
test_008_003_execute
|
||||||
};
|
};
|
||||||
#endif /* CH_CFG_USE_SEMAPHORES */
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Exported data.
|
* Exported data.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Memory Pools.
|
* @brief Mailboxes.
|
||||||
*/
|
*/
|
||||||
const testcase_t * const test_sequence_008[] = {
|
const testcase_t * const test_sequence_008[] = {
|
||||||
&test_008_001,
|
&test_008_001,
|
||||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
|
||||||
&test_008_002,
|
&test_008_002,
|
||||||
#endif
|
|
||||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
|
||||||
&test_008_003,
|
&test_008_003,
|
||||||
#endif
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CH_CFG_USE_MEMPOOLS */
|
#endif /* CH_CFG_USE_MAILBOXES */
|
||||||
|
|
|
@ -19,252 +19,272 @@
|
||||||
#include "test_root.h"
|
#include "test_root.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_sequence_009 [9] Memory Heaps
|
* @page test_sequence_009 [9] Memory Pools
|
||||||
*
|
*
|
||||||
* File: @ref test_sequence_009.c
|
* File: @ref test_sequence_009.c
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* This sequence tests the ChibiOS/RT functionalities related to memory
|
* This sequence tests the ChibiOS/RT functionalities related to memory
|
||||||
* heaps.
|
* pools.
|
||||||
*
|
*
|
||||||
* <h2>Conditions</h2>
|
* <h2>Conditions</h2>
|
||||||
* This sequence is only executed if the following preprocessor condition
|
* This sequence is only executed if the following preprocessor condition
|
||||||
* evaluates to true:
|
* evaluates to true:
|
||||||
* - CH_CFG_USE_HEAP
|
* - CH_CFG_USE_MEMPOOLS
|
||||||
* .
|
* .
|
||||||
*
|
*
|
||||||
* <h2>Test Cases</h2>
|
* <h2>Test Cases</h2>
|
||||||
* - @subpage test_009_001
|
* - @subpage test_009_001
|
||||||
* - @subpage test_009_002
|
* - @subpage test_009_002
|
||||||
|
* - @subpage test_009_003
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Shared code.
|
* Shared code.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define ALLOC_SIZE 16
|
#define MEMORY_POOL_SIZE 4
|
||||||
#define HEAP_SIZE (ALLOC_SIZE * 8)
|
|
||||||
|
|
||||||
static memory_heap_t test_heap;
|
static uint32_t objects[MEMORY_POOL_SIZE];
|
||||||
static CH_HEAP_AREA(myheap, HEAP_SIZE);
|
static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), NULL);
|
||||||
|
static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t));
|
||||||
|
|
||||||
|
static void *null_provider(size_t size, unsigned align) {
|
||||||
|
|
||||||
|
(void)size;
|
||||||
|
(void)align;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Test cases.
|
* Test cases.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_009_001 [9.1] Allocation and fragmentation
|
* @page test_009_001 [9.1] Loading and emptying a memory pool
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* Series of allocations/deallocations are performed in carefully
|
* The memory pool functionality is tested by loading and emptying it,
|
||||||
* designed sequences in order to stimulate all the possible code paths
|
* all conditions are tested.
|
||||||
* inside the allocator. The test expects to find the heap back to the
|
|
||||||
* initial status after each sequence.
|
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [9.1.1] Testing initial conditions, the heap must not be
|
* - [9.1.1] Adding the objects to the pool using chPoolLoadArray().
|
||||||
* fragmented and one free block present.
|
* - [9.1.2] Emptying the pool using chPoolAlloc().
|
||||||
* - [9.1.2] Trying to allocate an block bigger than available space,
|
* - [9.1.3] Now must be empty.
|
||||||
* an error is expected.
|
* - [9.1.4] Adding the objects to the pool using chPoolFree().
|
||||||
* - [9.1.3] Single block allocation using chHeapAlloc() then the block
|
* - [9.1.5] Emptying the pool using chPoolAlloc() again.
|
||||||
* is freed using chHeapFree(), must not fail.
|
* - [9.1.6] Now must be empty again.
|
||||||
* - [9.1.4] Using chHeapStatus() to assess the heap state. There must
|
* - [9.1.7] Covering the case where a provider is unable to return
|
||||||
* be at least one free block of sufficient size.
|
* more memory.
|
||||||
* - [9.1.5] Allocating then freeing in the same order.
|
|
||||||
* - [9.1.6] Allocating then freeing in reverse order.
|
|
||||||
* - [9.1.7] Small fragments handling. Checking the behavior when
|
|
||||||
* allocating blocks with size not multiple of alignment unit.
|
|
||||||
* - [9.1.8] Skipping a fragment, the first fragment in the list is too
|
|
||||||
* small so the allocator must pick the second one.
|
|
||||||
* - [9.1.9] Allocating the whole available space.
|
|
||||||
* - [9.1.10] Testing final conditions. The heap geometry must be the
|
|
||||||
* same than the one registered at beginning.
|
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_009_001_setup(void) {
|
static void test_009_001_setup(void) {
|
||||||
chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
|
chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_009_001_execute(void) {
|
static void test_009_001_execute(void) {
|
||||||
void *p1, *p2, *p3;
|
unsigned i;
|
||||||
size_t n, sz;
|
|
||||||
|
|
||||||
/* [9.1.1] Testing initial conditions, the heap must not be
|
/* [9.1.1] Adding the objects to the pool using chPoolLoadArray().*/
|
||||||
fragmented and one free block present.*/
|
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
|
chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.2] Trying to allocate an block bigger than available space,
|
/* [9.1.2] Emptying the pool using chPoolAlloc().*/
|
||||||
an error is expected.*/
|
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2);
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
test_assert(p1 == NULL, "allocation not failed");
|
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.3] Single block allocation using chHeapAlloc() then the block
|
/* [9.1.3] Now must be empty.*/
|
||||||
is freed using chHeapFree(), must not fail.*/
|
|
||||||
test_set_step(3);
|
test_set_step(3);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||||
test_assert(p1 != NULL, "allocation failed");
|
|
||||||
chHeapFree(p1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.4] Using chHeapStatus() to assess the heap state. There must
|
/* [9.1.4] Adding the objects to the pool using chPoolFree().*/
|
||||||
be at least one free block of sufficient size.*/
|
|
||||||
test_set_step(4);
|
test_set_step(4);
|
||||||
{
|
{
|
||||||
size_t total_size, largest_size;
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
|
chPoolFree(&mp1, &objects[i]);
|
||||||
n = chHeapStatus(&test_heap, &total_size, &largest_size);
|
|
||||||
test_assert(n == 1, "missing free block");
|
|
||||||
test_assert(total_size >= ALLOC_SIZE, "unexpected heap state");
|
|
||||||
test_assert(total_size == largest_size, "unexpected heap state");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.5] Allocating then freeing in the same order.*/
|
/* [9.1.5] Emptying the pool using chPoolAlloc() again.*/
|
||||||
test_set_step(5);
|
test_set_step(5);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
||||||
p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
chHeapFree(p1); /* Does not merge.*/
|
|
||||||
chHeapFree(p2); /* Merges backward.*/
|
|
||||||
chHeapFree(p3); /* Merges both sides.*/
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.6] Allocating then freeing in reverse order.*/
|
/* [9.1.6] Now must be empty again.*/
|
||||||
test_set_step(6);
|
test_set_step(6);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||||
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
chHeapFree(p3); /* Merges forward.*/
|
|
||||||
chHeapFree(p2); /* Merges forward.*/
|
|
||||||
chHeapFree(p1); /* Merges forward.*/
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.1.7] Small fragments handling. Checking the behavior when
|
/* [9.1.7] Covering the case where a provider is unable to return
|
||||||
allocating blocks with size not multiple of alignment unit.*/
|
more memory.*/
|
||||||
test_set_step(7);
|
test_set_step(7);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1);
|
chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
|
||||||
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
|
||||||
chHeapFree(p1);
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
|
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
/* Note, the first situation happens when the alignment size is smaller
|
|
||||||
than the header size, the second in the other cases.*/
|
|
||||||
test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) ||
|
|
||||||
(chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented");
|
|
||||||
chHeapFree(p2);
|
|
||||||
chHeapFree(p1);
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [9.1.8] Skipping a fragment, the first fragment in the list is too
|
|
||||||
small so the allocator must pick the second one.*/
|
|
||||||
test_set_step(8);
|
|
||||||
{
|
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
chHeapFree(p1);
|
|
||||||
test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
|
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/
|
|
||||||
chHeapFree(p1);
|
|
||||||
chHeapFree(p2);
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [9.1.9] Allocating the whole available space.*/
|
|
||||||
test_set_step(9);
|
|
||||||
{
|
|
||||||
(void)chHeapStatus(&test_heap, &n, NULL);
|
|
||||||
p1 = chHeapAlloc(&test_heap, n);
|
|
||||||
test_assert(p1 != NULL, "allocation failed");
|
|
||||||
test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty");
|
|
||||||
chHeapFree(p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [9.1.10] Testing final conditions. The heap geometry must be the
|
|
||||||
same than the one registered at beginning.*/
|
|
||||||
test_set_step(10);
|
|
||||||
{
|
|
||||||
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
|
||||||
test_assert(n == sz, "size changed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_009_001 = {
|
static const testcase_t test_009_001 = {
|
||||||
"Allocation and fragmentation",
|
"Loading and emptying a memory pool",
|
||||||
test_009_001_setup,
|
test_009_001_setup,
|
||||||
NULL,
|
NULL,
|
||||||
test_009_001_execute
|
test_009_001_execute
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @page test_009_002 [9.2] Default Heap
|
* @page test_009_002 [9.2] Loading and emptying a guarded memory pool without waiting
|
||||||
*
|
*
|
||||||
* <h2>Description</h2>
|
* <h2>Description</h2>
|
||||||
* The default heap is pre-allocated in the system. We test base
|
* The memory pool functionality is tested by loading and emptying it,
|
||||||
* functionality.
|
* all conditions are tested.
|
||||||
|
*
|
||||||
|
* <h2>Conditions</h2>
|
||||||
|
* This test is only executed if the following preprocessor condition
|
||||||
|
* evaluates to true:
|
||||||
|
* - CH_CFG_USE_SEMAPHORES
|
||||||
|
* .
|
||||||
*
|
*
|
||||||
* <h2>Test Steps</h2>
|
* <h2>Test Steps</h2>
|
||||||
* - [9.2.1] Single block allocation using chHeapAlloc() then the block
|
* - [9.2.1] Adding the objects to the pool using
|
||||||
* is freed using chHeapFree(), must not fail.
|
* chGuardedPoolLoadArray().
|
||||||
* - [9.2.2] Testing allocation failure.
|
* - [9.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
|
||||||
|
* - [9.2.3] Now must be empty.
|
||||||
|
* - [9.2.4] Adding the objects to the pool using chGuardedPoolFree().
|
||||||
|
* - [9.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
|
||||||
|
* - [9.2.6] Now must be empty again.
|
||||||
* .
|
* .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_009_002_execute(void) {
|
static void test_009_002_setup(void) {
|
||||||
void *p1;
|
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
||||||
size_t total_size, largest_size;
|
}
|
||||||
|
|
||||||
/* [9.2.1] Single block allocation using chHeapAlloc() then the block
|
static void test_009_002_execute(void) {
|
||||||
is freed using chHeapFree(), must not fail.*/
|
unsigned i;
|
||||||
|
|
||||||
|
/* [9.2.1] Adding the objects to the pool using
|
||||||
|
chGuardedPoolLoadArray().*/
|
||||||
test_set_step(1);
|
test_set_step(1);
|
||||||
{
|
{
|
||||||
(void)chHeapStatus(NULL, &total_size, &largest_size);
|
chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
|
||||||
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
|
||||||
test_assert(p1 != NULL, "allocation failed");
|
|
||||||
chHeapFree(p1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [9.2.2] Testing allocation failure.*/
|
/* [9.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
|
||||||
test_set_step(2);
|
test_set_step(2);
|
||||||
{
|
{
|
||||||
p1 = chHeapAlloc(NULL, (size_t)-256);
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
test_assert(p1 == NULL, "allocation not failed");
|
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [9.2.3] Now must be empty.*/
|
||||||
|
test_set_step(3);
|
||||||
|
{
|
||||||
|
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [9.2.4] Adding the objects to the pool using
|
||||||
|
chGuardedPoolFree().*/
|
||||||
|
test_set_step(4);
|
||||||
|
{
|
||||||
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
|
chGuardedPoolFree(&gmp1, &objects[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [9.2.5] Emptying the pool using chGuardedPoolAllocTimeout()
|
||||||
|
again.*/
|
||||||
|
test_set_step(5);
|
||||||
|
{
|
||||||
|
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||||
|
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [9.2.6] Now must be empty again.*/
|
||||||
|
test_set_step(6);
|
||||||
|
{
|
||||||
|
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const testcase_t test_009_002 = {
|
static const testcase_t test_009_002 = {
|
||||||
"Default Heap",
|
"Loading and emptying a guarded memory pool without waiting",
|
||||||
NULL,
|
test_009_002_setup,
|
||||||
NULL,
|
NULL,
|
||||||
test_009_002_execute
|
test_009_002_execute
|
||||||
};
|
};
|
||||||
|
#endif /* CH_CFG_USE_SEMAPHORES */
|
||||||
|
|
||||||
|
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @page test_009_003 [9.3] Guarded Memory Pools timeout
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* The timeout features for the Guarded Memory Pools is tested.
|
||||||
|
*
|
||||||
|
* <h2>Conditions</h2>
|
||||||
|
* This test is only executed if the following preprocessor condition
|
||||||
|
* evaluates to true:
|
||||||
|
* - CH_CFG_USE_SEMAPHORES
|
||||||
|
* .
|
||||||
|
*
|
||||||
|
* <h2>Test Steps</h2>
|
||||||
|
* - [9.3.1] Trying to allocate with 100mS timeout, must fail because
|
||||||
|
* the pool is empty.
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_009_003_setup(void) {
|
||||||
|
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_009_003_execute(void) {
|
||||||
|
|
||||||
|
/* [9.3.1] Trying to allocate with 100mS timeout, must fail because
|
||||||
|
the pool is empty.*/
|
||||||
|
test_set_step(1);
|
||||||
|
{
|
||||||
|
test_assert(chGuardedPoolAllocTimeout(&gmp1, MS2ST(100)) == NULL, "list not empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const testcase_t test_009_003 = {
|
||||||
|
"Guarded Memory Pools timeout",
|
||||||
|
test_009_003_setup,
|
||||||
|
NULL,
|
||||||
|
test_009_003_execute
|
||||||
|
};
|
||||||
|
#endif /* CH_CFG_USE_SEMAPHORES */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Exported data.
|
* Exported data.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Memory Heaps.
|
* @brief Memory Pools.
|
||||||
*/
|
*/
|
||||||
const testcase_t * const test_sequence_009[] = {
|
const testcase_t * const test_sequence_009[] = {
|
||||||
&test_009_001,
|
&test_009_001,
|
||||||
|
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||||
&test_009_002,
|
&test_009_002,
|
||||||
|
#endif
|
||||||
|
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||||
|
&test_009_003,
|
||||||
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CH_CFG_USE_HEAP */
|
#endif /* CH_CFG_USE_MEMPOOLS */
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hal.h"
|
||||||
|
#include "ch_test.h"
|
||||||
|
#include "test_root.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page test_sequence_010 [10] Memory Heaps
|
||||||
|
*
|
||||||
|
* File: @ref test_sequence_010.c
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* This sequence tests the ChibiOS/RT functionalities related to memory
|
||||||
|
* heaps.
|
||||||
|
*
|
||||||
|
* <h2>Conditions</h2>
|
||||||
|
* This sequence is only executed if the following preprocessor condition
|
||||||
|
* evaluates to true:
|
||||||
|
* - CH_CFG_USE_HEAP
|
||||||
|
* .
|
||||||
|
*
|
||||||
|
* <h2>Test Cases</h2>
|
||||||
|
* - @subpage test_010_001
|
||||||
|
* - @subpage test_010_002
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Shared code.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define ALLOC_SIZE 16
|
||||||
|
#define HEAP_SIZE (ALLOC_SIZE * 8)
|
||||||
|
|
||||||
|
static memory_heap_t test_heap;
|
||||||
|
static CH_HEAP_AREA(myheap, HEAP_SIZE);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Test cases.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page test_010_001 [10.1] Allocation and fragmentation
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* Series of allocations/deallocations are performed in carefully
|
||||||
|
* designed sequences in order to stimulate all the possible code paths
|
||||||
|
* inside the allocator. The test expects to find the heap back to the
|
||||||
|
* initial status after each sequence.
|
||||||
|
*
|
||||||
|
* <h2>Test Steps</h2>
|
||||||
|
* - [10.1.1] Testing initial conditions, the heap must not be
|
||||||
|
* fragmented and one free block present.
|
||||||
|
* - [10.1.2] Trying to allocate an block bigger than available space,
|
||||||
|
* an error is expected.
|
||||||
|
* - [10.1.3] Single block allocation using chHeapAlloc() then the
|
||||||
|
* block is freed using chHeapFree(), must not fail.
|
||||||
|
* - [10.1.4] Using chHeapStatus() to assess the heap state. There must
|
||||||
|
* be at least one free block of sufficient size.
|
||||||
|
* - [10.1.5] Allocating then freeing in the same order.
|
||||||
|
* - [10.1.6] Allocating then freeing in reverse order.
|
||||||
|
* - [10.1.7] Small fragments handling. Checking the behavior when
|
||||||
|
* allocating blocks with size not multiple of alignment unit.
|
||||||
|
* - [10.1.8] Skipping a fragment, the first fragment in the list is
|
||||||
|
* too small so the allocator must pick the second one.
|
||||||
|
* - [10.1.9] Allocating the whole available space.
|
||||||
|
* - [10.1.10] Testing final conditions. The heap geometry must be the
|
||||||
|
* same than the one registered at beginning.
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_010_001_setup(void) {
|
||||||
|
chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_010_001_execute(void) {
|
||||||
|
void *p1, *p2, *p3;
|
||||||
|
size_t n, sz;
|
||||||
|
|
||||||
|
/* [10.1.1] Testing initial conditions, the heap must not be
|
||||||
|
fragmented and one free block present.*/
|
||||||
|
test_set_step(1);
|
||||||
|
{
|
||||||
|
test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.2] Trying to allocate an block bigger than available space,
|
||||||
|
an error is expected.*/
|
||||||
|
test_set_step(2);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2);
|
||||||
|
test_assert(p1 == NULL, "allocation not failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.3] Single block allocation using chHeapAlloc() then the
|
||||||
|
block is freed using chHeapFree(), must not fail.*/
|
||||||
|
test_set_step(3);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
test_assert(p1 != NULL, "allocation failed");
|
||||||
|
chHeapFree(p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.4] Using chHeapStatus() to assess the heap state. There must
|
||||||
|
be at least one free block of sufficient size.*/
|
||||||
|
test_set_step(4);
|
||||||
|
{
|
||||||
|
size_t total_size, largest_size;
|
||||||
|
|
||||||
|
n = chHeapStatus(&test_heap, &total_size, &largest_size);
|
||||||
|
test_assert(n == 1, "missing free block");
|
||||||
|
test_assert(total_size >= ALLOC_SIZE, "unexpected heap state");
|
||||||
|
test_assert(total_size == largest_size, "unexpected heap state");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.5] Allocating then freeing in the same order.*/
|
||||||
|
test_set_step(5);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
chHeapFree(p1); /* Does not merge.*/
|
||||||
|
chHeapFree(p2); /* Merges backward.*/
|
||||||
|
chHeapFree(p3); /* Merges both sides.*/
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.6] Allocating then freeing in reverse order.*/
|
||||||
|
test_set_step(6);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
chHeapFree(p3); /* Merges forward.*/
|
||||||
|
chHeapFree(p2); /* Merges forward.*/
|
||||||
|
chHeapFree(p1); /* Merges forward.*/
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.7] Small fragments handling. Checking the behavior when
|
||||||
|
allocating blocks with size not multiple of alignment unit.*/
|
||||||
|
test_set_step(7);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1);
|
||||||
|
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
chHeapFree(p1);
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
/* Note, the first situation happens when the alignment size is smaller
|
||||||
|
than the header size, the second in the other cases.*/
|
||||||
|
test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) ||
|
||||||
|
(chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented");
|
||||||
|
chHeapFree(p2);
|
||||||
|
chHeapFree(p1);
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.8] Skipping a fragment, the first fragment in the list is
|
||||||
|
too small so the allocator must pick the second one.*/
|
||||||
|
test_set_step(8);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
chHeapFree(p1);
|
||||||
|
test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/
|
||||||
|
chHeapFree(p1);
|
||||||
|
chHeapFree(p2);
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.9] Allocating the whole available space.*/
|
||||||
|
test_set_step(9);
|
||||||
|
{
|
||||||
|
(void)chHeapStatus(&test_heap, &n, NULL);
|
||||||
|
p1 = chHeapAlloc(&test_heap, n);
|
||||||
|
test_assert(p1 != NULL, "allocation failed");
|
||||||
|
test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty");
|
||||||
|
chHeapFree(p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.1.10] Testing final conditions. The heap geometry must be the
|
||||||
|
same than the one registered at beginning.*/
|
||||||
|
test_set_step(10);
|
||||||
|
{
|
||||||
|
test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
|
||||||
|
test_assert(n == sz, "size changed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const testcase_t test_010_001 = {
|
||||||
|
"Allocation and fragmentation",
|
||||||
|
test_010_001_setup,
|
||||||
|
NULL,
|
||||||
|
test_010_001_execute
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page test_010_002 [10.2] Default Heap
|
||||||
|
*
|
||||||
|
* <h2>Description</h2>
|
||||||
|
* The default heap is pre-allocated in the system. We test base
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* <h2>Test Steps</h2>
|
||||||
|
* - [10.2.1] Single block allocation using chHeapAlloc() then the
|
||||||
|
* block is freed using chHeapFree(), must not fail.
|
||||||
|
* - [10.2.2] Testing allocation failure.
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_010_002_execute(void) {
|
||||||
|
void *p1;
|
||||||
|
size_t total_size, largest_size;
|
||||||
|
|
||||||
|
/* [10.2.1] Single block allocation using chHeapAlloc() then the
|
||||||
|
block is freed using chHeapFree(), must not fail.*/
|
||||||
|
test_set_step(1);
|
||||||
|
{
|
||||||
|
(void)chHeapStatus(NULL, &total_size, &largest_size);
|
||||||
|
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
|
||||||
|
test_assert(p1 != NULL, "allocation failed");
|
||||||
|
chHeapFree(p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [10.2.2] Testing allocation failure.*/
|
||||||
|
test_set_step(2);
|
||||||
|
{
|
||||||
|
p1 = chHeapAlloc(NULL, (size_t)-256);
|
||||||
|
test_assert(p1 == NULL, "allocation not failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const testcase_t test_010_002 = {
|
||||||
|
"Default Heap",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
test_010_002_execute
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Exported data.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Memory Heaps.
|
||||||
|
*/
|
||||||
|
const testcase_t * const test_sequence_010[] = {
|
||||||
|
&test_010_001,
|
||||||
|
&test_010_002,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CH_CFG_USE_HEAP */
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const testcase_t * const test_sequence_010[];
|
|
@ -9,7 +9,8 @@ TESTSRC = ${CHIBIOS}/test/lib/ch_test.c \
|
||||||
${CHIBIOS}/test/rt/source/test/test_sequence_006.c \
|
${CHIBIOS}/test/rt/source/test/test_sequence_006.c \
|
||||||
${CHIBIOS}/test/rt/source/test/test_sequence_007.c \
|
${CHIBIOS}/test/rt/source/test/test_sequence_007.c \
|
||||||
${CHIBIOS}/test/rt/source/test/test_sequence_008.c \
|
${CHIBIOS}/test/rt/source/test/test_sequence_008.c \
|
||||||
${CHIBIOS}/test/rt/source/test/test_sequence_009.c
|
${CHIBIOS}/test/rt/source/test/test_sequence_009.c \
|
||||||
|
${CHIBIOS}/test/rt/source/test/test_sequence_010.c
|
||||||
|
|
||||||
# Required include directories
|
# Required include directories
|
||||||
TESTINC = ${CHIBIOS}/test/lib \
|
TESTINC = ${CHIBIOS}/test/lib \
|
||||||
|
|
Loading…
Reference in New Issue