diff --git a/demos/ARM7-LPC214x-GCC/Makefile b/demos/ARM7-LPC214x-GCC/Makefile index 0c0ad93e9..eb9cf9bc7 100644 --- a/demos/ARM7-LPC214x-GCC/Makefile +++ b/demos/ARM7-LPC214x-GCC/Makefile @@ -93,9 +93,13 @@ AOPT = TOPT = -mthumb -D THUMB # Common options here -# NOTE: -ffixed-r7 is only needed if you enabled CH_CURRP_REGISTER_CACHE in chconf.h. +# NOTE: -ffixed-r7 is only needed if you enabled CH_CURRP_REGISTER_CACHE in +# chconf.h. +# NOTE: -falign-functions=16 may improve the performance, not always, but +# increases the code size. OPT = -O2 -ggdb -fomit-frame-pointer -fno-strict-aliasing #OPT += -ffixed-r7 +#OPT += -falign-functions=16 # Define warning options here WARN = -Wall -Wstrict-prototypes diff --git a/demos/ARM7-LPC214x-GCC/main.c b/demos/ARM7-LPC214x-GCC/main.c index fbd4f2726..e10063bcb 100644 --- a/demos/ARM7-LPC214x-GCC/main.c +++ b/demos/ARM7-LPC214x-GCC/main.c @@ -119,8 +119,14 @@ static t_msg Thread3(void *arg) { int main(int argc, char **argv) { chSysInit(); - chThdCreate(NORMALPRIO, 0, waThread1, sizeof(waThread1), Thread1, NULL); - chThdCreate(NORMALPRIO, 0, waThread2, sizeof(waThread2), Thread2, NULL); + /* + * If a button is pressed during the reset then the blinking leds are not + * started in order to make accurate benchmarks. + */ + if ((IO0PIN & 0x00018000) == 0x00018000) { + chThdCreate(NORMALPRIO, 0, waThread1, sizeof(waThread1), Thread1, NULL); + chThdCreate(NORMALPRIO, 0, waThread2, sizeof(waThread2), Thread2, NULL); + } chThdCreate(NORMALPRIO, 0, waThread3, sizeof(waThread3), Thread3, NULL); chSysPause(); return 0; diff --git a/demos/AVR-AT90CANx-GCC/chconf.h b/demos/AVR-AT90CANx-GCC/chconf.h index 63a391e08..c6146f5e7 100644 --- a/demos/AVR-AT90CANx-GCC/chconf.h +++ b/demos/AVR-AT90CANx-GCC/chconf.h @@ -157,6 +157,12 @@ */ //#define CH_CURRP_REGISTER_CACHE "reg" +/** Configuration option: Includes basic debug support to the kernel. + * @note the debug support is port-dependent, it may be not present on some + * targets. In that case stub functions will be included. + */ +//#define CH_USE_DEBUG + #endif /* _CHCONF_H_ */ /** @} */ diff --git a/demos/AVR-AT90CANx-GCC/chcore.h b/demos/AVR-AT90CANx-GCC/chcore.h index c3e0cfa34..935c37488 100644 --- a/demos/AVR-AT90CANx-GCC/chcore.h +++ b/demos/AVR-AT90CANx-GCC/chcore.h @@ -101,6 +101,7 @@ typedef struct { #define chSysLock() asm("cli") #define chSysUnlock() asm("sei") +#define chSysPuts(msg) {} void chSysHalt(void) __attribute__((noreturn)) ; void chSysPause(void) __attribute__((noreturn)) ; diff --git a/demos/AVR-AT90CANx-GCC/chtypes.h b/demos/AVR-AT90CANx-GCC/chtypes.h index d3c26caaf..60e16aaf4 100644 --- a/demos/AVR-AT90CANx-GCC/chtypes.h +++ b/demos/AVR-AT90CANx-GCC/chtypes.h @@ -34,6 +34,7 @@ typedef BYTE8 t_tmode; typedef BYTE8 t_tstate; +typedef BYTE8 t_tid; typedef BYTE8 t_prio; typedef WORD16 t_msg; typedef BYTE8 t_eventid; diff --git a/demos/Win32-MSVS/ch.vcproj b/demos/Win32-MSVS/ch.vcproj index 26dd9557e..3490c810b 100644 --- a/demos/Win32-MSVS/ch.vcproj +++ b/demos/Win32-MSVS/ch.vcproj @@ -141,6 +141,9 @@ + + @@ -209,6 +212,9 @@ + + diff --git a/demos/Win32-MSVS/chconf.h b/demos/Win32-MSVS/chconf.h index 1aa089575..be1896046 100644 --- a/demos/Win32-MSVS/chconf.h +++ b/demos/Win32-MSVS/chconf.h @@ -161,6 +161,12 @@ */ //#define CH_CURRP_REGISTER_CACHE "reg" +/** Configuration option: Includes basic debug support to the kernel. + * @note the debug support is port-dependent, it may be not present on some + * targets. In that case stub functions will be included. + */ +//#define CH_USE_DEBUG + #endif /* _CHCONF_H_ */ /** @} */ diff --git a/demos/Win32-MSVS/chcore.c b/demos/Win32-MSVS/chcore.c index 01619f9cd..8aedbb465 100644 --- a/demos/Win32-MSVS/chcore.c +++ b/demos/Win32-MSVS/chcore.c @@ -47,7 +47,7 @@ void InitCore(void) { /* * Interrupt simulation. */ -static void ChkIntSources(void) { +void ChkIntSources(void) { LARGE_INTEGER n; if (Com1InInterruptSimCom() || Com2InInterruptSimCom() || diff --git a/demos/Win32-MSVS/chcore.h b/demos/Win32-MSVS/chcore.h index 26e0b66bf..58e278fe4 100644 --- a/demos/Win32-MSVS/chcore.h +++ b/demos/Win32-MSVS/chcore.h @@ -58,8 +58,8 @@ typedef struct { } #define chSysLock() - #define chSysUnlock() +#define chSysPuts(msg) {} #define INT_REQUIRED_STACK 0x0 diff --git a/demos/Win32-MSVS/chtypes.h b/demos/Win32-MSVS/chtypes.h index 6481c22a8..5ab9a06e1 100644 --- a/demos/Win32-MSVS/chtypes.h +++ b/demos/Win32-MSVS/chtypes.h @@ -33,6 +33,7 @@ typedef BYTE8 t_tmode; typedef BYTE8 t_tstate; +typedef UWORD16 t_tid; typedef ULONG32 t_prio; typedef LONG32 t_msg; typedef LONG32 t_eventid; diff --git a/demos/Win32-MinGW/chconf.h b/demos/Win32-MinGW/chconf.h index b7a8acedd..8ce32defa 100644 --- a/demos/Win32-MinGW/chconf.h +++ b/demos/Win32-MinGW/chconf.h @@ -161,6 +161,12 @@ */ //#define CH_CURRP_REGISTER_CACHE "reg" +/** Configuration option: Includes basic debug support to the kernel. + * @note the debug support is port-dependent, it may be not present on some + * targets. In that case stub functions will be included. + */ +//#define CH_USE_DEBUG + #endif /* _CHCONF_H_ */ /** @} */ diff --git a/demos/Win32-MinGW/chcore.c b/demos/Win32-MinGW/chcore.c index ee04147e9..c96611f8b 100644 --- a/demos/Win32-MinGW/chcore.c +++ b/demos/Win32-MinGW/chcore.c @@ -70,7 +70,7 @@ void InitCore(void) { /* * Interrupt simulation. */ -static void ChkIntSources(void) { +void ChkIntSources(void) { LARGE_INTEGER n; if (Com1InInterruptSimCom() || Com2InInterruptSimCom() || diff --git a/demos/Win32-MinGW/chcore.h b/demos/Win32-MinGW/chcore.h index 7f0021854..6d3055081 100644 --- a/demos/Win32-MinGW/chcore.h +++ b/demos/Win32-MinGW/chcore.h @@ -58,8 +58,8 @@ typedef struct { } #define chSysLock() - #define chSysUnlock() +#define chSysPuts(msg) {} #define INT_REQUIRED_STACK 0x0 diff --git a/demos/Win32-MinGW/chtypes.h b/demos/Win32-MinGW/chtypes.h index 803b5ead4..2ac219148 100644 --- a/demos/Win32-MinGW/chtypes.h +++ b/demos/Win32-MinGW/chtypes.h @@ -33,6 +33,7 @@ typedef BYTE8 t_tmode; typedef BYTE8 t_tstate; +typedef UWORD16 t_tid; typedef ULONG32 t_prio; typedef LONG32 t_msg; typedef LONG32 t_eventid; diff --git a/readme.txt b/readme.txt index 79b03287d..36255b42f 100644 --- a/readme.txt +++ b/readme.txt @@ -48,6 +48,7 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet. using the CH_USE_DEBUG in chconf.h. The trace buffer is meant to be fetched and decoded by an external tool (coming soon, it can be accessed using JTAG in the meanwhile). +- Added new API chThdGetPriority() as a macro. - Implemented panic messages when CH_USE_DEBUG is enabled. - Added a thread identifier field to the Thread structure, it is used only for debug. diff --git a/src/chmsg.c b/src/chmsg.c index 5ea3f9821..0f24b24aa 100644 --- a/src/chmsg.c +++ b/src/chmsg.c @@ -153,7 +153,7 @@ t_msg chMsgWait(void) { * @return the pointer to the message structure. Note, it is always the * message associated to the thread on the top of the messages queue. * If the queue is empty then \p NULL is returned. - * @note You can assume that the data contained in the message is stable until + * @note You can assume that the data pointed by the message is stable until * you invoke \p chMsgRelease() because the sending thread is * suspended until then. Always remember that the message data is not * copied between the sender and the receiver, just a pointer is passed. diff --git a/src/chschd.c b/src/chschd.c index c88a63ead..a3763cd38 100644 --- a/src/chschd.c +++ b/src/chschd.c @@ -81,7 +81,11 @@ Thread *chSchReadyI(Thread *tp) { * Switches to the next thread in the ready list, the ready list is assumed * to contain at least a thread. */ +#ifdef CH_OPTIMIZE_SPEED +static INLINE void nextready(void) { +#else static void nextready(void) { +#endif Thread *otp = currp; (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR; @@ -111,27 +115,27 @@ void chSchGoSleepS(t_tstate newstate) { * Wakeups a thread, the thread is inserted into the ready list or made * running directly depending on its relative priority compared to the current * thread. - * @param tp the Thread to be made ready + * @param ntp the Thread to be made ready * @param msg wakeup message to the awakened thread * @note The function must be called in the system mutex zone. * @note The function is not meant to be used in the user code directly. * @note It is equivalent to a \p chSchReadyI() followed by a * \p chSchRescheduleI() but much more efficient. */ -void chSchWakeupS(Thread *tp, t_msg msg) { - Thread *ctp = currp; +void chSchWakeupS(Thread *ntp, t_msg msg) { - if (tp->p_prio <= ctp->p_prio) - chSchReadyI(tp)->p_rdymsg = msg; + if (ntp->p_prio <= currp->p_prio) + chSchReadyI(ntp)->p_rdymsg = msg; else { - chSchReadyI(ctp); - (currp = tp)->p_state = PRCURR; - tp->p_rdymsg = msg; + Thread *otp = currp; + chSchReadyI(otp); + (currp = ntp)->p_state = PRCURR; + ntp->p_rdymsg = msg; preempt = CH_TIME_QUANTUM; #ifdef CH_USE_DEBUG - chDbgTrace(ctp, tp); + chDbgTrace(otp, ntp); #endif - chSysSwitchI(&ctp->p_ctx, &tp->p_ctx); + chSysSwitchI(&otp->p_ctx, &ntp->p_ctx); } } diff --git a/src/include/threads.h b/src/include/threads.h index e4cd8376e..ee00039b3 100644 --- a/src/include/threads.h +++ b/src/include/threads.h @@ -178,6 +178,9 @@ extern "C" { /** Returns the pointer to the \p Thread currently in execution.*/ #define chThdSelf() currp +/** Returns the thread priority.*/ +#define chThdGetPriority() (currp->p_prio) + /** Returns the pointer to the \p Thread local storage area, if any.*/ #define chThdLS() (void *)(currp + 1) diff --git a/test/test.c b/test/test.c index 8fe61794c..a40a059f3 100644 --- a/test/test.c +++ b/test/test.c @@ -19,6 +19,8 @@ #include +void ChkIntSources(void); + #if defined(WIN32) && defined(_DEBUG) static BYTE8 wsT1[UserStackSize(512)]; static BYTE8 wsT2[UserStackSize(512)]; @@ -126,6 +128,7 @@ t_msg Thread6(void *p) { t_msg TestThread(void *p) { t_msg msg; unsigned int i; + t_time time; comp = p; println("*****************************"); @@ -137,19 +140,19 @@ t_msg TestThread(void *p) { * Ready list ordering test. */ println("*** Ready List, priority enqueuing test #1, you should read ABCDE:"); - t5 = chThdCreate(NORMALPRIO-5, 0, wsT5, sizeof(wsT5), Thread1, "E"); - t4 = chThdCreate(NORMALPRIO-4, 0, wsT4, sizeof(wsT4), Thread1, "D"); - t3 = chThdCreate(NORMALPRIO-3, 0, wsT3, sizeof(wsT3), Thread1, "C"); - t2 = chThdCreate(NORMALPRIO-2, 0, wsT2, sizeof(wsT2), Thread1, "B"); - t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread1, "A"); + 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(""); println("*** Ready List, priority enqueuing test #2, you should read ABCDE:"); - t4 = chThdCreate(NORMALPRIO-4, 0, wsT4, sizeof(wsT4), Thread1, "D"); - t5 = chThdCreate(NORMALPRIO-5, 0, wsT5, sizeof(wsT5), Thread1, "E"); - t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread1, "A"); - t2 = chThdCreate(NORMALPRIO-2, 0, wsT2, sizeof(wsT2), Thread1, "B"); - t3 = chThdCreate(NORMALPRIO-3, 0, wsT3, sizeof(wsT3), Thread1, "C"); + 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(""); @@ -158,11 +161,11 @@ t_msg TestThread(void *p) { */ chSemInit(&sem1, 0); println("*** Semaphores, FIFO enqueuing test, you should read ABCDE:"); - t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread2, "A"); - t2 = chThdCreate(NORMALPRIO+1, 0, wsT2, sizeof(wsT2), Thread2, "B"); - t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread2, "C"); - t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread2, "D"); - t5 = chThdCreate(NORMALPRIO+2, 0, wsT5, sizeof(wsT5), Thread2, "E"); + 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); @@ -172,11 +175,11 @@ t_msg TestThread(void *p) { println(""); println("*** Semaphores, priority enqueuing test #1, you should read ABCDE:"); chSemInit(&sem1, 0); - t5 = chThdCreate(NORMALPRIO+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); - t4 = chThdCreate(NORMALPRIO+2, 0, wsT4, sizeof(wsT4), Thread3, "D"); - t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread3, "C"); - t2 = chThdCreate(NORMALPRIO+4, 0, wsT2, sizeof(wsT2), Thread3, "B"); - t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread3, "A"); + t5 = chThdCreate(chThdGetPriority()+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); + t4 = chThdCreate(chThdGetPriority()+2, 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"); chSemLowerPrioSignal(&sem1); chSemLowerPrioSignal(&sem1); chSemLowerPrioSignal(&sem1); @@ -186,11 +189,11 @@ t_msg TestThread(void *p) { println(""); println("*** Semaphores, priority enqueuing test #2, you should read ABCDE:"); chSemInit(&sem1, 0); - t4 = chThdCreate(NORMALPRIO+2, 0, wsT4, sizeof(wsT4), Thread3, "D"); - t5 = chThdCreate(NORMALPRIO+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); - t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread3, "A"); - t2 = chThdCreate(NORMALPRIO+4, 0, wsT2, sizeof(wsT2), Thread3, "B"); - t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread3, "C"); + t4 = chThdCreate(chThdGetPriority()+2, 0, wsT4, sizeof(wsT4), Thread3, "D"); + t5 = chThdCreate(chThdGetPriority()+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); + t1 = chThdCreate(chThdGetPriority()+5, 0, wsT1, sizeof(wsT1), Thread3, "A"); + t2 = chThdCreate(chThdGetPriority()+4, 0, wsT2, sizeof(wsT2), Thread3, "B"); + t3 = chThdCreate(chThdGetPriority()+3, 0, wsT3, sizeof(wsT3), Thread3, "C"); chSemLowerPrioSignal(&sem1); chSemLowerPrioSignal(&sem1); chSemLowerPrioSignal(&sem1); @@ -210,7 +213,7 @@ t_msg TestThread(void *p) { * Messages test. */ println("*** Messages, dispatch test, you should read AABBCCDDEE:"); - t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread4, chThdSelf()); + t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread4, chThdSelf()); do { chMsgRelease(msg = chMsgWait()); if (msg) @@ -219,7 +222,7 @@ t_msg TestThread(void *p) { chThdWait(t1); println(""); println("*** Messages, timeout test, you should read ABCDE (slowly):"); - t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread5, chThdSelf()); + t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread5, chThdSelf()); for (i = 0; i < 5; i++) { chFDDPut(comp, 'A'+i); chMsgSendTimeout(t1, 'A'+i, 500); @@ -232,16 +235,22 @@ t_msg TestThread(void *p) { * Kernel benchmarks. */ println("*** Kernel Benchmark, context switch stress test:"); - t_time time = chSysGetTime() + 1; - while (chSysGetTime() < time) - ; + time = chSysGetTime() + 1; + while (chSysGetTime() < time) { +#if defined(WIN32) + ChkIntSources(); +#endif + } time += 1000; i = 0; - t1 = chThdCreate(NORMALPRIO+1, 0, wsT1, sizeof(wsT1), Thread6, chThdSelf()); - while (chSysGetTime() < time) + t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread6, chThdSelf()); + while (chSysGetTime() < time) { i = chMsgSend(t1, i); +#if defined(WIN32) + ChkIntSources(); +#endif + } chThdTerminate(t1); - chMsgSend(t1, 0); /* Lets the thread check the termination flag.*/ chThdWait(t1); print("Messages throughput = "); printn(i);