git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@323 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
a108008263
commit
300ecfe103
|
@ -70,7 +70,9 @@ ASRC = ../../ports/ARM7-LPC214x/chcore.c \
|
|||
../../src/chschd.c ../../src/chthreads.c ../../src/chsem.c ../../src/chmtx.c \
|
||||
../../src/chevents.c ../../src/chmsg.c ../../src/chsleep.c ../../src/chqueues.c \
|
||||
../../src/chserial.c \
|
||||
../../src/lib/evtimer.c ../../test/test.c \
|
||||
../../src/lib/evtimer.c \
|
||||
../../test/test.c ../../test/testrdy.c ../../test/testsem.c \
|
||||
../../test/testmtx.c ../../test/testmsg.c \
|
||||
board.c buzzer.c mmcsd.c main.c
|
||||
|
||||
# List THUMB-mode C sources here
|
||||
|
|
|
@ -75,6 +75,12 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
|
|||
*****************************************************************************
|
||||
|
||||
*** 0.6.6 ***
|
||||
- NEW: Improved test suite, now the suite is divided in modules and the code
|
||||
is much easier to understand. The new framework simplifies the inclusion of
|
||||
new test cases and makes possible to verify the exact sequence and the
|
||||
timing of test events.
|
||||
- NEW: New API chSysInTimeWindow() that checks if the current system time is
|
||||
within the specified time window.
|
||||
- FIX: Fixed a problem in the STM32 port USART1 driver.
|
||||
- Added the definitions for packed structures to the chtypes.h files.
|
||||
- Fixed a problem in the MMC/SD driver in the LPC2148 demo.
|
||||
|
|
|
@ -39,4 +39,18 @@ void chThdSleep(systime_t time) {
|
|||
}
|
||||
#endif /* CH_USE_SLEEP */
|
||||
|
||||
#ifdef CH_USE_SYSTEMTIME
|
||||
/**
|
||||
* Checks if the current system time is within the specified time window.
|
||||
* @param start the start of the time window (inclusive)
|
||||
* @param end the end of the time window (non inclusive)
|
||||
*/
|
||||
bool_t chSysInTimeWindow(systime_t start, systime_t end) {
|
||||
|
||||
systime_t time = chSysGetTime();
|
||||
return end >= start ? (time >= start) && (time < end) :
|
||||
(time >= start) || (time < end);
|
||||
}
|
||||
#endif /* CH_USE_SYSTEMTIME */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -31,6 +31,9 @@ extern "C" {
|
|||
#ifdef CH_USE_SLEEP
|
||||
void chThdSleep(systime_t time);
|
||||
#endif /* CH_USE_SLEEP */
|
||||
#ifdef CH_USE_SYSTEMTIME
|
||||
bool_t chSysInTimeWindow(systime_t start, systime_t end);
|
||||
#endif /* CH_USE_SYSTEMTIME */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
651
test/test.c
651
test/test.c
|
@ -19,39 +19,46 @@
|
|||
|
||||
#include <ch.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
void ChkIntSources(void);
|
||||
#endif
|
||||
#include "test.h"
|
||||
#include "testrdy.h"
|
||||
#include "testsem.h"
|
||||
#include "testmtx.h"
|
||||
#include "testmsg.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
WorkingArea(wsT1, 512);
|
||||
WorkingArea(wsT2, 512);
|
||||
WorkingArea(wsT3, 512);
|
||||
WorkingArea(wsT4, 512);
|
||||
WorkingArea(wsT5, 512);
|
||||
#else
|
||||
WorkingArea(wsT1, 128);
|
||||
WorkingArea(wsT2, 128);
|
||||
WorkingArea(wsT3, 128);
|
||||
WorkingArea(wsT4, 128);
|
||||
WorkingArea(wsT5, 128);
|
||||
#endif
|
||||
static Thread *t1, *t2, *t3, *t4, *t5;
|
||||
/*
|
||||
* Array of all the test cases.
|
||||
*/
|
||||
static const struct testcase *tests[] = {
|
||||
&testrdy1,
|
||||
&testrdy2,
|
||||
&testsem1,
|
||||
&testsem2,
|
||||
&testmtx1,
|
||||
&testmtx2,
|
||||
&testmtx3,
|
||||
&testmsg1,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool_t local_fail, global_fail;
|
||||
static char *failmsg;
|
||||
static char tokens_buffer[MAX_TOKENS];
|
||||
static char *tokp;
|
||||
static WorkingArea(waT0, THREADS_STACK_SIZE);
|
||||
static WorkingArea(waT1, THREADS_STACK_SIZE);
|
||||
static WorkingArea(waT2, THREADS_STACK_SIZE);
|
||||
static WorkingArea(waT3, THREADS_STACK_SIZE);
|
||||
static WorkingArea(waT4, THREADS_STACK_SIZE);
|
||||
|
||||
void *wa[MAX_THREADS] = {waT0, waT1, waT2, waT3, waT4};
|
||||
Thread *threads[MAX_THREADS];
|
||||
|
||||
/*
|
||||
* Console output.
|
||||
*/
|
||||
static FullDuplexDriver *comp;
|
||||
static Semaphore sem1;
|
||||
static Mutex m1, m2;
|
||||
|
||||
static void wait(void) {
|
||||
|
||||
chThdWait(t1);
|
||||
chThdWait(t2);
|
||||
chThdWait(t3);
|
||||
chThdWait(t4);
|
||||
chThdWait(t5);
|
||||
}
|
||||
|
||||
static void printn(uint32_t n) {
|
||||
void test_printn(uint32_t n) {
|
||||
char buf[16], *p;
|
||||
|
||||
if (!n)
|
||||
|
@ -65,506 +72,154 @@ static void printn(uint32_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
static void print(char *msgp) {
|
||||
void test_print(char *msgp) {
|
||||
|
||||
while (*msgp)
|
||||
chFDDPut(comp, *msgp++);
|
||||
}
|
||||
|
||||
static void println(char *msgp) {
|
||||
void test_println(char *msgp) {
|
||||
|
||||
print(msgp);
|
||||
test_print(msgp);
|
||||
chFDDPut(comp, '\r');
|
||||
chFDDPut(comp, '\n');
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void CPU(systime_t ms) {
|
||||
/*
|
||||
* Tokens.
|
||||
*/
|
||||
static void clear_tokens(void) {
|
||||
|
||||
systime_t time = chSysGetTime() + ms;
|
||||
while (chSysGetTime() != time) {
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
tokp = tokens_buffer;
|
||||
}
|
||||
|
||||
static void print_tokens(void) {
|
||||
char *cp = tokens_buffer;
|
||||
|
||||
while (cp < tokp)
|
||||
chFDDPut(comp, *cp++);
|
||||
}
|
||||
|
||||
void test_emit_token(char token) {
|
||||
|
||||
chSysLock();
|
||||
*tokp++ = token;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Assertions.
|
||||
*/
|
||||
void test_fail(char * msg) {
|
||||
|
||||
local_fail = TRUE;
|
||||
global_fail = TRUE;
|
||||
failmsg = msg;
|
||||
}
|
||||
|
||||
void test_assert(bool_t condition, char * msg) {
|
||||
|
||||
if (!condition)
|
||||
test_fail(msg);
|
||||
}
|
||||
|
||||
void test_assert_sequence(char *expected) {
|
||||
char *cp = tokens_buffer;
|
||||
while (cp < tokp) {
|
||||
if (*cp++ != *expected++)
|
||||
test_fail(NULL);
|
||||
}
|
||||
if (*expected)
|
||||
test_fail(NULL);
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
systime_t wait_tick(void) {
|
||||
void test_assert_time_window(systime_t start, systime_t end) {
|
||||
|
||||
systime_t time = chSysGetTime() + 1;
|
||||
while (chSysGetTime() < time) {
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
return time;
|
||||
test_assert(chSysInTimeWindow(start, end), "time window error");
|
||||
}
|
||||
|
||||
msg_t Thread1(void *p) {
|
||||
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread2(void *p) {
|
||||
|
||||
chSemWait(&sem1);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread3(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread4(void *p) {
|
||||
msg_t msg;
|
||||
/*
|
||||
* Threads utils.
|
||||
*/
|
||||
void test_wait_threads(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
msg = chMsgSend(p, 'A' + i);
|
||||
chFDDPut(comp, msg);
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
if (threads[i])
|
||||
chThdWait(threads[i]);
|
||||
}
|
||||
|
||||
void test_cpu_pulse(systime_t ms) {
|
||||
|
||||
systime_t start = chSysGetTime();
|
||||
while (chSysInTimeWindow(start, start + ms)) {
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
chMsgSend(p, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread6(void *p) {
|
||||
|
||||
while (!chThdShouldTerminate())
|
||||
chMsgRelease(chMsgWait());
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread7(void *p) {
|
||||
|
||||
return (msg_t)NULL;
|
||||
}
|
||||
|
||||
void testrdy1(void) {
|
||||
|
||||
println("*** Ready List, priority enqueuing test #1, you should read ABCDE:");
|
||||
t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread1, "E");
|
||||
t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread1, "D");
|
||||
t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread1, "C");
|
||||
t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread1, "B");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread1, "A");
|
||||
wait();
|
||||
println("");
|
||||
}
|
||||
|
||||
void testrdy2(void) {
|
||||
|
||||
println("*** Ready List, priority enqueuing test #2, you should read ABCDE:");
|
||||
t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread1, "D");
|
||||
t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread1, "E");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread1, "A");
|
||||
t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread1, "B");
|
||||
t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread1, "C");
|
||||
wait();
|
||||
println("");
|
||||
}
|
||||
|
||||
void testsem1(void) {
|
||||
|
||||
println("*** Semaphores, FIFO enqueuing test, you should read ABCDE:");
|
||||
chSemInit(&sem1, 0);
|
||||
t1 = chThdCreate(chThdGetPriority()+5, 0, wsT1, sizeof(wsT1), Thread2, "A");
|
||||
t2 = chThdCreate(chThdGetPriority()+1, 0, wsT2, sizeof(wsT2), Thread2, "B");
|
||||
t3 = chThdCreate(chThdGetPriority()+3, 0, wsT3, sizeof(wsT3), Thread2, "C");
|
||||
t4 = chThdCreate(chThdGetPriority()+4, 0, wsT4, sizeof(wsT4), Thread2, "D");
|
||||
t5 = chThdCreate(chThdGetPriority()+2, 0, wsT5, sizeof(wsT5), Thread2, "E");
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
wait();
|
||||
println("");
|
||||
}
|
||||
|
||||
void testsem2(void) {
|
||||
unsigned int i;
|
||||
|
||||
println("*** Semaphores, timeout test, you should read ABCDE (slowly):");
|
||||
chSemInit(&sem1, 0);
|
||||
for (i = 0; i < 5; i++) {
|
||||
chFDDPut(comp, 'A' + i);
|
||||
chSemWaitTimeout(&sem1, 500);
|
||||
}
|
||||
println("");
|
||||
}
|
||||
|
||||
void testmtx1(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
println("*** Mutexes, priority enqueuing test, you should read ABCDE:");
|
||||
chMtxLock(&m1);
|
||||
t5 = chThdCreate(chThdGetPriority()+1, 0, wsT5, sizeof(wsT5), Thread3, "E");
|
||||
t4 = chThdCreate(chThdGetPriority()+3, 0, wsT4, sizeof(wsT4), Thread3, "D");
|
||||
t3 = chThdCreate(chThdGetPriority()+3, 0, wsT3, sizeof(wsT3), Thread3, "C");
|
||||
t2 = chThdCreate(chThdGetPriority()+4, 0, wsT2, sizeof(wsT2), Thread3, "B");
|
||||
t1 = chThdCreate(chThdGetPriority()+5, 0, wsT1, sizeof(wsT1), Thread3, "A");
|
||||
chMtxUnlock();
|
||||
wait();
|
||||
println("");
|
||||
}
|
||||
|
||||
msg_t Thread8(void *p) {
|
||||
|
||||
chThdSleep(5);
|
||||
chMtxLock(&m1);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread9(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
chThdSleep(20);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread10(void *p) {
|
||||
|
||||
chThdSleep(10);
|
||||
CPU(50);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread11(void *p) {
|
||||
|
||||
chThdSleep(5);
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread12(void *p) {
|
||||
|
||||
chSemWait(&sem1);
|
||||
chThdSleep(20);
|
||||
chSemSignal(&sem1);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Time
|
||||
* 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
|
||||
* 1 .....................++--------------------------------------------------
|
||||
* 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
|
||||
* Test suite execution.
|
||||
*/
|
||||
void testmtx2(void) {
|
||||
static void execute_test(const struct testcase *tcp) {
|
||||
int i;
|
||||
|
||||
chMtxInit(&m1);
|
||||
println("*** Mutexes, mutex with inheritance (simple case), you should read ABC:");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread8, "A");
|
||||
t2 = chThdCreate(chThdGetPriority()-3, 0, wsT2, sizeof(wsT2), Thread9, "C");
|
||||
t3 = chThdCreate(chThdGetPriority()-2, 0, wsT3, sizeof(wsT3), Thread10, "B");
|
||||
chThdWait(t1);
|
||||
chThdWait(t2);
|
||||
chThdWait(t3);
|
||||
println("");
|
||||
/* Initialization */
|
||||
clear_tokens();
|
||||
local_fail = FALSE;
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
threads[i] = NULL;
|
||||
|
||||
tcp->setup();
|
||||
tcp->execute();
|
||||
tcp->teardown();
|
||||
}
|
||||
|
||||
void testmtx3(void) {
|
||||
|
||||
chSemInit(&sem1, 1);
|
||||
println("*** Mutexes, mutex without inheritance, inversion happens, you should read BAC:");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread11, "A");
|
||||
t2 = chThdCreate(chThdGetPriority()-3, 0, wsT2, sizeof(wsT2), Thread12, "C");
|
||||
t3 = chThdCreate(chThdGetPriority()-2, 0, wsT3, sizeof(wsT3), Thread10, "B");
|
||||
chThdWait(t1);
|
||||
chThdWait(t2);
|
||||
chThdWait(t3);
|
||||
println("");
|
||||
}
|
||||
|
||||
msg_t Thread13(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
CPU(50);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread14(void *p) {
|
||||
|
||||
chThdSleep(10);
|
||||
chMtxLock(&m2);
|
||||
CPU(20);
|
||||
chMtxLock(&m1);
|
||||
CPU(50);
|
||||
chMtxUnlock();
|
||||
CPU(20);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread15(void *p) {
|
||||
|
||||
chThdSleep(20);
|
||||
chMtxLock(&m2);
|
||||
CPU(50);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread16(void *p) {
|
||||
|
||||
chThdSleep(40);
|
||||
CPU(200);
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t Thread17(void *p) {
|
||||
|
||||
chThdSleep(50);
|
||||
chMtxLock(&m2);
|
||||
CPU(50);
|
||||
chMtxUnlock();
|
||||
chFDDPut(comp, *(uint8_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Time 0 10 20 30 40 50
|
||||
* 0 +++BL++------------------2++++------4+++++BU0--------------------------
|
||||
* 1 .......++AL++--2+++++++++BL.........4.....++++++++BU4++++AU1-----------
|
||||
* 2 .............++AL............................................------++AU
|
||||
* 3 ..............................++++-------------------------------++....
|
||||
* 4 ..................................++AL...................++++AU++......
|
||||
*/
|
||||
void testmtx4(void) {
|
||||
|
||||
chMtxInit(&m1); /* B */
|
||||
chMtxInit(&m2); /* A */
|
||||
println("*** Mutexes, mutex with inheritance (complex case), you should read ABCDE:");
|
||||
t1 = chThdCreate(chThdGetPriority()-5, 0, wsT1, sizeof(wsT1), Thread13, "E");
|
||||
t2 = chThdCreate(chThdGetPriority()-4, 0, wsT2, sizeof(wsT2), Thread14, "D");
|
||||
t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread15, "C");
|
||||
t4 = chThdCreate(chThdGetPriority()-2, 0, wsT4, sizeof(wsT4), Thread16, "B");
|
||||
t5 = chThdCreate(chThdGetPriority()-1, 0, wsT5, sizeof(wsT5), Thread17, "A");
|
||||
wait();
|
||||
println("");
|
||||
}
|
||||
|
||||
void testmsg1(void) {
|
||||
msg_t msg;
|
||||
|
||||
println("*** Messages, dispatch test, you should read AABBCCDDEE:");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread4, chThdSelf());
|
||||
do {
|
||||
chMsgRelease(msg = chMsgWait());
|
||||
if (msg)
|
||||
chFDDPut(comp, msg);
|
||||
} while (msg);
|
||||
chThdWait(t1);
|
||||
println("");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
unsigned int msg_loop_test(Thread *tp) {
|
||||
uint32_t i;
|
||||
|
||||
systime_t time = wait_tick() + 1000;
|
||||
i = 0;
|
||||
while (chSysGetTime() < time) {
|
||||
(void)chMsgSend(tp, 0);
|
||||
i++;
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void precache(void) {
|
||||
uint32_t i;
|
||||
|
||||
println("\r\nPreparing for benchmarks\r\n");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread6, 0);
|
||||
i = msg_loop_test(t1);
|
||||
chThdTerminate(t1);
|
||||
chThdWait(t1);
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void bench1(void) {
|
||||
uint32_t i;
|
||||
|
||||
println("*** Kernel Benchmark, context switch test #1 (optimal):");
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread6, 0);
|
||||
i = msg_loop_test(t1);
|
||||
chThdTerminate(t1);
|
||||
chThdWait(t1);
|
||||
print("Messages throughput = ");
|
||||
printn(i);
|
||||
print(" msgs/S, ");
|
||||
printn(i << 1);
|
||||
println(" ctxswc/S");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void bench2(void) {
|
||||
uint32_t i;
|
||||
|
||||
println("*** Kernel Benchmark, context switch test #2 (no threads in ready list):");
|
||||
t1 = chThdCreate(chThdGetPriority()+1, 0, wsT1, sizeof(wsT1), Thread6, 0);
|
||||
i = msg_loop_test(t1);
|
||||
chThdTerminate(t1);
|
||||
chMsgSend(t1, 0);
|
||||
chThdWait(t1);
|
||||
print("Messages throughput = ");
|
||||
printn(i);
|
||||
print(" msgs/S, ");
|
||||
printn(i << 1);
|
||||
println(" ctxswc/S");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void bench3(void) {
|
||||
uint32_t i;
|
||||
|
||||
println("*** Kernel Benchmark, context switch test #3 (04 threads in ready list):");
|
||||
t1 = chThdCreate(chThdGetPriority()+1, 0, wsT1, sizeof(wsT1), Thread6, "A");
|
||||
t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread7, "B");
|
||||
t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread7, "C");
|
||||
t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread7, "D");
|
||||
t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread7, "E");
|
||||
i = msg_loop_test(t1);
|
||||
chThdTerminate(t1);
|
||||
chMsgSend(t1, 0);
|
||||
wait();
|
||||
print("Messages throughput = ");
|
||||
printn(i);
|
||||
print(" msgs/S, ");
|
||||
printn(i << 1);
|
||||
println(" ctxswc/S");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void bench4(void) {
|
||||
uint32_t i;
|
||||
systime_t time;
|
||||
|
||||
println("*** Kernel Benchmark, threads creation/termination:");
|
||||
time = wait_tick() + 1000;
|
||||
i = 0;
|
||||
while (chSysGetTime() < time) {
|
||||
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread7, NULL);
|
||||
chThdWait(t1);
|
||||
i++;
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
print("Threads throughput = ");
|
||||
printn(i);
|
||||
println(" threads/S");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void bench5(void) {
|
||||
static uint8_t ib[16];
|
||||
static Queue iq;
|
||||
uint32_t i;
|
||||
systime_t time;
|
||||
|
||||
println("*** Kernel Benchmark, I/O Queues throughput:");
|
||||
chIQInit(&iq, ib, sizeof(ib), NULL);
|
||||
time = wait_tick() + 1000;
|
||||
i = 0;
|
||||
while (chSysGetTime() < time) {
|
||||
chIQPutI(&iq, 0);
|
||||
chIQPutI(&iq, 1);
|
||||
chIQPutI(&iq, 2);
|
||||
chIQPutI(&iq, 3);
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
(void)chIQGet(&iq);
|
||||
i++;
|
||||
#if defined(WIN32)
|
||||
ChkIntSources();
|
||||
#endif
|
||||
}
|
||||
print("Queues throughput = ");
|
||||
printn(i * 4);
|
||||
println(" bytes/S");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tester thread, this thread must be created with priority \p NORMALPRIO.
|
||||
*/
|
||||
msg_t TestThread(void *p) {
|
||||
int i;
|
||||
|
||||
comp = p;
|
||||
println("*****************************");
|
||||
println("*** ChibiOS/RT test suite ***");
|
||||
println("*****************************");
|
||||
println("");
|
||||
test_println("");
|
||||
test_println("*****************************");
|
||||
test_println("*** ChibiOS/RT test suite ***");
|
||||
test_println("*****************************");
|
||||
test_println("");
|
||||
|
||||
/*
|
||||
* Ready list ordering tests.
|
||||
*/
|
||||
testrdy1();
|
||||
testrdy2();
|
||||
global_fail = FALSE;
|
||||
i = 0;
|
||||
while (tests[i]) {
|
||||
#if DELAY_BETWEEN_TESTS > 0
|
||||
chThdSleep(DELAY_BETWEEN_TESTS);
|
||||
#endif
|
||||
test_println("------------------------------------------------------------");
|
||||
test_print("--- Test Case ");
|
||||
test_printn(i + 1);
|
||||
test_print(" (");
|
||||
test_print(tests[i]->gettest());
|
||||
test_println(")");
|
||||
execute_test(tests[i]);
|
||||
if (local_fail) {
|
||||
test_print("--- Result: FAIL (");
|
||||
if (failmsg)
|
||||
test_print(failmsg);
|
||||
else {
|
||||
test_print("sequence error: ");
|
||||
print_tokens();
|
||||
}
|
||||
test_println(")");
|
||||
}
|
||||
else
|
||||
test_println("--- Result: SUCCESS");
|
||||
i++;
|
||||
}
|
||||
test_println("------------------------------------------------------------");
|
||||
test_println("");
|
||||
test_print("Final result: ");
|
||||
if (global_fail)
|
||||
test_println("FAIL");
|
||||
else
|
||||
test_println("SUCCESS");
|
||||
|
||||
/*
|
||||
* Semaphores tests.
|
||||
*/
|
||||
testsem1();
|
||||
testsem2();
|
||||
|
||||
/*
|
||||
* Mutexes tests.
|
||||
*/
|
||||
testmtx1();
|
||||
testmtx2();
|
||||
testmtx3();
|
||||
testmtx4();
|
||||
|
||||
/*
|
||||
* Messages tests.
|
||||
*/
|
||||
testmsg1();
|
||||
|
||||
/*
|
||||
* Kernel benchmarks.
|
||||
* NOTE: The calls to chThdSleep() are required in order to give I/O queues
|
||||
* enough time to transmit everything, else the tests would get some
|
||||
* extra interrupts to serve from previous tests.
|
||||
*/
|
||||
precache();
|
||||
chThdSleep(100);
|
||||
bench1();
|
||||
chThdSleep(100);
|
||||
bench2();
|
||||
chThdSleep(100);
|
||||
bench3();
|
||||
chThdSleep(100);
|
||||
bench4();
|
||||
chThdSleep(100);
|
||||
bench5();
|
||||
chThdSleep(100);
|
||||
|
||||
println("\r\nTest complete");
|
||||
return 0;
|
||||
}
|
||||
|
|
30
test/test.h
30
test/test.h
|
@ -17,17 +17,43 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#ifndef _TEST_H_
|
||||
#define _TEST_H_
|
||||
|
||||
#define MAX_THREADS 5
|
||||
#define MAX_TOKENS 16
|
||||
#define DELAY_BETWEEN_TESTS 200
|
||||
|
||||
#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430)
|
||||
#define THREADS_STACK_SIZE 64
|
||||
#else
|
||||
#define THREADS_STACK_SIZE 128
|
||||
#endif
|
||||
#define STKSIZE UserStackSize(THREADS_STACK_SIZE)
|
||||
|
||||
struct testcase {
|
||||
char *(*gettest)(void);
|
||||
void (*setup)(void);
|
||||
void (*teardown)(void);
|
||||
void (*execute)(void);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
msg_t TestThread(void *p);
|
||||
void test_emit_token(char token);
|
||||
void test_fail(char * msg);
|
||||
void test_assert(bool_t condition, char * msg);
|
||||
void test_assert_sequence(char *expected);
|
||||
void test_assert_time_window(systime_t start, systime_t end);
|
||||
void test_wait_threads(void);
|
||||
void test_cpu_pulse(systime_t ms);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern Thread *threads[MAX_THREADS];
|
||||
extern void *wa[MAX_THREADS];
|
||||
|
||||
#endif /* _TEST_H_ */
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
static char *msg1_gettest(void) {
|
||||
|
||||
return "Messages, dispatch test";
|
||||
}
|
||||
|
||||
static void msg1_setup(void) {
|
||||
}
|
||||
|
||||
static void msg1_teardown(void) {
|
||||
}
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
msg_t msg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
msg = chMsgSend(p, 'A' + i);
|
||||
test_emit_token(msg);
|
||||
}
|
||||
chMsgSend(p, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msg1_execute(void) {
|
||||
msg_t msg;
|
||||
|
||||
threads[0] = chThdCreate(chThdGetPriority()-1, 0, wa[0], STKSIZE, thread, chThdSelf());
|
||||
do {
|
||||
chMsgRelease(msg = chMsgWait());
|
||||
if (msg)
|
||||
test_emit_token(msg);
|
||||
} while (msg);
|
||||
test_wait_threads();
|
||||
test_assert_sequence("AABBCCDDEE");
|
||||
}
|
||||
|
||||
const struct testcase testmsg1 = {
|
||||
msg1_gettest,
|
||||
msg1_setup,
|
||||
msg1_teardown,
|
||||
msg1_execute
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TESTMSG_H_
|
||||
#define _TESTMSG_H_
|
||||
|
||||
extern const struct testcase testmsg1;
|
||||
|
||||
#endif /* _TESTMSG_H_ */
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#define ALLOWED_DELAY 5
|
||||
|
||||
static Mutex m1, m2;
|
||||
|
||||
static char *mtx1_gettest(void) {
|
||||
|
||||
return "Mutexes, priority enqueuing test";
|
||||
}
|
||||
|
||||
static void mtx1_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static void mtx1_teardown(void) {
|
||||
}
|
||||
|
||||
static msg_t thread1(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
test_emit_token(*(char *)p);
|
||||
chMtxUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtx1_execute(void) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
threads[0] = chThdCreate(chThdGetPriority()+1, 0, wa[0], STKSIZE, thread1, "E");
|
||||
threads[1] = chThdCreate(chThdGetPriority()+2, 0, wa[1], STKSIZE, thread1, "D");
|
||||
threads[2] = chThdCreate(chThdGetPriority()+3, 0, wa[2], STKSIZE, thread1, "C");
|
||||
threads[3] = chThdCreate(chThdGetPriority()+4, 0, wa[3], STKSIZE, thread1, "B");
|
||||
threads[4] = chThdCreate(chThdGetPriority()+5, 0, wa[4], STKSIZE, thread1, "A");
|
||||
chMtxUnlock();
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE");
|
||||
}
|
||||
|
||||
const struct testcase testmtx1 = {
|
||||
mtx1_gettest,
|
||||
mtx1_setup,
|
||||
mtx1_teardown,
|
||||
mtx1_execute
|
||||
};
|
||||
|
||||
static char *mtx2_gettest(void) {
|
||||
|
||||
return "Mutexes, priority inheritance, simple case";
|
||||
}
|
||||
|
||||
static void mtx2_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
}
|
||||
|
||||
static void mtx2_teardown(void) {
|
||||
}
|
||||
|
||||
static msg_t thread2(void *p) {
|
||||
|
||||
chThdSleep(5);
|
||||
chMtxLock(&m1);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread3(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
chThdSleep(20);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread4(void *p) {
|
||||
|
||||
chThdSleep(10);
|
||||
test_cpu_pulse(50);
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Time
|
||||
* 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
|
||||
* 1 .....................++--------------------------------------------------
|
||||
* 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
|
||||
*/
|
||||
static void mtx2_execute(void) {
|
||||
|
||||
threads[0] = chThdCreate(chThdGetPriority()-1, 0, wa[0], STKSIZE, thread2, "A");
|
||||
threads[1] = chThdCreate(chThdGetPriority()-3, 0, wa[1], STKSIZE, thread3, "C");
|
||||
threads[2] = chThdCreate(chThdGetPriority()-2, 0, wa[2], STKSIZE, thread4, "B");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABC");
|
||||
}
|
||||
|
||||
const struct testcase testmtx2 = {
|
||||
mtx2_gettest,
|
||||
mtx2_setup,
|
||||
mtx2_teardown,
|
||||
mtx2_execute
|
||||
};
|
||||
|
||||
static char *mtx3_gettest(void) {
|
||||
|
||||
return "Mutexes, priority inheritance, complex case";
|
||||
}
|
||||
|
||||
static void mtx3_setup(void) {
|
||||
|
||||
chMtxInit(&m1);
|
||||
chMtxInit(&m2);
|
||||
}
|
||||
|
||||
static void mtx3_teardown(void) {
|
||||
}
|
||||
|
||||
static msg_t thread5(void *p) {
|
||||
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(50);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread6(void *p) {
|
||||
|
||||
chThdSleep(10);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(20);
|
||||
chMtxLock(&m1);
|
||||
test_cpu_pulse(50);
|
||||
chMtxUnlock();
|
||||
test_cpu_pulse(20);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread7(void *p) {
|
||||
|
||||
chThdSleep(20);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(50);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread8(void *p) {
|
||||
|
||||
chThdSleep(40);
|
||||
test_cpu_pulse(200);
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static msg_t thread9(void *p) {
|
||||
|
||||
chThdSleep(50);
|
||||
chMtxLock(&m2);
|
||||
test_cpu_pulse(50);
|
||||
chMtxUnlock();
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Time 0 10 20 30 40 50
|
||||
* 0 +++BL++------------------2++++------4+++++BU0--------------------------
|
||||
* 1 .......++AL++--2+++++++++BL.........4.....++++++++BU4++++AU1-----------
|
||||
* 2 .............++AL............................................------++AU
|
||||
* 3 ..............................++++-------------------------------++....
|
||||
* 4 ..................................++AL...................++++AU++......
|
||||
*/
|
||||
static void mtx3_execute(void) {
|
||||
|
||||
threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread5, "E");
|
||||
threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread6, "D");
|
||||
threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread7, "C");
|
||||
threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread8, "B");
|
||||
threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread9, "A");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE");
|
||||
}
|
||||
|
||||
const struct testcase testmtx3 = {
|
||||
mtx3_gettest,
|
||||
mtx3_setup,
|
||||
mtx3_teardown,
|
||||
mtx3_execute
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TESTMTX_H_
|
||||
#define _TESTMTX_H_
|
||||
|
||||
extern const struct testcase testmtx1, testmtx2, testmtx3;
|
||||
|
||||
#endif /* _TESTMTX_H_ */
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *rdy1_gettest(void) {
|
||||
|
||||
return "Ready List, priority enqueuing test #1";
|
||||
}
|
||||
|
||||
static void rdy1_setup(void) {
|
||||
}
|
||||
|
||||
static void rdy1_teardown(void) {
|
||||
}
|
||||
|
||||
static void rdy1_execute(void) {
|
||||
|
||||
threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread, "E");
|
||||
threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread, "D");
|
||||
threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread, "C");
|
||||
threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread, "B");
|
||||
threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread, "A");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE");
|
||||
}
|
||||
|
||||
const struct testcase testrdy1 = {
|
||||
rdy1_gettest,
|
||||
rdy1_setup,
|
||||
rdy1_teardown,
|
||||
rdy1_execute
|
||||
};
|
||||
|
||||
static char *rdy2_gettest(void) {
|
||||
|
||||
return "Ready List, priority enqueuing test #2";
|
||||
}
|
||||
|
||||
static void rdy2_setup(void) {
|
||||
}
|
||||
|
||||
static void rdy2_teardown(void) {
|
||||
}
|
||||
|
||||
static void rdy2_execute(void) {
|
||||
|
||||
threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread, "D");
|
||||
threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread, "E");
|
||||
threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread, "A");
|
||||
threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread, "B");
|
||||
threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread, "C");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE");
|
||||
}
|
||||
|
||||
const struct testcase testrdy2 = {
|
||||
rdy2_gettest,
|
||||
rdy2_setup,
|
||||
rdy2_teardown,
|
||||
rdy2_execute
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TESTRDY_H_
|
||||
#define _TESTRDY_H_
|
||||
|
||||
extern const struct testcase testrdy1, testrdy2;
|
||||
|
||||
#endif /* _TESTRDY_H_ */
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#define ALLOWED_DELAY 5
|
||||
|
||||
static Semaphore sem1;
|
||||
|
||||
static char *sem1_gettest(void) {
|
||||
|
||||
return "Semaphores, FIFO enqueuing test";
|
||||
}
|
||||
|
||||
static void sem1_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void sem1_teardown(void) {
|
||||
}
|
||||
|
||||
static msg_t thread(void *p) {
|
||||
|
||||
chSemWait(&sem1);
|
||||
test_emit_token(*(char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sem1_execute(void) {
|
||||
|
||||
threads[0] = chThdCreate(chThdGetPriority()+5, 0, wa[0], STKSIZE, thread, "A");
|
||||
threads[1] = chThdCreate(chThdGetPriority()+1, 0, wa[1], STKSIZE, thread, "B");
|
||||
threads[2] = chThdCreate(chThdGetPriority()+3, 0, wa[2], STKSIZE, thread, "C");
|
||||
threads[3] = chThdCreate(chThdGetPriority()+4, 0, wa[3], STKSIZE, thread, "D");
|
||||
threads[4] = chThdCreate(chThdGetPriority()+2, 0, wa[4], STKSIZE, thread, "E");
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE");
|
||||
}
|
||||
|
||||
const struct testcase testsem1 = {
|
||||
sem1_gettest,
|
||||
sem1_setup,
|
||||
sem1_teardown,
|
||||
sem1_execute
|
||||
};
|
||||
|
||||
static char *sem2_gettest(void) {
|
||||
|
||||
return "Semaphores, timeout test";
|
||||
}
|
||||
|
||||
static void sem2_setup(void) {
|
||||
|
||||
chSemInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void sem2_teardown(void) {
|
||||
}
|
||||
|
||||
static void sem2_execute(void) {
|
||||
int i;
|
||||
systime_t target_time;
|
||||
|
||||
target_time = chSysGetTime() + 5 * 500;
|
||||
for (i = 0; i < 5; i++) {
|
||||
test_emit_token('A' + i);
|
||||
chSemWaitTimeout(&sem1, 500);
|
||||
}
|
||||
test_assert_sequence("ABCDE");
|
||||
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
|
||||
}
|
||||
|
||||
const struct testcase testsem2 = {
|
||||
sem2_gettest,
|
||||
sem2_setup,
|
||||
sem2_teardown,
|
||||
sem2_execute
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TESTSEM_H_
|
||||
#define _TESTSEM_H_
|
||||
|
||||
extern const struct testcase testsem1, testsem2;
|
||||
|
||||
#endif /* _TESTSEM_H_ */
|
Loading…
Reference in New Issue