aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/ARM7-AT91SAM7X-GCC/chconf.h255
-rw-r--r--demos/ARM7-AT91SAM7X-LWIP-GCC/chconf.h255
-rw-r--r--demos/ARM7-AT91SAM7X-LWIP-GCC/lwip/arch/sys_arch.c6
-rw-r--r--os/kernel/include/ch.h1
-rw-r--r--os/kernel/include/heap.h47
-rw-r--r--os/kernel/include/memcore.h (renamed from os/kernel/include/mem.h)37
-rw-r--r--os/kernel/include/threads.h4
-rw-r--r--os/kernel/kernel.mk1
-rw-r--r--os/kernel/src/chheap.c222
-rw-r--r--os/kernel/src/chmemcore.c (renamed from os/kernel/src/chmem.c)27
-rw-r--r--os/kernel/src/chsys.c3
-rw-r--r--os/kernel/src/chthreads.c7
-rw-r--r--os/kernel/templates/chconf.h248
-rw-r--r--readme.txt9
-rw-r--r--test/test.c8
-rw-r--r--test/test.h17
-rw-r--r--test/testdyn.c66
-rw-r--r--test/testheap.c119
-rw-r--r--test/testmbox.c4
-rw-r--r--test/testqueues.c4
20 files changed, 860 insertions, 480 deletions
diff --git a/demos/ARM7-AT91SAM7X-GCC/chconf.h b/demos/ARM7-AT91SAM7X-GCC/chconf.h
index ba2e6d048..31c3c7a50 100644
--- a/demos/ARM7-AT91SAM7X-GCC/chconf.h
+++ b/demos/ARM7-AT91SAM7X-GCC/chconf.h
@@ -18,9 +18,9 @@
*/
/**
- * @file src/templates/chconf.h
+ * @file templates/chconf.h
* @brief Configuration file template.
- * @addtogroup Config
+ * @addtogroup config
* @{
*/
@@ -32,29 +32,36 @@
/*===========================================================================*/
/**
- * Frequency of the system timer that drives the system ticks. This also
- * defines the system tick time unit.
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
*/
#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000
#endif
/**
- * This constant is the number of system ticks allowed for the threads before
- * preemption occurs. This option is only meaningful if the option
- * @p CH_USE_ROUNDROBIN is also active.
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the round robin mechanism.
+ *
+ * @note Disabling round robin makes the kernel more compact and generally
+ * faster but forbids multiple threads at the same priority level.
*/
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20
#endif
/**
- * If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
- * operations is allowed.<br>
- * For performance and code size reasons the recommended setting is to leave
- * this option disabled.<br>
- * You can use this option if you need to merge ChibiOS/RT with external
- * libraries that require nested lock/unlock operations.
+ * @brief Nested locks.
+ * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
+ * operations is allowed.<br>
+ * For performance and code size reasons the recommended setting
+ * is to leave this option disabled.<br>
+ * You may use this option if you need to merge ChibiOS/RT with
+ * external libraries that require nested lock/unlock operations.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@@ -62,23 +69,18 @@
#endif
/**
- * If specified then the kernel performs the round robin scheduling algorithm
- * on threads of equal priority.
- * @note The default is @p TRUE.
- */
-#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__)
-#define CH_USE_ROUNDROBIN TRUE
-#endif
-
-/**
- * Number of RAM bytes to use as system heap. If set to zero then the whole
- * available RAM is used as system heap.
- * @note In order to use the whole RAM as system heap the linker script must
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
- * @note Requires @p CH_USE_HEAP.
+ * @note Requires @p CH_USE_COREMEM.
*/
-#if !defined(CH_HEAP_SIZE) || defined(__DOXYGEN__)
-#define CH_HEAP_SIZE 0
+#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
+#define CH_MEMCORE_SIZE 0
#endif
/*===========================================================================*/
@@ -86,8 +88,10 @@
/*===========================================================================*/
/**
- * If specified then time efficient rather than space efficient code is used
- * when two possible implementations exist.
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
@@ -96,18 +100,20 @@
#endif
/**
- * If enabled defines a CPU register to be used as storage for the global
- * @p currp variable. Caching this variable in a register can greatly
- * improve both space and time efficiency of the generated code. Another side
- * effect is that one less register has to be saved during the context switch
- * resulting in lower RAM usage and faster code.
+ * @brief Exotic optimization.
+ * @details If defined then a CPU register is used as storage for the global
+ * @p currp variable. Caching this variable in a register greatly
+ * improves both space and time OS efficiency. A side effect is that
+ * one less register has to be saved during the context switch
+ * resulting in lower RAM usage and faster context switch.
+ *
* @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the
* ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for
- * documentation.
+ * documentation only.
*/
#if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg"
@@ -118,7 +124,10 @@
/*===========================================================================*/
/**
- * If specified then the @p chThdWait() function is included in the kernel.
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@@ -126,7 +135,9 @@
#endif
/**
- * If specified then the Semaphores APIs are included in the kernel.
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@@ -134,8 +145,10 @@
#endif
/**
- * If enabled then the threads are enqueued on semaphores by priority rather
- * than FIFO order.
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -144,8 +157,10 @@
#endif
/**
- * If specified then the Semaphores the @p chSemWaitSignal() API is included
- * in the kernel.
+ * @brief Atomic semaphore API.
+ * @details If enabled then the semaphores the @p chSemWaitSignal() API
+ * is included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -154,7 +169,9 @@
#endif
/**
- * If specified then the Mutexes APIs are included in the kernel.
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@@ -162,7 +179,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES.
*/
@@ -171,7 +191,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS.
*/
@@ -180,7 +203,9 @@
#endif
/**
- * If specified then the Event flags APIs are included in the kernel.
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@@ -188,8 +213,10 @@
#endif
/**
- * If specified then the @p chEvtWaitXXXTimeout() functions are included in
- * the kernel.
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS.
*/
@@ -198,7 +225,10 @@
#endif
/**
- * If specified then the Synchronous Messages APIs are included in the kernel.
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@@ -206,7 +236,10 @@
#endif
/**
- * If enabled then messages are served by priority rather than in FIFO order.
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES.
*/
@@ -215,16 +248,21 @@
#endif
/**
- * If specified then the Asynchronous Messages (Mailboxes) APIs are included
- * in the kernel.
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
* @note The default is @p TRUE.
+ * @note Requires @p CH_USE_SEMAPHORES.
*/
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
-#define CH_USE_MAILBOXES TRUE
+#define CH_USE_MAILBOXES TRUE
#endif
/**
- * If specified then the I/O queues APIs are included in the kernel.
+ * @brief I/O Queues APIs.
+ * @details If enabled then the I/O queues APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -233,9 +271,24 @@
#endif
/**
- * If specified then the memory heap allocator APIs are included in the kernel.
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
+#define CH_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
- * @note Requires @p CH_USE_MUTEXES or @p CH_USE_SEMAPHORES.
+ * @note Requires @p CH_USE_COREMEM and either @p CH_USE_MUTEXES or
+ * @p CH_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@@ -243,18 +296,24 @@
#endif
/**
- * If enabled enforces the use of the C-runtime @p malloc() and @p free()
- * functions as backend for the system heap allocator.
+ * @brief C-runtime allocator.
+ * @details If enabled the the heap allocator APIs just wrap the C-runtime
+ * @p malloc() and @p free() functions.
+ *
* @note The default is @p FALSE.
* @note Requires @p CH_USE_HEAP.
+ * @note The C-runtime may or may not require @p CH_USE_COREMEM, see the
+ * appropriate documentation.
*/
#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE
#endif
/**
- * If specified then the memory pools allocator APIs are included in the
- * kernel.
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@@ -262,8 +321,10 @@
#endif
/**
- * If specified then the dynamic threads creation APIs are included in the
- * kernel.
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT.
*/
@@ -276,8 +337,10 @@
/*===========================================================================*/
/**
- * Debug option, if enabled then the checks on the API functions input
- * parameters are activated.
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@@ -285,9 +348,11 @@
#endif
/**
- * Debug option, if enabled then all the assertions in the kernel code are
- * activated. This includes consistency checks inside the kernel, runtime
- * anomalies and port-defined checks.
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@@ -295,8 +360,10 @@
#endif
/**
- * Debug option, if enabled the context switch circular trace buffer is
- * activated.
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the context switch circular trace buffer is
+ * activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@@ -304,25 +371,37 @@
#endif
/**
- * Debug option, if enabled a runtime stack check is performed.
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way. It
- * may not be implemented at all.
+ * may not be implemented or some ports.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif
/**
- * Debug option, if enabled the threads working area is filled with a byte
- * pattern when a thread is created.
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE
#endif
/**
- * Debug option, if enabled a field is added to the @p Thread structure that
- * counts the system ticks occurred while executing the thread.
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p Thread structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p TRUE.
+ * @note This debug option is defaulted to TRUE because it is required by
+ * some test cases into the test suite.
*/
#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE
@@ -333,38 +412,46 @@
/*===========================================================================*/
/**
- * User fields added to the end of the @p Thread structure.
+ * @brief Threads descriptor structure hook.
+ * @details User fields added to the end of the @p Thread structure.
*/
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \
struct { \
- /* Add thread custom fields here.*/ \
+ /* Add threads custom fields here.*/ \
};
#endif
/**
- * User initialization code added to the @p chThdInit() API.
- * @note It is invoked from within @p chThdInit().
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitily from all
+ * the threads creation APIs.
*/
#if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \
- /* Add thread initialization code here.*/ \
+ /* Add threads initialization code here.*/ \
}
#endif
/**
- * User finalization code added to the @p chThdExit() API.
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
* @note It is inserted into lock zone.
+ * @note It is also invoked when the threads simply return in order to
+ * terminate.
*/
#if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \
- /* Add thread finalization code here.*/ \
+ /* Add threads finalization code here.*/ \
}
#endif
/**
- * Code inserted inside the idle thread loop immediately after an interrupt
- * resumed execution.
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
*/
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \
diff --git a/demos/ARM7-AT91SAM7X-LWIP-GCC/chconf.h b/demos/ARM7-AT91SAM7X-LWIP-GCC/chconf.h
index e6a58ce12..b12b89b93 100644
--- a/demos/ARM7-AT91SAM7X-LWIP-GCC/chconf.h
+++ b/demos/ARM7-AT91SAM7X-LWIP-GCC/chconf.h
@@ -18,9 +18,9 @@
*/
/**
- * @file src/templates/chconf.h
+ * @file templates/chconf.h
* @brief Configuration file template.
- * @addtogroup Config
+ * @addtogroup config
* @{
*/
@@ -32,29 +32,36 @@
/*===========================================================================*/
/**
- * Frequency of the system timer that drives the system ticks. This also
- * defines the system tick time unit.
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
*/
#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000
#endif
/**
- * This constant is the number of system ticks allowed for the threads before
- * preemption occurs. This option is only meaningful if the option
- * @p CH_USE_ROUNDROBIN is also active.
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the round robin mechanism.
+ *
+ * @note Disabling round robin makes the kernel more compact and generally
+ * faster but forbids multiple threads at the same priority level.
*/
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20
#endif
/**
- * If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
- * operations is allowed.<br>
- * For performance and code size reasons the recommended setting is to leave
- * this option disabled.<br>
- * You can use this option if you need to merge ChibiOS/RT with external
- * libraries that require nested lock/unlock operations.
+ * @brief Nested locks.
+ * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
+ * operations is allowed.<br>
+ * For performance and code size reasons the recommended setting
+ * is to leave this option disabled.<br>
+ * You may use this option if you need to merge ChibiOS/RT with
+ * external libraries that require nested lock/unlock operations.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@@ -62,23 +69,18 @@
#endif
/**
- * If specified then the kernel performs the round robin scheduling algorithm
- * on threads of equal priority.
- * @note The default is @p TRUE.
- */
-#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__)
-#define CH_USE_ROUNDROBIN TRUE
-#endif
-
-/**
- * Number of RAM bytes to use as system heap. If set to zero then the whole
- * available RAM is used as system heap.
- * @note In order to use the whole RAM as system heap the linker script must
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
- * @note Requires @p CH_USE_HEAP.
+ * @note Requires @p CH_USE_COREMEM.
*/
-#if !defined(CH_HEAP_SIZE) || defined(__DOXYGEN__)
-#define CH_HEAP_SIZE 0
+#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
+#define CH_MEMCORE_SIZE 0
#endif
/*===========================================================================*/
@@ -86,8 +88,10 @@
/*===========================================================================*/
/**
- * If specified then time efficient rather than space efficient code is used
- * when two possible implementations exist.
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
@@ -96,18 +100,20 @@
#endif
/**
- * If enabled defines a CPU register to be used as storage for the global
- * @p currp variable. Caching this variable in a register can greatly
- * improve both space and time efficiency of the generated code. Another side
- * effect is that one less register has to be saved during the context switch
- * resulting in lower RAM usage and faster code.
+ * @brief Exotic optimization.
+ * @details If defined then a CPU register is used as storage for the global
+ * @p currp variable. Caching this variable in a register greatly
+ * improves both space and time OS efficiency. A side effect is that
+ * one less register has to be saved during the context switch
+ * resulting in lower RAM usage and faster context switch.
+ *
* @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the
* ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for
- * documentation.
+ * documentation only.
*/
#if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg"
@@ -118,7 +124,10 @@
/*===========================================================================*/
/**
- * If specified then the @p chThdWait() function is included in the kernel.
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@@ -126,7 +135,9 @@
#endif
/**
- * If specified then the Semaphores APIs are included in the kernel.
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@@ -134,8 +145,10 @@
#endif
/**
- * If enabled then the threads are enqueued on semaphores by priority rather
- * than FIFO order.
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -144,8 +157,10 @@
#endif
/**
- * If specified then the Semaphores the @p chSemWaitSignal() API is included
- * in the kernel.
+ * @brief Atomic semaphore API.
+ * @details If enabled then the semaphores the @p chSemWaitSignal() API
+ * is included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -154,7 +169,9 @@
#endif
/**
- * If specified then the Mutexes APIs are included in the kernel.
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@@ -162,7 +179,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES.
*/
@@ -171,7 +191,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS.
*/
@@ -180,7 +203,9 @@
#endif
/**
- * If specified then the Event flags APIs are included in the kernel.
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@@ -188,8 +213,10 @@
#endif
/**
- * If specified then the @p chEvtWaitXXXTimeout() functions are included in
- * the kernel.
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS.
*/
@@ -198,7 +225,10 @@
#endif
/**
- * If specified then the Synchronous Messages APIs are included in the kernel.
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@@ -206,7 +236,10 @@
#endif
/**
- * If enabled then messages are served by priority rather than in FIFO order.
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES.
*/
@@ -215,16 +248,21 @@
#endif
/**
- * If specified then the Asynchronous Messages (Mailboxes) APIs are included
- * in the kernel.
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
* @note The default is @p TRUE.
+ * @note Requires @p CH_USE_SEMAPHORES.
*/
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
-#define CH_USE_MAILBOXES TRUE
+#define CH_USE_MAILBOXES TRUE
#endif
/**
- * If specified then the I/O queues APIs are included in the kernel.
+ * @brief I/O Queues APIs.
+ * @details If enabled then the I/O queues APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -233,9 +271,24 @@
#endif
/**
- * If specified then the memory heap allocator APIs are included in the kernel.
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
+#define CH_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
- * @note Requires @p CH_USE_MUTEXES or @p CH_USE_SEMAPHORES.
+ * @note Requires @p CH_USE_COREMEM and either @p CH_USE_MUTEXES or
+ * @p CH_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@@ -243,18 +296,24 @@
#endif
/**
- * If enabled enforces the use of the C-runtime @p malloc() and @p free()
- * functions as backend for the system heap allocator.
+ * @brief C-runtime allocator.
+ * @details If enabled the the heap allocator APIs just wrap the C-runtime
+ * @p malloc() and @p free() functions.
+ *
* @note The default is @p FALSE.
* @note Requires @p CH_USE_HEAP.
+ * @note The C-runtime may or may not require @p CH_USE_COREMEM, see the
+ * appropriate documentation.
*/
#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE
#endif
/**
- * If specified then the memory pools allocator APIs are included in the
- * kernel.
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@@ -262,8 +321,10 @@
#endif
/**
- * If specified then the dynamic threads creation APIs are included in the
- * kernel.
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT.
*/
@@ -276,8 +337,10 @@
/*===========================================================================*/
/**
- * Debug option, if enabled then the checks on the API functions input
- * parameters are activated.
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@@ -285,9 +348,11 @@
#endif
/**
- * Debug option, if enabled then all the assertions in the kernel code are
- * activated. This includes consistency checks inside the kernel, runtime
- * anomalies and port-defined checks.
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@@ -295,8 +360,10 @@
#endif
/**
- * Debug option, if enabled the context switch circular trace buffer is
- * activated.
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the context switch circular trace buffer is
+ * activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@@ -304,25 +371,37 @@
#endif
/**
- * Debug option, if enabled a runtime stack check is performed.
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way. It
- * may not be implemented at all.
+ * may not be implemented or some ports.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif
/**
- * Debug option, if enabled the threads working area is filled with a byte
- * pattern when a thread is created.
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE
#endif
/**
- * Debug option, if enabled a field is added to the @p Thread structure that
- * counts the system ticks occurred while executing the thread.
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p Thread structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p TRUE.
+ * @note This debug option is defaulted to TRUE because it is required by
+ * some test cases into the test suite.
*/
#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE
@@ -333,41 +412,49 @@
/*===========================================================================*/
/**
- * User fields added to the end of the @p Thread structure.
+ * @brief Threads descriptor structure hook.
+ * @details User fields added to the end of the @p Thread structure.
*/
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \
struct { \
- /* Add thread custom fields here.*/ \
+ /* Add threads custom fields here.*/ \
/* Space for the LWIP sys_timeouts structure.*/ \
void *p_lwipspace[1]; \
};
#endif
/**
- * User initialization code added to the @p chThdInit() API.
- * @note It is invoked from within @p chThdInit().
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitily from all
+ * the threads creation APIs.
*/
#if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \
- /* Add thread initialization code here.*/ \
+ /* Add threads initialization code here.*/ \
(tp)->p_lwipspace[0] = NULL; \
}
#endif
/**
- * User finalization code added to the @p chThdExit() API.
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
* @note It is inserted into lock zone.
+ * @note It is also invoked when the threads simply return in order to
+ * terminate.
*/
#if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \
- /* Add thread finalization code here.*/ \
+ /* Add threads finalization code here.*/ \
}
#endif
/**
- * Code inserted inside the idle thread loop immediately after an interrupt
- * resumed execution.
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
*/
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \
diff --git a/demos/ARM7-AT91SAM7X-LWIP-GCC/lwip/arch/sys_arch.c b/demos/ARM7-AT91SAM7X-LWIP-GCC/lwip/arch/sys_arch.c
index 7d39c9520..65b1b5314 100644
--- a/demos/ARM7-AT91SAM7X-LWIP-GCC/lwip/arch/sys_arch.c
+++ b/demos/ARM7-AT91SAM7X-LWIP-GCC/lwip/arch/sys_arch.c
@@ -66,7 +66,7 @@ void sys_init(void) {
sys_sem_t sys_sem_new(u8_t count) {
- sys_sem_t sem = chHeapAlloc(sizeof(Semaphore));
+ sys_sem_t sem = chHeapAlloc(NULL, sizeof(Semaphore));
chSemInit(sem, (cnt_t)count);
return sem;
}
@@ -97,7 +97,7 @@ u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) {
sys_mbox_t sys_mbox_new(int size) {
sys_mbox_t mbox;
- mbox = chHeapAlloc(sizeof(Mailbox) + sizeof(msg_t) * size);
+ mbox = chHeapAlloc(NULL, sizeof(Mailbox) + sizeof(msg_t) * size);
chMBInit(mbox, (void *)(((uint8_t *)mbox) + sizeof(Mailbox)), size);
return mbox;
}
@@ -147,7 +147,7 @@ struct sys_timeouts *sys_arch_timeouts(void) {
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg),
void *arg, int stacksize, int prio) {
size_t wsz = THD_WA_SIZE(stacksize);
- void *wsp = chHeapAlloc(wsz);
+ void *wsp = chCoreAlloc(wsz);
if (wsp == NULL)
return NULL;
return (sys_thread_t)chThdCreateStatic(wsp, wsz, prio, (tfunc_t)thread, arg);
diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h
index 46d917e29..fa30c0eaf 100644
--- a/os/kernel/include/ch.h
+++ b/os/kernel/include/ch.h
@@ -75,6 +75,7 @@
#include "events.h"
#include "messages.h"
#include "mailboxes.h"
+#include "memcore.h"
#include "heap.h"
#include "mempools.h"
#include "threads.h"
diff --git a/os/kernel/include/heap.h b/os/kernel/include/heap.h
index 4fbd48225..1f07faa91 100644
--- a/os/kernel/include/heap.h
+++ b/os/kernel/include/heap.h
@@ -27,17 +27,60 @@
#ifndef _HEAP_H_
#define _HEAP_H_
+#if CH_USE_HEAP
+
+/*
+ * Module dependancies check.
+ */
+#if !CH_USE_MEMCORE && !CH_USE_MALLOC_HEAP
+#error "CH_USE_HEAP requires CH_USE_MEM"
+#endif
+
+#if !CH_USE_MUTEXES && !CH_USE_SEMAPHORES
+#error "CH_USE_HEAP requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES"
+#endif
+
+typedef struct memory_heap MemoryHeap;
+
+/**
+ * @brief Memory heap block header.
+ */
+struct heap_header {
+ union {
+ struct heap_header *h_next; /**< @brief Next block in free list. */
+ MemoryHeap *h_heap; /**< @brief Block owner heap. */
+ };
+ size_t h_size; /**< @brief Size of the memory block. */
+};
+
+/**
+ * @brief Structure describing a memory heap.
+ */
+struct memory_heap {
+ memgetfunc_t h_provider; /**< @brief Memory blocks provider for
+ this heap. */
+ struct heap_header h_free; /**< @brief Free blocks list header. */
+#if CH_USE_MUTEXES
+ Mutex h_mtx; /**< @brief Heap access mutex. */
+#else
+ Semaphore h_sem; /**< @brief Heap access semaphore. */
+#endif
+};
+
#ifdef __cplusplus
extern "C" {
#endif
void heap_init(void);
- void *chHeapAlloc(size_t size);
+ void chHeapInit(MemoryHeap *heapp, void *buf, size_t size);
+ void *chHeapAlloc(MemoryHeap *heapp, size_t size);
void chHeapFree(void *p);
- size_t chHeapStatus(size_t *sizep);
+ size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep);
#ifdef __cplusplus
}
#endif
+#endif /* CH_USE_HEAP */
+
#endif /* _HEAP_H_ */
/** @} */
diff --git a/os/kernel/include/mem.h b/os/kernel/include/memcore.h
index c7f5ba07a..8f3fe4671 100644
--- a/os/kernel/include/mem.h
+++ b/os/kernel/include/memcore.h
@@ -18,16 +18,16 @@
*/
/**
- * @file mem.h
- * @brief Low level memory manager macros and structures.
- * @addtogroup coremem
+ * @file memcore.h
+ * @brief Core memory manager macros and structures.
+ * @addtogroup memcore
* @{
*/
-#ifndef _MEM_H_
-#define _MEM_H_
+#ifndef _MEMCORE_H_
+#define _MEMCORE_H_
-#if CH_USE_COREMEM
+#if CH_USE_MEMCORE
/**
* @brief Memory alignment type.
@@ -35,6 +35,13 @@
typedef void *align_t;
/**
+ * @brief Memory get function.
+ * @note This type must be assignment compatible with the @p chMemAlloc()
+ * function.
+ */
+typedef void *(*memgetfunc_t)(size_t size);
+
+/**
* @brief Alignment mask constant.
*/
#define MEM_ALIGN_MASK (sizeof(align_t) - 1)
@@ -42,20 +49,26 @@ typedef void *align_t;
/**
* @brief Alignment helper macro.
*/
-#define MEM_ALIGN_SIZE(p) (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK)
+#define MEM_ALIGN_SIZE(p) (((size_t)(p) + MEM_ALIGN_MASK) & ~MEM_ALIGN_MASK)
+
+/**
+ * @brief Returns whatever a pointer or memory size is aligned to
+ * the type @p align_t.
+ */
+#define MEM_IS_ALIGNED(p) (((size_t)(p) & MEM_ALIGN_MASK) == 0)
#ifdef __cplusplus
extern "C" {
#endif
- void mem_init(void);
- void *chMemAlloc(size_t size);
- void *chMemAllocI(size_t size);
+ void core_init(void);
+ void *chCoreAlloc(size_t size);
+ void *chCoreAllocI(size_t size);
#ifdef __cplusplus
}
#endif
-#endif /* CH_USE_COREMEM */
+#endif /* CH_USE_MEMCORE */
-#endif /* _MEM_H_ */
+#endif /* _MEMCORE_H_ */
/** @} */
diff --git a/os/kernel/include/threads.h b/os/kernel/include/threads.h
index 1b9850435..ccafc3e96 100644
--- a/os/kernel/include/threads.h
+++ b/os/kernel/include/threads.h
@@ -167,8 +167,8 @@ extern "C" {
Thread *chThdCreateStatic(void *wsp, size_t size,
tprio_t prio, tfunc_t pf, void *arg);
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
- Thread *chThdCreateFromHeap(size_t size, tprio_t prio,
- tfunc_t pf, void *arg);
+ Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg);
#endif
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
diff --git a/os/kernel/kernel.mk b/os/kernel/kernel.mk
index adbe0af9c..47c8bb1d4 100644
--- a/os/kernel/kernel.mk
+++ b/os/kernel/kernel.mk
@@ -13,6 +13,7 @@ KERNSRC = ${CHIBIOS}/os/kernel/src/chsys.c \
${CHIBIOS}/os/kernel/src/chmsg.c \
${CHIBIOS}/os/kernel/src/chmboxes.c \
${CHIBIOS}/os/kernel/src/chqueues.c \
+ ${CHIBIOS}/os/kernel/src/chmemcore.c \
${CHIBIOS}/os/kernel/src/chheap.c \
${CHIBIOS}/os/kernel/src/chmempools.c
diff --git a/os/kernel/src/chheap.c b/os/kernel/src/chheap.c
index b5ad50505..e7a975f3d 100644
--- a/os/kernel/src/chheap.c
+++ b/os/kernel/src/chheap.c
@@ -28,41 +28,23 @@
#if CH_USE_HEAP
-#if !CH_USE_MALLOC_HEAP
-
-#define MAGIC 0xF5A0
-#define ALIGN_TYPE void *
-#define ALIGN_MASK (sizeof(ALIGN_TYPE) - 1)
-#define ALIGN_SIZE(p) (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK)
-
-struct header {
- union {
- struct header *h_next;
- size_t h_magic;
- };
- size_t h_size;
-};
-
-static struct {
- struct header free; /* Guaranteed to be not adjacent to the heap */
+/*
+ * Defaults on the best synchronization mechanism available.
+ */
#if CH_USE_MUTEXES
-#define H_LOCK() chMtxLock(&heap.hmtx)
-#define H_UNLOCK() chMtxUnlock()
- Mutex hmtx;
-#elif CH_USE_SEMAPHORES
-#define H_LOCK() chSemWait(&heap.hsem)
-#define H_UNLOCK() chSemSignal(&heap.hsem)
- Semaphore hsem;
+#define H_LOCK(h) chMtxLock(&(h)->h_mtx)
+#define H_UNLOCK(h) chMtxUnlock()
#else
-#error "The heap allocator requires mutexes or semaphores to be enabled"
+#define H_LOCK(h) chSemWait(&(h)->h_sem)
+#define H_UNLOCK(h) chSemSignal(&(h)->h_sem)
#endif
-#if CH_HEAP_SIZE > 0
- union {
- ALIGN_TYPE alignment;
- char buffer[ALIGN_SIZE(CH_HEAP_SIZE)];
- };
-#endif
-} heap;
+
+#if !CH_USE_MALLOC_HEAP
+
+/**
+ * @brief Default heap descriptor.
+ */
+static MemoryHeap default_heap;
/**
* @brief Initializes the allocator subsystem.
@@ -70,26 +52,40 @@ static struct {
* @note Internal use only.
*/
void heap_init(void) {
- struct header *hp;
-
-#if CH_HEAP_SIZE == 0
- extern char __heap_base__;
- extern char __heap_end__;
-
- hp = (void *)&__heap_base__;
- hp->h_size = &__heap_end__ - &__heap_base__ - sizeof(struct header);
+ default_heap.h_provider = chCoreAlloc;
+ default_heap.h_free.h_next = NULL;
+ default_heap.h_free.h_size = 0;
+#if CH_USE_MUTEXES
+ chMtxInit(&default_heap.h_mtx);
#else
- hp = (void *)&heap.buffer[0];
- hp->h_size = (&heap.buffer[ALIGN_SIZE(CH_HEAP_SIZE)] - &heap.buffer[0]) -
- sizeof(struct header);
+ chSemInit(&default_heap.h_sem, 1);
#endif
+}
+
+/**
+ * @brief Initializes a memory heap.
+ *
+ * @param[out] heapp pointer to a memory heap descriptor to be initialized
+ * @param[in] buf heap buffer base
+ * @param[in] size heap size
+ *
+ * @note Both the heap buffer base and the heap size must be aligned to
+ * the @p align_t type size.
+ */
+void chHeapInit(MemoryHeap *heapp, void *buf, size_t size) {
+ struct heap_header *hp;
+
+ chDbgCheck(MEM_IS_ALIGNED(buf) && MEM_IS_ALIGNED(size), "chHeapInit");
+
+ heapp->h_provider = NULL;
+ heapp->h_free.h_next = hp = buf;
+ heapp->h_free.h_size = 0;
hp->h_next = NULL;
- heap.free.h_next = hp;
- heap.free.h_size = 0;
+ hp->h_size = size - sizeof(struct heap_header);
#if CH_USE_MUTEXES
- chMtxInit(&heap.hmtx);
+ chMtxInit(&heapp->h_mtx);
#else
- chSemInit(&heap.hsem, 1);
+ chSemInit(&heapp->h_sem, 1);
#endif
}
@@ -97,53 +93,75 @@ void heap_init(void) {
* @brief Allocates a block of memory from the heap by using the first-fit
* algorithm.
* @details The allocated block is guaranteed to be properly aligned for a
- * pointer data type.
+ * pointer data type (@p align_t).
*
+ * @param[in] heapp pointer to a heap descriptor or @p NULL in order to access
+ * the default heap.
* @param[in] size the size of the block to be allocated. Note that the
* allocated block may be a bit bigger than the requested
* size for alignment and fragmentation reasons.
* @return A pointer to the allocated block.
* @retval NULL if the block cannot be allocated.
*/
-void *chHeapAlloc(size_t size) {
- struct header *qp, *hp, *fp;
+void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
+ struct heap_header *qp, *hp, *fp;
- size = ALIGN_SIZE(size);
- qp = &heap.free;
- H_LOCK();
+ if (heapp == NULL)
+ heapp = &default_heap;
+
+ size = MEM_ALIGN_SIZE(size);
+ qp = &heapp->h_free;
+ H_LOCK(heapp);
while (qp->h_next != NULL) {
hp = qp->h_next;
if (hp->h_size >= size) {
- if (hp->h_size < size + sizeof(struct header)) {
- /* Gets the whole block even if it is slightly bigger than the
- requested size because the fragment would be too small to be
- useful */
+ if (hp->h_size < size + sizeof(struct heap_header)) {
+ /*
+ * Gets the whole block even if it is slightly bigger than the
+ * requested size because the fragment would be too small to be
+ * useful.
+ */
qp->h_next = hp->h_next;
}
else {
- /* Block bigger enough, must split it */
- fp = (void *)((char *)(hp) + sizeof(struct header) + size);
+ /*
+ * Block bigger enough, must split it.
+ */
+ fp = (void *)((uint8_t *)(hp) + sizeof(struct heap_header) + size);
fp->h_next = hp->h_next;
- fp->h_size = hp->h_size - sizeof(struct header) - size;
+ fp->h_size = hp->h_size - sizeof(struct heap_header) - size;
qp->h_next = fp;
hp->h_size = size;
}
- hp->h_magic = MAGIC;
+ hp->h_heap = heapp;
- H_UNLOCK();
+ H_UNLOCK(heapp);
return (void *)(hp + 1);
}
qp = hp;
}
- H_UNLOCK();
+ H_UNLOCK(heapp);
+
+ /*
+ * More memory is required, tries to get it from the associated provider.
+ */
+ if (heapp->h_provider) {
+ hp = heapp->h_provider(size + sizeof(struct heap_header));
+ if (hp != NULL) {
+ hp->h_heap = heapp;
+ hp->h_size = size;
+ hp++;
+ return (void *)hp;
+ }
+ }
return NULL;
}
-#define LIMIT(p) (struct header *)((char *)(p) + \
- sizeof(struct header) + \
- (p)->h_size)
+#define LIMIT(p) (struct heap_header *)((uint8_t *)(p) + \
+ sizeof(struct heap_header) + \
+ (p)->h_size)
/**
* @brief Frees a previously allocated memory block.
@@ -151,50 +169,59 @@ void *chHeapAlloc(size_t size) {
* @param[in] p the memory block pointer
*/
void chHeapFree(void *p) {
- struct header *qp, *hp;
+ struct heap_header *qp, *hp;
+ MemoryHeap *heapp;
chDbgCheck(p != NULL, "chHeapFree");
- hp = (struct header *)p - 1;
- chDbgAssert(hp->h_magic == MAGIC,
- "chHeapFree(), #1",
- "it is not magic");
- qp = &heap.free;
- H_LOCK();
+ hp = (struct heap_header *)p - 1;
+ heapp = hp->h_heap;
+ qp = &heapp->h_free;
+ H_LOCK(heapp);
while (TRUE) {
-
chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
- "chHeapFree(), #2",
+ "chHeapFree(), #1",
"within free block");
- if (((qp == &heap.free) || (hp > qp)) &&
+ if (((qp == &heapp->h_free) || (hp > qp)) &&
((qp->h_next == NULL) || (hp < qp->h_next))) {
- /* Insertion after qp */
+ /*
+ * Insertion after qp.
+ */
hp->h_next = qp->h_next;
qp->h_next = hp;
- /* Verifies if the newly inserted block should be merged */
+ /*
+ * Verifies if the newly inserted block should be merged.
+ */
if (LIMIT(hp) == hp->h_next) {
- /* Merge with the next block */
- hp->h_size += hp->h_next->h_size + sizeof(struct header);
+ /*
+ * Merge with the next block.
+ */
+ hp->h_size += hp->h_next->h_size + sizeof(struct heap_header);
hp->h_next = hp->h_next->h_next;
}
- if ((LIMIT(qp) == hp)) { /* Cannot happen when qp == &heap.free */
- /* Merge with the previous block */
- qp->h_size += hp->h_size + sizeof(struct header);
+ if ((LIMIT(qp) == hp)) {
+ /*
+ * Merge with the previous block.
+ */
+ qp->h_size += hp->h_size + sizeof(struct heap_header);
qp->h_next = hp->h_next;
}
-
- H_UNLOCK();
- return;
+ break;
}
qp = qp->h_next;
}
+
+ H_UNLOCK(heapp);
+ return;
}
/**
* @brief Reports the heap status.
*
+ * @param[in] heapp pointer to a heap descriptor or @p NULL in order to access
+ * the default heap.
* @param[in] sizep pointer to a variable that will receive the total
* fragmented free space
* @return The number of fragments in the heap.
@@ -203,19 +230,22 @@ void chHeapFree(void *p) {
* @note This function is not implemented when the @p CH_USE_MALLOC_HEAP
* configuration option is used (it always returns zero).
*/
-size_t chHeapStatus(size_t *sizep) {
- struct header *qp;
+size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
+ struct heap_header *qp;
size_t n, sz;
- H_LOCK();
+ if (heapp == NULL)
+ heapp = &default_heap;
+
+ H_LOCK(heapp);
sz = 0;
- for (n = 0, qp = &heap.free; qp->h_next; n++, qp = qp->h_next)
+ for (n = 0, qp = &heapp->h_free; qp->h_next; n++, qp = qp->h_next)
sz += qp->h_next->h_size;
if (sizep)
*sizep = sz;
- H_UNLOCK();
+ H_UNLOCK(heapp);
return n;
}
@@ -231,8 +261,6 @@ static Mutex hmtx;
#define H_LOCK() chSemWait(&hsem)
#define H_UNLOCK() chSemSignal(&hsem)
static Semaphore hsem;
-#else
-#error "The heap allocator requires mutexes or semaphores to be enabled"
#endif
void heap_init(void) {
@@ -244,9 +272,11 @@ void heap_init(void) {
#endif
}
-void *chHeapAlloc(size_t size) {
+void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
void *p;
+ chDbgCheck(heapp == NULL, "chHeapAlloc");
+
H_LOCK();
p = malloc(size);
H_UNLOCK();
@@ -262,7 +292,9 @@ void chHeapFree(void *p) {
H_UNLOCK();
}
-size_t chHeapStatus(size_t *sizep) {
+size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
+
+ chDbgCheck(heapp == NULL, "chHeapStatus");
if (sizep)
*sizep = 0;
diff --git a/os/kernel/src/chmem.c b/os/kernel/src/chmemcore.c
index 3ac45a6ae..87ef6037a 100644
--- a/os/kernel/src/chmem.c
+++ b/os/kernel/src/chmemcore.c
@@ -18,33 +18,38 @@
*/
/**
- * @file chmem.c
- * @brief Low level memory manager code.
- * @addtogroup coremem
+ * @file chmemcore.c
+ * @brief Core memory manager code.
+ * @addtogroup memcore
* @{
*/
#include <ch.h>
-#if CH_USE_COREMEM
+#if CH_USE_MEMCORE
-#if CH_COREMEM_SIZE == 0
+#if CH_MEMCORE_SIZE == 0
extern align_t __heap_base__;
extern align_t __heap_end__;
#else
-align_t buffer[ALIGN_SIZE(CH_MEM_SIZE) / sizeof(align_t)];
+align_t buffer[ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)];
#endif
static align_t *nextmem;
static align_t *endmem;
-void mem_init(void) {
-#if CH_COREMEM_SIZE == 0
+/**
+ * @brief Low level memory manager initialization.
+ *
+ * @note Internal use only.
+ */
+void core_init(void) {
+#if CH_MEMCORE_SIZE == 0
nextmem = &__heap_base__;
endmem = &__heap_end__;
#else
nextmem = &buffer[0];
- endmem = &buffer[ALIGN_SIZE(CH_MEM_SIZE) / sizeof(align_t)];
+ endmem = &buffer[ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)];
#endif
}
@@ -81,7 +86,7 @@ void *chCoreAlloc(size_t size) {
void *chCoreAllocI(size_t size) {
void *p;
- size = ALIGN_SIZE(size);
+ size = MEM_ALIGN_SIZE(size);
if (nextmem + size > endmem)
return NULL;
p = nextmem;
@@ -89,6 +94,6 @@ void *chCoreAllocI(size_t size) {
return p;
}
-#endif /* CH_USE_COREMEM */
+#endif /* CH_USE_MEMCORE */
/** @} */
diff --git a/os/kernel/src/chsys.c b/os/kernel/src/chsys.c
index 8ee7375f8..7d42eb644 100644
--- a/os/kernel/src/chsys.c
+++ b/os/kernel/src/chsys.c
@@ -61,6 +61,9 @@ void chSysInit(void) {
port_init();
scheduler_init();
vt_init();
+#if CH_USE_MEMCORE
+ core_init();
+#endif
#if CH_USE_HEAP
heap_init();
#endif
diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c
index a3028867a..89d1d6329 100644
--- a/os/kernel/src/chthreads.c
+++ b/os/kernel/src/chthreads.c
@@ -124,6 +124,8 @@ Thread *chThdCreateStatic(void *wsp, size_t size,
/**
* @brief Creates a new thread allocating the memory from the heap.
*
+ * @param[in] heapp heap from which allocate the memory or NULL for the
+ * default heap
* @param[in] size size of the working area to be allocated
* @param[in] prio the priority level for the new thread
* @param[in] pf the thread function
@@ -139,11 +141,12 @@ Thread *chThdCreateStatic(void *wsp, size_t size,
* @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled
* in @p chconf.h.
*/
-Thread *chThdCreateFromHeap(size_t size, tprio_t prio, tfunc_t pf, void *arg) {
+Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg) {
void *wsp;
Thread *tp;
- wsp = chHeapAlloc(size);
+ wsp = chHeapAlloc(heapp, size);
if (wsp == NULL)
return NULL;
tp = chThdInit(wsp, size, prio, pf, arg);
diff --git a/os/kernel/templates/chconf.h b/os/kernel/templates/chconf.h
index 819d3d1d0..31c3c7a50 100644
--- a/os/kernel/templates/chconf.h
+++ b/os/kernel/templates/chconf.h
@@ -32,29 +32,36 @@
/*===========================================================================*/
/**
- * Frequency of the system timer that drives the system ticks. This also
- * defines the system tick time unit.
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
*/
#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000
#endif
/**
- * This constant is the number of system ticks allowed for the threads before
- * preemption occurs. This option is only meaningful if the option
- * @p CH_USE_ROUNDROBIN is also active.
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the round robin mechanism.
+ *
+ * @note Disabling round robin makes the kernel more compact and generally
+ * faster but forbids multiple threads at the same priority level.
*/
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20
#endif
/**
- * If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
- * operations is allowed.<br>
- * For performance and code size reasons the recommended setting is to leave
- * this option disabled.<br>
- * You can use this option if you need to merge ChibiOS/RT with external
- * libraries that require nested lock/unlock operations.
+ * @brief Nested locks.
+ * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
+ * operations is allowed.<br>
+ * For performance and code size reasons the recommended setting
+ * is to leave this option disabled.<br>
+ * You may use this option if you need to merge ChibiOS/RT with
+ * external libraries that require nested lock/unlock operations.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@@ -62,23 +69,18 @@
#endif
/**
- * If specified then the kernel performs the round robin scheduling algorithm
- * on threads of equal priority.
- * @note The default is @p TRUE.
- */
-#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__)
-#define CH_USE_ROUNDROBIN TRUE
-#endif
-
-/**
- * Number of RAM bytes to use as system heap. If set to zero then the whole
- * available RAM is used as system heap.
- * @note In order to use the whole RAM as system heap the linker script must
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
- * @note Requires @p CH_USE_HEAP.
+ * @note Requires @p CH_USE_COREMEM.
*/
-#if !defined(CH_HEAP_SIZE) || defined(__DOXYGEN__)
-#define CH_HEAP_SIZE 0
+#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
+#define CH_MEMCORE_SIZE 0
#endif
/*===========================================================================*/
@@ -86,8 +88,10 @@
/*===========================================================================*/
/**
- * If specified then time efficient rather than space efficient code is used
- * when two possible implementations exist.
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
@@ -96,18 +100,20 @@
#endif
/**
- * If enabled defines a CPU register to be used as storage for the global
- * @p currp variable. Caching this variable in a register can greatly
- * improve both space and time efficiency of the generated code. Another side
- * effect is that one less register has to be saved during the context switch
- * resulting in lower RAM usage and faster code.
+ * @brief Exotic optimization.
+ * @details If defined then a CPU register is used as storage for the global
+ * @p currp variable. Caching this variable in a register greatly
+ * improves both space and time OS efficiency. A side effect is that
+ * one less register has to be saved during the context switch
+ * resulting in lower RAM usage and faster context switch.
+ *
* @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the
* ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for
- * documentation.
+ * documentation only.
*/
#if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg"
@@ -118,7 +124,10 @@
/*===========================================================================*/
/**
- * If specified then the @p chThdWait() function is included in the kernel.
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@@ -126,7 +135,9 @@
#endif
/**
- * If specified then the Semaphores APIs are included in the kernel.
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@@ -134,8 +145,10 @@
#endif
/**
- * If enabled then the threads are enqueued on semaphores by priority rather
- * than FIFO order.
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -144,8 +157,10 @@
#endif
/**
- * If specified then the Semaphores the @p chSemWaitSignal() API is included
- * in the kernel.
+ * @brief Atomic semaphore API.
+ * @details If enabled then the semaphores the @p chSemWaitSignal() API
+ * is included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -154,7 +169,9 @@
#endif
/**
- * If specified then the Mutexes APIs are included in the kernel.
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@@ -162,7 +179,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES.
*/
@@ -171,7 +191,10 @@
#endif
/**
- * If specified then the Conditional Variables APIs are included in the kernel.
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS.
*/
@@ -180,7 +203,9 @@
#endif
/**
- * If specified then the Event flags APIs are included in the kernel.
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@@ -188,8 +213,10 @@
#endif
/**
- * If specified then the @p chEvtWaitXXXTimeout() functions are included in
- * the kernel.
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS.
*/
@@ -198,7 +225,10 @@
#endif
/**
- * If specified then the Synchronous Messages APIs are included in the kernel.
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@@ -206,7 +236,10 @@
#endif
/**
- * If enabled then messages are served by priority rather than in FIFO order.
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
* @note The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES.
*/
@@ -215,8 +248,10 @@
#endif
/**
- * If specified then the Asynchronous Messages (Mailboxes) APIs are included
- * in the kernel.
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -225,7 +260,9 @@
#endif
/**
- * If specified then the I/O queues APIs are included in the kernel.
+ * @brief I/O Queues APIs.
+ * @details If enabled then the I/O queues APIs are included in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/
@@ -234,9 +271,24 @@
#endif
/**
- * If specified then the memory heap allocator APIs are included in the kernel.
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
- * @note Requires @p CH_USE_MUTEXES or @p CH_USE_SEMAPHORES.
+ */
+#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
+#define CH_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_COREMEM and either @p CH_USE_MUTEXES or
+ * @p CH_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@@ -244,18 +296,24 @@
#endif
/**
- * If enabled enforces the use of the C-runtime @p malloc() and @p free()
- * functions as backend for the system heap allocator.
+ * @brief C-runtime allocator.
+ * @details If enabled the the heap allocator APIs just wrap the C-runtime
+ * @p malloc() and @p free() functions.
+ *
* @note The default is @p FALSE.
* @note Requires @p CH_USE_HEAP.
+ * @note The C-runtime may or may not require @p CH_USE_COREMEM, see the
+ * appropriate documentation.
*/
#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE
#endif
/**
- * If specified then the memory pools allocator APIs are included in the
- * kernel.
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
*/
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@@ -263,8 +321,10 @@
#endif
/**
- * If specified then the dynamic threads creation APIs are included in the
- * kernel.
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
* @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT.
*/
@@ -277,8 +337,10 @@
/*===========================================================================*/
/**
- * Debug option, if enabled then the checks on the API functions input
- * parameters are activated.
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@@ -286,9 +348,11 @@
#endif
/**
- * Debug option, if enabled then all the assertions in the kernel code are
- * activated. This includes consistency checks inside the kernel, runtime
- * anomalies and port-defined checks.
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@@ -296,8 +360,10 @@
#endif
/**
- * Debug option, if enabled the context switch circular trace buffer is
- * activated.
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the context switch circular trace buffer is
+ * activated.
+ *
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@@ -305,25 +371,37 @@
#endif
/**
- * Debug option, if enabled a runtime stack check is performed.
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way. It
- * may not be implemented at all.
+ * may not be implemented or some ports.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif
/**
- * Debug option, if enabled the threads working area is filled with a byte
- * pattern when a thread is created.
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE
#endif
/**
- * Debug option, if enabled a field is added to the @p Thread structure that
- * counts the system ticks occurred while executing the thread.
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p Thread structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p TRUE.
+ * @note This debug option is defaulted to TRUE because it is required by
+ * some test cases into the test suite.
*/
#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE
@@ -334,38 +412,46 @@
/*===========================================================================*/
/**
- * User fields added to the end of the @p Thread structure.
+ * @brief Threads descriptor structure hook.
+ * @details User fields added to the end of the @p Thread structure.
*/
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \
struct { \
- /* Add thread custom fields here.*/ \
+ /* Add threads custom fields here.*/ \
};
#endif
/**
- * User initialization code added to the @p chThdInit() API.
- * @note It is invoked from within @p chThdInit().
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitily from all
+ * the threads creation APIs.
*/
#if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \
- /* Add thread initialization code here.*/ \
+ /* Add threads initialization code here.*/ \
}
#endif
/**
- * User finalization code added to the @p chThdExit() API.
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
* @note It is inserted into lock zone.
+ * @note It is also invoked when the threads simply return in order to
+ * terminate.
*/
#if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \
- /* Add thread finalization code here.*/ \
+ /* Add threads finalization code here.*/ \
}
#endif
/**
- * Code inserted inside the idle thread loop immediately after an interrupt
- * resumed execution.
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
*/
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \
diff --git a/readme.txt b/readme.txt
index 676f9918b..f361bde0c 100644
--- a/readme.txt
+++ b/readme.txt
@@ -7,6 +7,15 @@
Removed the old EMAC driver, updated the uIP WEB demo to use the new
driver model.
- NEW: Added a simple lwIP demo (web server) for the AT91SAM7X.
+- NEW: Centralized memory heap manager. This simple allocator implements a
+ sbrk()-like API: chCoreAlloc(). The other allocators now use this manager
+ in order to get memory blocks.
+- NEW: The heap allocator has been modified, now it is possible to have
+ multiple heaps. The default heap gets its memory from the new heap manager.
+- CHANGE: Because the changes in the allocators some API prototypes changed:
+ chHeapAlloc(), chHeapStatus(), chThdCreateFromHeap().
+- CHANGE: Because the changes in the allocators some configuration options
+ changed, see the template chconf.h file.
- CHANGE: renamed ./demos/ARM7-AT91SAM7X-WEB-GCC in ARM7-AT91SAM7X-UIP-GCC.
*** 1.3.2 ***
diff --git a/test/test.c b/test/test.c
index 434ef1b8c..bbeb9adc4 100644
--- a/test/test.c
+++ b/test/test.c
@@ -59,11 +59,7 @@ static char *tokp;
* Static working areas, the following areas can be used for threads or
* used as temporary buffers.
*/
-WORKING_AREA(waT0, THREADS_STACK_SIZE);
-WORKING_AREA(waT1, THREADS_STACK_SIZE);
-WORKING_AREA(waT2, THREADS_STACK_SIZE);
-WORKING_AREA(waT3, THREADS_STACK_SIZE);
-WORKING_AREA(waT4, THREADS_STACK_SIZE);
+union test_buffers test;
/*
* Pointers to the spawned threads.
@@ -73,7 +69,7 @@ Thread *threads[MAX_THREADS];
/*
* Pointers to the working areas.
*/
-void * const wa[5] = {waT0, waT1, waT2, waT3, waT4};
+void * const wa[5] = {test.waT0, test.waT1, test.waT2, test.waT3, test.waT4};
/*
* Console output.
diff --git a/test/test.h b/test/test.h
index fca9da8b1..7b261b553 100644
--- a/test/test.h
+++ b/test/test.h
@@ -47,6 +47,17 @@ struct testcase {
void (*execute)(void);
};
+union test_buffers {
+ struct {
+ WORKING_AREA(waT0, THREADS_STACK_SIZE);
+ WORKING_AREA(waT1, THREADS_STACK_SIZE);
+ WORKING_AREA(waT2, THREADS_STACK_SIZE);
+ WORKING_AREA(waT3, THREADS_STACK_SIZE);
+ WORKING_AREA(waT4, THREADS_STACK_SIZE);
+ };
+ uint8_t buffer[WA_SIZE * 5];
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -94,11 +105,7 @@ extern "C" {
}
extern Thread *threads[MAX_THREADS];
-extern WORKING_AREA(waT0, THREADS_STACK_SIZE);
-extern WORKING_AREA(waT1, THREADS_STACK_SIZE);
-extern WORKING_AREA(waT2, THREADS_STACK_SIZE);
-extern WORKING_AREA(waT3, THREADS_STACK_SIZE);
-extern WORKING_AREA(waT4, THREADS_STACK_SIZE);
+extern union test_buffers test;
extern void * const wa[];
extern bool_t test_timer_done;
diff --git a/test/testdyn.c b/test/testdyn.c
index 44e6ffaa4..07c3f92a0 100644
--- a/test/testdyn.c
+++ b/test/testdyn.c
@@ -70,50 +70,56 @@ static msg_t thread(void *p) {
}
#if CH_USE_HEAP
+
+static MemoryHeap heap1;
+
static char *dyn1_gettest(void) {
return "Dynamic APIs, threads creation from heap";
}
+static void dyn1_setup(void) {
+
+ chHeapInit(&heap1, test.buffer, sizeof(union test_buffers));
+}
+
static void dyn1_execute(void) {
size_t n, sz;
void *p1;
tprio_t prio = chThdGetPriority();
- /* Test skipped if the heap is already fragmented. */
- if ((n = chHeapStatus(&sz)) == 1) {
- /* Starting threads from the heap. */
- threads[0] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE),
- prio-1, thread, "A");
- threads[1] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE),
- prio-2, thread, "B");
- /* Allocating the whole heap in order to make the thread creation fail.*/
- (void)chHeapStatus(&n);
- p1 = chHeapAlloc(n);
- threads[2] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE),
- prio-3, thread, "C");
- chHeapFree(p1);
-
- test_assert(1, (threads[0] != NULL) &&
- (threads[1] != NULL) &&
- (threads[2] == NULL) &&
- (threads[3] == NULL) &&
- (threads[4] == NULL),
- "thread creation failed");
-
- /* Claiming the memory from terminated threads. */
- test_wait_threads();
- test_assert_sequence(2, "AB");
-
- /* Heap status checked again.*/
- test_assert(3, chHeapStatus(&n) == 1, "heap fragmented");
- test_assert(4, n == sz, "heap size changed");
- }
+ (void)chHeapStatus(&heap1, &sz);
+ /* Starting threads from the heap. */
+ threads[0] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
+ prio-1, thread, "A");
+ threads[1] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
+ prio-2, thread, "B");
+ /* Allocating the whole heap in order to make the thread creation fail.*/
+ (void)chHeapStatus(&heap1, &n);
+ p1 = chHeapAlloc(&heap1, n);
+ threads[2] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
+ prio-3, thread, "C");
+ chHeapFree(p1);
+
+ test_assert(1, (threads[0] != NULL) &&
+ (threads[1] != NULL) &&
+ (threads[2] == NULL) &&
+ (threads[3] == NULL) &&
+ (threads[4] == NULL),
+ "thread creation failed");
+
+ /* Claiming the memory from terminated threads. */
+ test_wait_threads();
+ test_assert_sequence(2, "AB");
+
+ /* Heap status checked again.*/
+ test_assert(3, chHeapStatus(&heap1, &n) == 1, "heap fragmented");
+ test_assert(4, n == sz, "heap size changed");
}
const struct testcase testdyn1 = {
dyn1_gettest,
- NULL,
+ dyn1_setup,
NULL,
dyn1_execute
};
diff --git a/test/testheap.c b/test/testheap.c
index 6e68c11be..6545893ce 100644
--- a/test/testheap.c
+++ b/test/testheap.c
@@ -50,6 +50,8 @@
#define SIZE 16
+static MemoryHeap test_heap;
+
/**
* @page test_heap_001 Allocation and fragmentation test
*
@@ -66,74 +68,73 @@ static char *heap1_gettest(void) {
return "Heap, allocation and fragmentation test";
}
+static void heap1_setup(void) {
+
+ chHeapInit(&test_heap, test.buffer, sizeof(union test_buffers));
+}
+
static void heap1_execute(void) {
void *p1, *p2, *p3;
size_t n, sz;
/* Test skipped if the heap is already fragmented. */
- if ((n = chHeapStatus(&sz)) == 1) {
- test_print("--- Size : ");
- test_printn(sz);
- test_println(" bytes, not fragmented");
-
- /* Same order */
- p1 = chHeapAlloc(SIZE);
- p2 = chHeapAlloc(SIZE);
- p3 = chHeapAlloc(SIZE);
- chHeapFree(p1); /* Does not merge */
- chHeapFree(p2); /* Merges backward */
- chHeapFree(p3); /* Merges both sides */
- test_assert(1, chHeapStatus(&n) == 1, "heap fragmented");
-
- /* Reverse order */
- p1 = chHeapAlloc(SIZE);
- p2 = chHeapAlloc(SIZE);
- p3 = chHeapAlloc(SIZE);
- chHeapFree(p3); /* Merges forward */
- chHeapFree(p2); /* Merges forward */
- chHeapFree(p1); /* Merges forward */
- test_assert(2, chHeapStatus(&n) == 1, "heap fragmented");
-
- /* Small fragments handling */
- p1 = chHeapAlloc(SIZE + 1);
- p2 = chHeapAlloc(SIZE);
- chHeapFree(p1);
- test_assert(3, chHeapStatus(&n) == 2, "invalid state");
- p1 = chHeapAlloc(SIZE);
- test_assert(4, chHeapStatus(&n) == 1, "heap fragmented");
- chHeapFree(p2);
- chHeapFree(p1);
- test_assert(5, chHeapStatus(&n) == 1, "heap fragmented");
-
- /* Skip fragment handling */
- p1 = chHeapAlloc(SIZE);
- p2 = chHeapAlloc(SIZE);
- chHeapFree(p1);
- test_assert(6, chHeapStatus(&n) == 2, "invalid state");
- p1 = chHeapAlloc(SIZE * 2); /* Skips first fragment */
- chHeapFree(p1);
- chHeapFree(p2);
- test_assert(7, chHeapStatus(&n) == 1, "heap fragmented");
-
- /* Allocate all handling */
- (void)chHeapStatus(&n);
- p1 = chHeapAlloc(n);
- test_assert(8, chHeapStatus(&n) == 0, "not empty");
- chHeapFree(p1);
-
- test_assert(9, chHeapStatus(&n) == 1, "heap fragmented");
- test_assert(10, n == sz, "size changed");
- }
- else {
- test_print("--- Size : ");
- test_printn(sz);
- test_println(" bytes, fragmented, test skipped");
- }
+ (void)chHeapStatus(&test_heap, &sz);
+ test_print("--- Size : ");
+ test_printn(sz);
+ test_println(" bytes");
+
+ /* Same order */
+ p1 = chHeapAlloc(&test_heap, SIZE);
+ p2 = chHeapAlloc(&test_heap, SIZE);
+ p3 = chHeapAlloc(&test_heap, SIZE);
+ chHeapFree(p1); /* Does not merge */
+ chHeapFree(p2); /* Merges backward */
+ chHeapFree(p3); /* Merges both sides */
+ test_assert(1, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+
+ /* Reverse order */
+ p1 = chHeapAlloc(&test_heap, SIZE);
+ p2 = chHeapAlloc(&test_heap, SIZE);
+ p3 = chHeapAlloc(&test_heap, SIZE);
+ chHeapFree(p3); /* Merges forward */
+ chHeapFree(p2); /* Merges forward */
+ chHeapFree(p1); /* Merges forward */
+ test_assert(2, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+
+ /* Small fragments handling */
+ p1 = chHeapAlloc(&test_heap, SIZE + 1);
+ p2 = chHeapAlloc(&test_heap, SIZE);
+ chHeapFree(p1);
+ test_assert(3, chHeapStatus(&test_heap, &n) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, SIZE);
+ test_assert(4, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+ chHeapFree(p2);
+ chHeapFree(p1);
+ test_assert(5, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+
+ /* Skip fragment handling */
+ p1 = chHeapAlloc(&test_heap, SIZE);
+ p2 = chHeapAlloc(&test_heap, SIZE);
+ chHeapFree(p1);
+ test_assert(6, chHeapStatus(&test_heap, &n) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, SIZE * 2); /* Skips first fragment */
+ chHeapFree(p1);
+ chHeapFree(p2);
+ test_assert(7, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+
+ /* Allocate all handling */
+ (void)chHeapStatus(&test_heap, &n);
+ p1 = chHeapAlloc(&test_heap, n);
+ test_assert(8, chHeapStatus(&test_heap, &n) == 0, "not empty");
+ chHeapFree(p1);
+
+ test_assert(9, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
+ test_assert(10, n == sz, "size changed");
}
const struct testcase testheap1 = {
heap1_gettest,
- NULL,
+ heap1_setup,
NULL,
heap1_execute
};
diff --git a/test/testmbox.c b/test/testmbox.c
index 96cf543ce..3c23cf937 100644
--- a/test/testmbox.c
+++ b/test/testmbox.c
@@ -59,7 +59,7 @@
* variables are explicitly initialized in each test case. It is done in order
* to test the macros.
*/
-static MAILBOX_DECL(mb1, waT0, MB_SIZE);
+static MAILBOX_DECL(mb1, test.waT0, MB_SIZE);
/**
* @page test_mbox_001 Queuing and timeouts
@@ -77,7 +77,7 @@ static char *mbox1_gettest(void) {
static void mbox1_setup(void) {
- chMBInit(&mb1, (msg_t *)waT0, MB_SIZE);
+ chMBInit(&mb1, (msg_t *)test.waT0, MB_SIZE);
}
static void mbox1_execute(void) {
diff --git a/test/testqueues.c b/test/testqueues.c
index aff42334c..e5e3a4c0b 100644
--- a/test/testqueues.c
+++ b/test/testqueues.c
@@ -63,8 +63,8 @@ static void notify(void) {}
* variables are explicitly initialized in each test case. It is done in order
* to test the macros.
*/
-static INPUTQUEUE_DECL(iq, waT0, TEST_QUEUES_SIZE, notify);
-static OUTPUTQUEUE_DECL(oq, waT0, TEST_QUEUES_SIZE, notify);
+static INPUTQUEUE_DECL(iq, test.waT0, TEST_QUEUES_SIZE, notify);
+static OUTPUTQUEUE_DECL(oq, test.waT1, TEST_QUEUES_SIZE, notify);
/**
* @page test_queues_001 Input Queues functionality and APIs