New heap manager.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1221 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2009-10-16 17:45:19 +00:00
parent 8da7f367ee
commit 2c46df1916
20 changed files with 855 additions and 475 deletions

View File

@ -18,9 +18,9 @@
*/ */
/** /**
* @file src/templates/chconf.h * @file templates/chconf.h
* @brief Configuration file template. * @brief Configuration file template.
* @addtogroup Config * @addtogroup config
* @{ * @{
*/ */
@ -32,29 +32,36 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Frequency of the system timer that drives the system ticks. This also * @brief System tick frequency.
* defines the system tick time unit. * @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__) #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000 #define CH_FREQUENCY 1000
#endif #endif
/** /**
* This constant is the number of system ticks allowed for the threads before * @brief Round robin interval.
* preemption occurs. This option is only meaningful if the option * @details This constant is the number of system ticks allowed for the
* @p CH_USE_ROUNDROBIN is also active. * 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__) #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20 #define CH_TIME_QUANTUM 20
#endif #endif
/** /**
* If enabled then the use of nested @p chSysLock() / @p chSysUnlock() * @brief Nested locks.
* operations is allowed.<br> * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
* For performance and code size reasons the recommended setting is to leave * operations is allowed.<br>
* this option disabled.<br> * For performance and code size reasons the recommended setting
* You can use this option if you need to merge ChibiOS/RT with external * is to leave this option disabled.<br>
* libraries that require nested lock/unlock operations. * 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. * @note The default is @p FALSE.
*/ */
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__) #if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@ -62,23 +69,18 @@
#endif #endif
/** /**
* If specified then the kernel performs the round robin scheduling algorithm * @brief Managed RAM size.
* on threads of equal priority. * @details Size of the RAM area to be managed by the OS. If set to zero
* @note The default is @p TRUE. * then the whole available RAM is used. The core memory is made
*/ * available to the heap allocator and/or can be used directly through
#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__) * the simplified core memory allocator.
#define CH_USE_ROUNDROBIN TRUE *
#endif * @note In order to let the OS manage the whole RAM the linker script must
/**
* 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
* provide the @p __heap_base__ and @p __heap_end__ symbols. * 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__) #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_HEAP_SIZE 0 #define CH_MEMCORE_SIZE 0
#endif #endif
/*===========================================================================*/ /*===========================================================================*/
@ -86,8 +88,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* If specified then time efficient rather than space efficient code is used * @brief OS optimization.
* when two possible implementations exist. * @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 This is not related to the compiler optimization options.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
@ -96,18 +100,20 @@
#endif #endif
/** /**
* If enabled defines a CPU register to be used as storage for the global * @brief Exotic optimization.
* @p currp variable. Caching this variable in a register can greatly * @details If defined then a CPU register is used as storage for the global
* improve both space and time efficiency of the generated code. Another side * @p currp variable. Caching this variable in a register greatly
* effect is that one less register has to be saved during the context switch * improves both space and time OS efficiency. A side effect is that
* resulting in lower RAM usage and faster code. * 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 * @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores. * on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the * @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 * ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>. * -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for * @note This option must be enabled in the Makefile, it is listed here for
* documentation. * documentation only.
*/ */
#if defined(__DOXYGEN__) #if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg" #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@ -126,7 +135,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@ -134,8 +145,10 @@
#endif #endif
/** /**
* If enabled then the threads are enqueued on semaphores by priority rather * @brief Semaphores queuing mode.
* than FIFO order. * @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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -144,8 +157,10 @@
#endif #endif
/** /**
* If specified then the Semaphores the @p chSemWaitSignal() API is included * @brief Atomic semaphore API.
* in the kernel. * @details If enabled then the semaphores the @p chSemWaitSignal() API
* is included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -154,7 +169,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@ -162,7 +179,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES. * @note Requires @p CH_USE_MUTEXES.
*/ */
@ -171,7 +191,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS. * @note Requires @p CH_USE_CONDVARS.
*/ */
@ -180,7 +203,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@ -188,8 +213,10 @@
#endif #endif
/** /**
* If specified then the @p chEvtWaitXXXTimeout() functions are included in * @brief Events Flags APIs with timeout.
* the kernel. * @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS. * @note Requires @p CH_USE_EVENTS.
*/ */
@ -198,7 +225,10 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@ -206,7 +236,10 @@
#endif #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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES. * @note Requires @p CH_USE_MESSAGES.
*/ */
@ -215,16 +248,21 @@
#endif #endif
/** /**
* If specified then the Asynchronous Messages (Mailboxes) APIs are included * @brief Mailboxes APIs.
* in the kernel. * @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/ */
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) #if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
#define CH_USE_MAILBOXES TRUE #define CH_USE_MAILBOXES TRUE
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -233,9 +271,24 @@
#endif #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 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. * @note Mutexes are recommended.
*/ */
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@ -243,18 +296,24 @@
#endif #endif
/** /**
* If enabled enforces the use of the C-runtime @p malloc() and @p free() * @brief C-runtime allocator.
* functions as backend for the system heap 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 The default is @p FALSE.
* @note Requires @p CH_USE_HEAP. * @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__) #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE #define CH_USE_MALLOC_HEAP FALSE
#endif #endif
/** /**
* If specified then the memory pools allocator APIs are included in the * @brief Memory Pools Allocator APIs.
* kernel. * @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@ -262,8 +321,10 @@
#endif #endif
/** /**
* If specified then the dynamic threads creation APIs are included in the * @brief Dynamic Threads APIs.
* kernel. * @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT. * @note Requires @p CH_USE_WAITEXIT.
*/ */
@ -276,8 +337,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Debug option, if enabled then the checks on the API functions input * @brief Debug option, parameters checks.
* parameters are activated. * @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@ -285,9 +348,11 @@
#endif #endif
/** /**
* Debug option, if enabled then all the assertions in the kernel code are * @brief Debug option, consistency checks.
* activated. This includes consistency checks inside the kernel, runtime * @details If enabled then all the assertions in the kernel code are
* anomalies and port-defined checks. * activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@ -295,8 +360,10 @@
#endif #endif
/** /**
* Debug option, if enabled the context switch circular trace buffer is * @brief Debug option, trace buffer.
* activated. * @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@ -304,25 +371,37 @@
#endif #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 * @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__) #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE #define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif #endif
/** /**
* Debug option, if enabled the threads working area is filled with a byte * @brief Debug option, stacks initialization.
* pattern when a thread is created. * @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__) #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE #define CH_DBG_FILL_THREADS FALSE
#endif #endif
/** /**
* Debug option, if enabled a field is added to the @p Thread structure that * @brief Debug option, threads profiling.
* counts the system ticks occurred while executing the thread. * @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__) #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE #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__) #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \ #define THREAD_EXT_FIELDS \
struct { \ struct { \
/* Add thread custom fields here.*/ \ /* Add threads custom fields here.*/ \
}; };
#endif #endif
/** /**
* User initialization code added to the @p chThdInit() API. * @brief Threads initialization hook.
* @note It is invoked from within @p chThdInit(). * @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__) #if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \ #define THREAD_EXT_INIT(tp) { \
/* Add thread initialization code here.*/ \ /* Add threads initialization code here.*/ \
} }
#endif #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 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__) #if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \ #define THREAD_EXT_EXIT(tp) { \
/* Add thread finalization code here.*/ \ /* Add threads finalization code here.*/ \
} }
#endif #endif
/** /**
* Code inserted inside the idle thread loop immediately after an interrupt * @brief Idle Loop hook.
* resumed execution. * @details This hook is continuously invoked by the idle thread loop.
*/ */
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \ #define IDLE_LOOP_HOOK() { \

View File

@ -18,9 +18,9 @@
*/ */
/** /**
* @file src/templates/chconf.h * @file templates/chconf.h
* @brief Configuration file template. * @brief Configuration file template.
* @addtogroup Config * @addtogroup config
* @{ * @{
*/ */
@ -32,29 +32,36 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Frequency of the system timer that drives the system ticks. This also * @brief System tick frequency.
* defines the system tick time unit. * @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__) #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000 #define CH_FREQUENCY 1000
#endif #endif
/** /**
* This constant is the number of system ticks allowed for the threads before * @brief Round robin interval.
* preemption occurs. This option is only meaningful if the option * @details This constant is the number of system ticks allowed for the
* @p CH_USE_ROUNDROBIN is also active. * 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__) #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20 #define CH_TIME_QUANTUM 20
#endif #endif
/** /**
* If enabled then the use of nested @p chSysLock() / @p chSysUnlock() * @brief Nested locks.
* operations is allowed.<br> * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
* For performance and code size reasons the recommended setting is to leave * operations is allowed.<br>
* this option disabled.<br> * For performance and code size reasons the recommended setting
* You can use this option if you need to merge ChibiOS/RT with external * is to leave this option disabled.<br>
* libraries that require nested lock/unlock operations. * 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. * @note The default is @p FALSE.
*/ */
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__) #if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@ -62,23 +69,18 @@
#endif #endif
/** /**
* If specified then the kernel performs the round robin scheduling algorithm * @brief Managed RAM size.
* on threads of equal priority. * @details Size of the RAM area to be managed by the OS. If set to zero
* @note The default is @p TRUE. * then the whole available RAM is used. The core memory is made
*/ * available to the heap allocator and/or can be used directly through
#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__) * the simplified core memory allocator.
#define CH_USE_ROUNDROBIN TRUE *
#endif * @note In order to let the OS manage the whole RAM the linker script must
/**
* 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
* provide the @p __heap_base__ and @p __heap_end__ symbols. * 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__) #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_HEAP_SIZE 0 #define CH_MEMCORE_SIZE 0
#endif #endif
/*===========================================================================*/ /*===========================================================================*/
@ -86,8 +88,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* If specified then time efficient rather than space efficient code is used * @brief OS optimization.
* when two possible implementations exist. * @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 This is not related to the compiler optimization options.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
@ -96,18 +100,20 @@
#endif #endif
/** /**
* If enabled defines a CPU register to be used as storage for the global * @brief Exotic optimization.
* @p currp variable. Caching this variable in a register can greatly * @details If defined then a CPU register is used as storage for the global
* improve both space and time efficiency of the generated code. Another side * @p currp variable. Caching this variable in a register greatly
* effect is that one less register has to be saved during the context switch * improves both space and time OS efficiency. A side effect is that
* resulting in lower RAM usage and faster code. * 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 * @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores. * on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the * @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 * ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>. * -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for * @note This option must be enabled in the Makefile, it is listed here for
* documentation. * documentation only.
*/ */
#if defined(__DOXYGEN__) #if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg" #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@ -126,7 +135,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@ -134,8 +145,10 @@
#endif #endif
/** /**
* If enabled then the threads are enqueued on semaphores by priority rather * @brief Semaphores queuing mode.
* than FIFO order. * @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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -144,8 +157,10 @@
#endif #endif
/** /**
* If specified then the Semaphores the @p chSemWaitSignal() API is included * @brief Atomic semaphore API.
* in the kernel. * @details If enabled then the semaphores the @p chSemWaitSignal() API
* is included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -154,7 +169,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@ -162,7 +179,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES. * @note Requires @p CH_USE_MUTEXES.
*/ */
@ -171,7 +191,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS. * @note Requires @p CH_USE_CONDVARS.
*/ */
@ -180,7 +203,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@ -188,8 +213,10 @@
#endif #endif
/** /**
* If specified then the @p chEvtWaitXXXTimeout() functions are included in * @brief Events Flags APIs with timeout.
* the kernel. * @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS. * @note Requires @p CH_USE_EVENTS.
*/ */
@ -198,7 +225,10 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@ -206,7 +236,10 @@
#endif #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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES. * @note Requires @p CH_USE_MESSAGES.
*/ */
@ -215,16 +248,21 @@
#endif #endif
/** /**
* If specified then the Asynchronous Messages (Mailboxes) APIs are included * @brief Mailboxes APIs.
* in the kernel. * @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES.
*/ */
#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) #if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
#define CH_USE_MAILBOXES TRUE #define CH_USE_MAILBOXES TRUE
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -233,9 +271,24 @@
#endif #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 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. * @note Mutexes are recommended.
*/ */
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@ -243,18 +296,24 @@
#endif #endif
/** /**
* If enabled enforces the use of the C-runtime @p malloc() and @p free() * @brief C-runtime allocator.
* functions as backend for the system heap 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 The default is @p FALSE.
* @note Requires @p CH_USE_HEAP. * @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__) #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE #define CH_USE_MALLOC_HEAP FALSE
#endif #endif
/** /**
* If specified then the memory pools allocator APIs are included in the * @brief Memory Pools Allocator APIs.
* kernel. * @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@ -262,8 +321,10 @@
#endif #endif
/** /**
* If specified then the dynamic threads creation APIs are included in the * @brief Dynamic Threads APIs.
* kernel. * @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT. * @note Requires @p CH_USE_WAITEXIT.
*/ */
@ -276,8 +337,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Debug option, if enabled then the checks on the API functions input * @brief Debug option, parameters checks.
* parameters are activated. * @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@ -285,9 +348,11 @@
#endif #endif
/** /**
* Debug option, if enabled then all the assertions in the kernel code are * @brief Debug option, consistency checks.
* activated. This includes consistency checks inside the kernel, runtime * @details If enabled then all the assertions in the kernel code are
* anomalies and port-defined checks. * activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@ -295,8 +360,10 @@
#endif #endif
/** /**
* Debug option, if enabled the context switch circular trace buffer is * @brief Debug option, trace buffer.
* activated. * @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@ -304,25 +371,37 @@
#endif #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 * @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__) #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE #define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif #endif
/** /**
* Debug option, if enabled the threads working area is filled with a byte * @brief Debug option, stacks initialization.
* pattern when a thread is created. * @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__) #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE #define CH_DBG_FILL_THREADS FALSE
#endif #endif
/** /**
* Debug option, if enabled a field is added to the @p Thread structure that * @brief Debug option, threads profiling.
* counts the system ticks occurred while executing the thread. * @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__) #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE #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__) #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \ #define THREAD_EXT_FIELDS \
struct { \ struct { \
/* Add thread custom fields here.*/ \ /* Add threads custom fields here.*/ \
/* Space for the LWIP sys_timeouts structure.*/ \ /* Space for the LWIP sys_timeouts structure.*/ \
void *p_lwipspace[1]; \ void *p_lwipspace[1]; \
}; };
#endif #endif
/** /**
* User initialization code added to the @p chThdInit() API. * @brief Threads initialization hook.
* @note It is invoked from within @p chThdInit(). * @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__) #if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \ #define THREAD_EXT_INIT(tp) { \
/* Add thread initialization code here.*/ \ /* Add threads initialization code here.*/ \
(tp)->p_lwipspace[0] = NULL; \ (tp)->p_lwipspace[0] = NULL; \
} }
#endif #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 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__) #if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \ #define THREAD_EXT_EXIT(tp) { \
/* Add thread finalization code here.*/ \ /* Add threads finalization code here.*/ \
} }
#endif #endif
/** /**
* Code inserted inside the idle thread loop immediately after an interrupt * @brief Idle Loop hook.
* resumed execution. * @details This hook is continuously invoked by the idle thread loop.
*/ */
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \ #define IDLE_LOOP_HOOK() { \

View File

@ -66,7 +66,7 @@ void sys_init(void) {
sys_sem_t sys_sem_new(u8_t count) { 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); chSemInit(sem, (cnt_t)count);
return sem; 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 sys_mbox_new(int size) {
sys_mbox_t mbox; 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); chMBInit(mbox, (void *)(((uint8_t *)mbox) + sizeof(Mailbox)), size);
return mbox; 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), sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg),
void *arg, int stacksize, int prio) { void *arg, int stacksize, int prio) {
size_t wsz = THD_WA_SIZE(stacksize); size_t wsz = THD_WA_SIZE(stacksize);
void *wsp = chHeapAlloc(wsz); void *wsp = chCoreAlloc(wsz);
if (wsp == NULL) if (wsp == NULL)
return NULL; return NULL;
return (sys_thread_t)chThdCreateStatic(wsp, wsz, prio, (tfunc_t)thread, arg); return (sys_thread_t)chThdCreateStatic(wsp, wsz, prio, (tfunc_t)thread, arg);

View File

@ -75,6 +75,7 @@
#include "events.h" #include "events.h"
#include "messages.h" #include "messages.h"
#include "mailboxes.h" #include "mailboxes.h"
#include "memcore.h"
#include "heap.h" #include "heap.h"
#include "mempools.h" #include "mempools.h"
#include "threads.h" #include "threads.h"

View File

@ -27,17 +27,60 @@
#ifndef _HEAP_H_ #ifndef _HEAP_H_
#define _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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void heap_init(void); 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); void chHeapFree(void *p);
size_t chHeapStatus(size_t *sizep); size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* CH_USE_HEAP */
#endif /* _HEAP_H_ */ #endif /* _HEAP_H_ */
/** @} */ /** @} */

View File

@ -18,22 +18,29 @@
*/ */
/** /**
* @file mem.h * @file memcore.h
* @brief Low level memory manager macros and structures. * @brief Core memory manager macros and structures.
* @addtogroup coremem * @addtogroup memcore
* @{ * @{
*/ */
#ifndef _MEM_H_ #ifndef _MEMCORE_H_
#define _MEM_H_ #define _MEMCORE_H_
#if CH_USE_COREMEM #if CH_USE_MEMCORE
/** /**
* @brief Memory alignment type. * @brief Memory alignment type.
*/ */
typedef void *align_t; 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. * @brief Alignment mask constant.
*/ */
@ -42,20 +49,26 @@ typedef void *align_t;
/** /**
* @brief Alignment helper macro. * @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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void mem_init(void); void core_init(void);
void *chMemAlloc(size_t size); void *chCoreAlloc(size_t size);
void *chMemAllocI(size_t size); void *chCoreAllocI(size_t size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* CH_USE_COREMEM */ #endif /* CH_USE_MEMCORE */
#endif /* _MEM_H_ */ #endif /* _MEMCORE_H_ */
/** @} */ /** @} */

View File

@ -167,8 +167,8 @@ extern "C" {
Thread *chThdCreateStatic(void *wsp, size_t size, Thread *chThdCreateStatic(void *wsp, size_t size,
tprio_t prio, tfunc_t pf, void *arg); tprio_t prio, tfunc_t pf, void *arg);
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP #if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
Thread *chThdCreateFromHeap(size_t size, tprio_t prio, Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size,
tfunc_t pf, void *arg); tprio_t prio, tfunc_t pf, void *arg);
#endif #endif
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS #if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,

View File

@ -13,6 +13,7 @@ KERNSRC = ${CHIBIOS}/os/kernel/src/chsys.c \
${CHIBIOS}/os/kernel/src/chmsg.c \ ${CHIBIOS}/os/kernel/src/chmsg.c \
${CHIBIOS}/os/kernel/src/chmboxes.c \ ${CHIBIOS}/os/kernel/src/chmboxes.c \
${CHIBIOS}/os/kernel/src/chqueues.c \ ${CHIBIOS}/os/kernel/src/chqueues.c \
${CHIBIOS}/os/kernel/src/chmemcore.c \
${CHIBIOS}/os/kernel/src/chheap.c \ ${CHIBIOS}/os/kernel/src/chheap.c \
${CHIBIOS}/os/kernel/src/chmempools.c ${CHIBIOS}/os/kernel/src/chmempools.c

View File

@ -28,41 +28,23 @@
#if CH_USE_HEAP #if CH_USE_HEAP
/*
* Defaults on the best synchronization mechanism available.
*/
#if CH_USE_MUTEXES
#define H_LOCK(h) chMtxLock(&(h)->h_mtx)
#define H_UNLOCK(h) chMtxUnlock()
#else
#define H_LOCK(h) chSemWait(&(h)->h_sem)
#define H_UNLOCK(h) chSemSignal(&(h)->h_sem)
#endif
#if !CH_USE_MALLOC_HEAP #if !CH_USE_MALLOC_HEAP
#define MAGIC 0xF5A0 /**
#define ALIGN_TYPE void * * @brief Default heap descriptor.
#define ALIGN_MASK (sizeof(ALIGN_TYPE) - 1) */
#define ALIGN_SIZE(p) (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK) static MemoryHeap default_heap;
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 */
#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;
#else
#error "The heap allocator requires mutexes or semaphores to be enabled"
#endif
#if CH_HEAP_SIZE > 0
union {
ALIGN_TYPE alignment;
char buffer[ALIGN_SIZE(CH_HEAP_SIZE)];
};
#endif
} heap;
/** /**
* @brief Initializes the allocator subsystem. * @brief Initializes the allocator subsystem.
@ -70,26 +52,40 @@ static struct {
* @note Internal use only. * @note Internal use only.
*/ */
void heap_init(void) { void heap_init(void) {
struct header *hp; default_heap.h_provider = chCoreAlloc;
default_heap.h_free.h_next = NULL;
#if CH_HEAP_SIZE == 0 default_heap.h_free.h_size = 0;
extern char __heap_base__;
extern char __heap_end__;
hp = (void *)&__heap_base__;
hp->h_size = &__heap_end__ - &__heap_base__ - sizeof(struct header);
#else
hp = (void *)&heap.buffer[0];
hp->h_size = (&heap.buffer[ALIGN_SIZE(CH_HEAP_SIZE)] - &heap.buffer[0]) -
sizeof(struct header);
#endif
hp->h_next = NULL;
heap.free.h_next = hp;
heap.free.h_size = 0;
#if CH_USE_MUTEXES #if CH_USE_MUTEXES
chMtxInit(&heap.hmtx); chMtxInit(&default_heap.h_mtx);
#else #else
chSemInit(&heap.hsem, 1); 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;
hp->h_size = size - sizeof(struct heap_header);
#if CH_USE_MUTEXES
chMtxInit(&heapp->h_mtx);
#else
chSemInit(&heapp->h_sem, 1);
#endif #endif
} }
@ -97,53 +93,75 @@ void heap_init(void) {
* @brief Allocates a block of memory from the heap by using the first-fit * @brief Allocates a block of memory from the heap by using the first-fit
* algorithm. * algorithm.
* @details The allocated block is guaranteed to be properly aligned for a * @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 * @param[in] size the size of the block to be allocated. Note that the
* allocated block may be a bit bigger than the requested * allocated block may be a bit bigger than the requested
* size for alignment and fragmentation reasons. * size for alignment and fragmentation reasons.
* @return A pointer to the allocated block. * @return A pointer to the allocated block.
* @retval NULL if the block cannot be allocated. * @retval NULL if the block cannot be allocated.
*/ */
void *chHeapAlloc(size_t size) { void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
struct header *qp, *hp, *fp; struct heap_header *qp, *hp, *fp;
size = ALIGN_SIZE(size); if (heapp == NULL)
qp = &heap.free; heapp = &default_heap;
H_LOCK();
size = MEM_ALIGN_SIZE(size);
qp = &heapp->h_free;
H_LOCK(heapp);
while (qp->h_next != NULL) { while (qp->h_next != NULL) {
hp = qp->h_next; hp = qp->h_next;
if (hp->h_size >= size) { if (hp->h_size >= size) {
if (hp->h_size < size + sizeof(struct header)) { 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 * Gets the whole block even if it is slightly bigger than the
useful */ * requested size because the fragment would be too small to be
* useful.
*/
qp->h_next = hp->h_next; qp->h_next = hp->h_next;
} }
else { 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_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; qp->h_next = fp;
hp->h_size = size; hp->h_size = size;
} }
hp->h_magic = MAGIC; hp->h_heap = heapp;
H_UNLOCK(); H_UNLOCK(heapp);
return (void *)(hp + 1); return (void *)(hp + 1);
} }
qp = hp; 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; return NULL;
} }
#define LIMIT(p) (struct header *)((char *)(p) + \ #define LIMIT(p) (struct heap_header *)((uint8_t *)(p) + \
sizeof(struct header) + \ sizeof(struct heap_header) + \
(p)->h_size) (p)->h_size)
/** /**
* @brief Frees a previously allocated memory block. * @brief Frees a previously allocated memory block.
@ -151,50 +169,59 @@ void *chHeapAlloc(size_t size) {
* @param[in] p the memory block pointer * @param[in] p the memory block pointer
*/ */
void chHeapFree(void *p) { void chHeapFree(void *p) {
struct header *qp, *hp; struct heap_header *qp, *hp;
MemoryHeap *heapp;
chDbgCheck(p != NULL, "chHeapFree"); chDbgCheck(p != NULL, "chHeapFree");
hp = (struct header *)p - 1; hp = (struct heap_header *)p - 1;
chDbgAssert(hp->h_magic == MAGIC, heapp = hp->h_heap;
"chHeapFree(), #1", qp = &heapp->h_free;
"it is not magic"); H_LOCK(heapp);
qp = &heap.free;
H_LOCK();
while (TRUE) { while (TRUE) {
chDbgAssert((hp < qp) || (hp >= LIMIT(qp)), chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
"chHeapFree(), #2", "chHeapFree(), #1",
"within free block"); "within free block");
if (((qp == &heap.free) || (hp > qp)) && if (((qp == &heapp->h_free) || (hp > qp)) &&
((qp->h_next == NULL) || (hp < qp->h_next))) { ((qp->h_next == NULL) || (hp < qp->h_next))) {
/* Insertion after qp */ /*
* Insertion after qp.
*/
hp->h_next = qp->h_next; hp->h_next = qp->h_next;
qp->h_next = hp; 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) { 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; hp->h_next = hp->h_next->h_next;
} }
if ((LIMIT(qp) == hp)) { /* Cannot happen when qp == &heap.free */ if ((LIMIT(qp) == hp)) {
/* Merge with the previous block */ /*
qp->h_size += hp->h_size + sizeof(struct header); * Merge with the previous block.
*/
qp->h_size += hp->h_size + sizeof(struct heap_header);
qp->h_next = hp->h_next; qp->h_next = hp->h_next;
} }
break;
H_UNLOCK();
return;
} }
qp = qp->h_next; qp = qp->h_next;
} }
H_UNLOCK(heapp);
return;
} }
/** /**
* @brief Reports the heap status. * @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 * @param[in] sizep pointer to a variable that will receive the total
* fragmented free space * fragmented free space
* @return The number of fragments in the heap. * @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 * @note This function is not implemented when the @p CH_USE_MALLOC_HEAP
* configuration option is used (it always returns zero). * configuration option is used (it always returns zero).
*/ */
size_t chHeapStatus(size_t *sizep) { size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
struct header *qp; struct heap_header *qp;
size_t n, sz; size_t n, sz;
H_LOCK(); if (heapp == NULL)
heapp = &default_heap;
H_LOCK(heapp);
sz = 0; 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; sz += qp->h_next->h_size;
if (sizep) if (sizep)
*sizep = sz; *sizep = sz;
H_UNLOCK(); H_UNLOCK(heapp);
return n; return n;
} }
@ -231,8 +261,6 @@ static Mutex hmtx;
#define H_LOCK() chSemWait(&hsem) #define H_LOCK() chSemWait(&hsem)
#define H_UNLOCK() chSemSignal(&hsem) #define H_UNLOCK() chSemSignal(&hsem)
static Semaphore hsem; static Semaphore hsem;
#else
#error "The heap allocator requires mutexes or semaphores to be enabled"
#endif #endif
void heap_init(void) { void heap_init(void) {
@ -244,9 +272,11 @@ void heap_init(void) {
#endif #endif
} }
void *chHeapAlloc(size_t size) { void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
void *p; void *p;
chDbgCheck(heapp == NULL, "chHeapAlloc");
H_LOCK(); H_LOCK();
p = malloc(size); p = malloc(size);
H_UNLOCK(); H_UNLOCK();
@ -262,7 +292,9 @@ void chHeapFree(void *p) {
H_UNLOCK(); H_UNLOCK();
} }
size_t chHeapStatus(size_t *sizep) { size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
chDbgCheck(heapp == NULL, "chHeapStatus");
if (sizep) if (sizep)
*sizep = 0; *sizep = 0;

View File

@ -18,33 +18,38 @@
*/ */
/** /**
* @file chmem.c * @file chmemcore.c
* @brief Low level memory manager code. * @brief Core memory manager code.
* @addtogroup coremem * @addtogroup memcore
* @{ * @{
*/ */
#include <ch.h> #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_base__;
extern align_t __heap_end__; extern align_t __heap_end__;
#else #else
align_t buffer[ALIGN_SIZE(CH_MEM_SIZE) / sizeof(align_t)]; align_t buffer[ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)];
#endif #endif
static align_t *nextmem; static align_t *nextmem;
static align_t *endmem; 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__; nextmem = &__heap_base__;
endmem = &__heap_end__; endmem = &__heap_end__;
#else #else
nextmem = &buffer[0]; nextmem = &buffer[0];
endmem = &buffer[ALIGN_SIZE(CH_MEM_SIZE) / sizeof(align_t)]; endmem = &buffer[ALIGN_SIZE(CH_MEMCORE_SIZE) / sizeof(align_t)];
#endif #endif
} }
@ -81,7 +86,7 @@ void *chCoreAlloc(size_t size) {
void *chCoreAllocI(size_t size) { void *chCoreAllocI(size_t size) {
void *p; void *p;
size = ALIGN_SIZE(size); size = MEM_ALIGN_SIZE(size);
if (nextmem + size > endmem) if (nextmem + size > endmem)
return NULL; return NULL;
p = nextmem; p = nextmem;
@ -89,6 +94,6 @@ void *chCoreAllocI(size_t size) {
return p; return p;
} }
#endif /* CH_USE_COREMEM */ #endif /* CH_USE_MEMCORE */
/** @} */ /** @} */

View File

@ -61,6 +61,9 @@ void chSysInit(void) {
port_init(); port_init();
scheduler_init(); scheduler_init();
vt_init(); vt_init();
#if CH_USE_MEMCORE
core_init();
#endif
#if CH_USE_HEAP #if CH_USE_HEAP
heap_init(); heap_init();
#endif #endif

View File

@ -124,6 +124,8 @@ Thread *chThdCreateStatic(void *wsp, size_t size,
/** /**
* @brief Creates a new thread allocating the memory from the heap. * @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] size size of the working area to be allocated
* @param[in] prio the priority level for the new thread * @param[in] prio the priority level for the new thread
* @param[in] pf the thread function * @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 * @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled
* in @p chconf.h. * 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; void *wsp;
Thread *tp; Thread *tp;
wsp = chHeapAlloc(size); wsp = chHeapAlloc(heapp, size);
if (wsp == NULL) if (wsp == NULL)
return NULL; return NULL;
tp = chThdInit(wsp, size, prio, pf, arg); tp = chThdInit(wsp, size, prio, pf, arg);

View File

@ -32,29 +32,36 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Frequency of the system timer that drives the system ticks. This also * @brief System tick frequency.
* defines the system tick time unit. * @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__) #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
#define CH_FREQUENCY 1000 #define CH_FREQUENCY 1000
#endif #endif
/** /**
* This constant is the number of system ticks allowed for the threads before * @brief Round robin interval.
* preemption occurs. This option is only meaningful if the option * @details This constant is the number of system ticks allowed for the
* @p CH_USE_ROUNDROBIN is also active. * 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__) #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
#define CH_TIME_QUANTUM 20 #define CH_TIME_QUANTUM 20
#endif #endif
/** /**
* If enabled then the use of nested @p chSysLock() / @p chSysUnlock() * @brief Nested locks.
* operations is allowed.<br> * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock()
* For performance and code size reasons the recommended setting is to leave * operations is allowed.<br>
* this option disabled.<br> * For performance and code size reasons the recommended setting
* You can use this option if you need to merge ChibiOS/RT with external * is to leave this option disabled.<br>
* libraries that require nested lock/unlock operations. * 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. * @note The default is @p FALSE.
*/ */
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__) #if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
@ -62,23 +69,18 @@
#endif #endif
/** /**
* If specified then the kernel performs the round robin scheduling algorithm * @brief Managed RAM size.
* on threads of equal priority. * @details Size of the RAM area to be managed by the OS. If set to zero
* @note The default is @p TRUE. * then the whole available RAM is used. The core memory is made
*/ * available to the heap allocator and/or can be used directly through
#if !defined(CH_USE_ROUNDROBIN) || defined(__DOXYGEN__) * the simplified core memory allocator.
#define CH_USE_ROUNDROBIN TRUE *
#endif * @note In order to let the OS manage the whole RAM the linker script must
/**
* 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
* provide the @p __heap_base__ and @p __heap_end__ symbols. * 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__) #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_HEAP_SIZE 0 #define CH_MEMCORE_SIZE 0
#endif #endif
/*===========================================================================*/ /*===========================================================================*/
@ -86,8 +88,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* If specified then time efficient rather than space efficient code is used * @brief OS optimization.
* when two possible implementations exist. * @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 This is not related to the compiler optimization options.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
@ -96,18 +100,20 @@
#endif #endif
/** /**
* If enabled defines a CPU register to be used as storage for the global * @brief Exotic optimization.
* @p currp variable. Caching this variable in a register can greatly * @details If defined then a CPU register is used as storage for the global
* improve both space and time efficiency of the generated code. Another side * @p currp variable. Caching this variable in a register greatly
* effect is that one less register has to be saved during the context switch * improves both space and time OS efficiency. A side effect is that
* resulting in lower RAM usage and faster code. * 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 * @note This option is only usable with the GCC compiler and is only useful
* on processors with many registers like ARM cores. * on processors with many registers like ARM cores.
* @note If this option is enabled then ALL the libraries linked to the * @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 * ChibiOS/RT code <b>must</b> be recompiled with the GCC option @p
* -ffixed-@<reg@>. * -ffixed-@<reg@>.
* @note This option must be enabled in the Makefile, it is listed here for * @note This option must be enabled in the Makefile, it is listed here for
* documentation. * documentation only.
*/ */
#if defined(__DOXYGEN__) #if defined(__DOXYGEN__)
#define CH_CURRP_REGISTER_CACHE "reg" #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
@ -126,7 +135,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
@ -134,8 +145,10 @@
#endif #endif
/** /**
* If enabled then the threads are enqueued on semaphores by priority rather * @brief Semaphores queuing mode.
* than FIFO order. * @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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -144,8 +157,10 @@
#endif #endif
/** /**
* If specified then the Semaphores the @p chSemWaitSignal() API is included * @brief Atomic semaphore API.
* in the kernel. * @details If enabled then the semaphores the @p chSemWaitSignal() API
* is included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -154,7 +169,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
@ -162,7 +179,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_MUTEXES. * @note Requires @p CH_USE_MUTEXES.
*/ */
@ -171,7 +191,10 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_CONDVARS. * @note Requires @p CH_USE_CONDVARS.
*/ */
@ -180,7 +203,9 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
@ -188,8 +213,10 @@
#endif #endif
/** /**
* If specified then the @p chEvtWaitXXXTimeout() functions are included in * @brief Events Flags APIs with timeout.
* the kernel. * @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_EVENTS. * @note Requires @p CH_USE_EVENTS.
*/ */
@ -198,7 +225,10 @@
#endif #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. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
@ -206,7 +236,10 @@
#endif #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 The default is @p FALSE. Enable this if you have special requirements.
* @note Requires @p CH_USE_MESSAGES. * @note Requires @p CH_USE_MESSAGES.
*/ */
@ -215,8 +248,10 @@
#endif #endif
/** /**
* If specified then the Asynchronous Messages (Mailboxes) APIs are included * @brief Mailboxes APIs.
* in the kernel. * @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -225,7 +260,9 @@
#endif #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 The default is @p TRUE.
* @note Requires @p CH_USE_SEMAPHORES. * @note Requires @p CH_USE_SEMAPHORES.
*/ */
@ -234,9 +271,24 @@
#endif #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 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. * @note Mutexes are recommended.
*/ */
#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
@ -244,18 +296,24 @@
#endif #endif
/** /**
* If enabled enforces the use of the C-runtime @p malloc() and @p free() * @brief C-runtime allocator.
* functions as backend for the system heap 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 The default is @p FALSE.
* @note Requires @p CH_USE_HEAP. * @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__) #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
#define CH_USE_MALLOC_HEAP FALSE #define CH_USE_MALLOC_HEAP FALSE
#endif #endif
/** /**
* If specified then the memory pools allocator APIs are included in the * @brief Memory Pools Allocator APIs.
* kernel. * @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
@ -263,8 +321,10 @@
#endif #endif
/** /**
* If specified then the dynamic threads creation APIs are included in the * @brief Dynamic Threads APIs.
* kernel. * @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE. * @note The default is @p TRUE.
* @note Requires @p CH_USE_WAITEXIT. * @note Requires @p CH_USE_WAITEXIT.
*/ */
@ -277,8 +337,10 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* Debug option, if enabled then the checks on the API functions input * @brief Debug option, parameters checks.
* parameters are activated. * @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
@ -286,9 +348,11 @@
#endif #endif
/** /**
* Debug option, if enabled then all the assertions in the kernel code are * @brief Debug option, consistency checks.
* activated. This includes consistency checks inside the kernel, runtime * @details If enabled then all the assertions in the kernel code are
* anomalies and port-defined checks. * activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@ -296,8 +360,10 @@
#endif #endif
/** /**
* Debug option, if enabled the context switch circular trace buffer is * @brief Debug option, trace buffer.
* activated. * @details If enabled then the context switch circular trace buffer is
* activated.
*
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
@ -305,25 +371,37 @@
#endif #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 * @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__) #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
#define CH_DBG_ENABLE_STACK_CHECK FALSE #define CH_DBG_ENABLE_STACK_CHECK FALSE
#endif #endif
/** /**
* Debug option, if enabled the threads working area is filled with a byte * @brief Debug option, stacks initialization.
* pattern when a thread is created. * @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__) #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
#define CH_DBG_FILL_THREADS FALSE #define CH_DBG_FILL_THREADS FALSE
#endif #endif
/** /**
* Debug option, if enabled a field is added to the @p Thread structure that * @brief Debug option, threads profiling.
* counts the system ticks occurred while executing the thread. * @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__) #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
#define CH_DBG_THREADS_PROFILING TRUE #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__) #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \ #define THREAD_EXT_FIELDS \
struct { \ struct { \
/* Add thread custom fields here.*/ \ /* Add threads custom fields here.*/ \
}; };
#endif #endif
/** /**
* User initialization code added to the @p chThdInit() API. * @brief Threads initialization hook.
* @note It is invoked from within @p chThdInit(). * @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__) #if !defined(THREAD_EXT_INIT) || defined(__DOXYGEN__)
#define THREAD_EXT_INIT(tp) { \ #define THREAD_EXT_INIT(tp) { \
/* Add thread initialization code here.*/ \ /* Add threads initialization code here.*/ \
} }
#endif #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 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__) #if !defined(THREAD_EXT_EXIT) || defined(__DOXYGEN__)
#define THREAD_EXT_EXIT(tp) { \ #define THREAD_EXT_EXIT(tp) { \
/* Add thread finalization code here.*/ \ /* Add threads finalization code here.*/ \
} }
#endif #endif
/** /**
* Code inserted inside the idle thread loop immediately after an interrupt * @brief Idle Loop hook.
* resumed execution. * @details This hook is continuously invoked by the idle thread loop.
*/ */
#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
#define IDLE_LOOP_HOOK() { \ #define IDLE_LOOP_HOOK() { \

View File

@ -7,6 +7,15 @@
Removed the old EMAC driver, updated the uIP WEB demo to use the new Removed the old EMAC driver, updated the uIP WEB demo to use the new
driver model. driver model.
- NEW: Added a simple lwIP demo (web server) for the AT91SAM7X. - 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. - CHANGE: renamed ./demos/ARM7-AT91SAM7X-WEB-GCC in ARM7-AT91SAM7X-UIP-GCC.
*** 1.3.2 *** *** 1.3.2 ***

View File

@ -59,11 +59,7 @@ static char *tokp;
* Static working areas, the following areas can be used for threads or * Static working areas, the following areas can be used for threads or
* used as temporary buffers. * used as temporary buffers.
*/ */
WORKING_AREA(waT0, THREADS_STACK_SIZE); union test_buffers test;
WORKING_AREA(waT1, THREADS_STACK_SIZE);
WORKING_AREA(waT2, THREADS_STACK_SIZE);
WORKING_AREA(waT3, THREADS_STACK_SIZE);
WORKING_AREA(waT4, THREADS_STACK_SIZE);
/* /*
* Pointers to the spawned threads. * Pointers to the spawned threads.
@ -73,7 +69,7 @@ Thread *threads[MAX_THREADS];
/* /*
* Pointers to the working areas. * 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. * Console output.

View File

@ -47,6 +47,17 @@ struct testcase {
void (*execute)(void); 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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -94,11 +105,7 @@ extern "C" {
} }
extern Thread *threads[MAX_THREADS]; extern Thread *threads[MAX_THREADS];
extern WORKING_AREA(waT0, THREADS_STACK_SIZE); extern union test_buffers test;
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 void * const wa[]; extern void * const wa[];
extern bool_t test_timer_done; extern bool_t test_timer_done;

View File

@ -70,50 +70,56 @@ static msg_t thread(void *p) {
} }
#if CH_USE_HEAP #if CH_USE_HEAP
static MemoryHeap heap1;
static char *dyn1_gettest(void) { static char *dyn1_gettest(void) {
return "Dynamic APIs, threads creation from heap"; 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) { static void dyn1_execute(void) {
size_t n, sz; size_t n, sz;
void *p1; void *p1;
tprio_t prio = chThdGetPriority(); tprio_t prio = chThdGetPriority();
/* Test skipped if the heap is already fragmented. */ (void)chHeapStatus(&heap1, &sz);
if ((n = chHeapStatus(&sz)) == 1) { /* Starting threads from the heap. */
/* Starting threads from the heap. */ threads[0] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
threads[0] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE), prio-1, thread, "A");
prio-1, thread, "A"); threads[1] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
threads[1] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE), prio-2, thread, "B");
prio-2, thread, "B"); /* Allocating the whole heap in order to make the thread creation fail.*/
/* Allocating the whole heap in order to make the thread creation fail.*/ (void)chHeapStatus(&heap1, &n);
(void)chHeapStatus(&n); p1 = chHeapAlloc(&heap1, n);
p1 = chHeapAlloc(n); threads[2] = chThdCreateFromHeap(&heap1, THD_WA_SIZE(THREADS_STACK_SIZE),
threads[2] = chThdCreateFromHeap(THD_WA_SIZE(THREADS_STACK_SIZE), prio-3, thread, "C");
prio-3, thread, "C"); chHeapFree(p1);
chHeapFree(p1);
test_assert(1, (threads[0] != NULL) && test_assert(1, (threads[0] != NULL) &&
(threads[1] != NULL) && (threads[1] != NULL) &&
(threads[2] == NULL) && (threads[2] == NULL) &&
(threads[3] == NULL) && (threads[3] == NULL) &&
(threads[4] == NULL), (threads[4] == NULL),
"thread creation failed"); "thread creation failed");
/* Claiming the memory from terminated threads. */ /* Claiming the memory from terminated threads. */
test_wait_threads(); test_wait_threads();
test_assert_sequence(2, "AB"); test_assert_sequence(2, "AB");
/* Heap status checked again.*/ /* Heap status checked again.*/
test_assert(3, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(3, chHeapStatus(&heap1, &n) == 1, "heap fragmented");
test_assert(4, n == sz, "heap size changed"); test_assert(4, n == sz, "heap size changed");
}
} }
const struct testcase testdyn1 = { const struct testcase testdyn1 = {
dyn1_gettest, dyn1_gettest,
NULL, dyn1_setup,
NULL, NULL,
dyn1_execute dyn1_execute
}; };

View File

@ -50,6 +50,8 @@
#define SIZE 16 #define SIZE 16
static MemoryHeap test_heap;
/** /**
* @page test_heap_001 Allocation and fragmentation test * @page test_heap_001 Allocation and fragmentation test
* *
@ -66,74 +68,73 @@ static char *heap1_gettest(void) {
return "Heap, allocation and fragmentation test"; 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) { static void heap1_execute(void) {
void *p1, *p2, *p3; void *p1, *p2, *p3;
size_t n, sz; size_t n, sz;
/* Test skipped if the heap is already fragmented. */ /* Test skipped if the heap is already fragmented. */
if ((n = chHeapStatus(&sz)) == 1) { (void)chHeapStatus(&test_heap, &sz);
test_print("--- Size : "); test_print("--- Size : ");
test_printn(sz); test_printn(sz);
test_println(" bytes, not fragmented"); test_println(" bytes");
/* Same order */ /* Same order */
p1 = chHeapAlloc(SIZE); p1 = chHeapAlloc(&test_heap, SIZE);
p2 = chHeapAlloc(SIZE); p2 = chHeapAlloc(&test_heap, SIZE);
p3 = chHeapAlloc(SIZE); p3 = chHeapAlloc(&test_heap, SIZE);
chHeapFree(p1); /* Does not merge */ chHeapFree(p1); /* Does not merge */
chHeapFree(p2); /* Merges backward */ chHeapFree(p2); /* Merges backward */
chHeapFree(p3); /* Merges both sides */ chHeapFree(p3); /* Merges both sides */
test_assert(1, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(1, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
/* Reverse order */ /* Reverse order */
p1 = chHeapAlloc(SIZE); p1 = chHeapAlloc(&test_heap, SIZE);
p2 = chHeapAlloc(SIZE); p2 = chHeapAlloc(&test_heap, SIZE);
p3 = chHeapAlloc(SIZE); p3 = chHeapAlloc(&test_heap, SIZE);
chHeapFree(p3); /* Merges forward */ chHeapFree(p3); /* Merges forward */
chHeapFree(p2); /* Merges forward */ chHeapFree(p2); /* Merges forward */
chHeapFree(p1); /* Merges forward */ chHeapFree(p1); /* Merges forward */
test_assert(2, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(2, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
/* Small fragments handling */ /* Small fragments handling */
p1 = chHeapAlloc(SIZE + 1); p1 = chHeapAlloc(&test_heap, SIZE + 1);
p2 = chHeapAlloc(SIZE); p2 = chHeapAlloc(&test_heap, SIZE);
chHeapFree(p1); chHeapFree(p1);
test_assert(3, chHeapStatus(&n) == 2, "invalid state"); test_assert(3, chHeapStatus(&test_heap, &n) == 2, "invalid state");
p1 = chHeapAlloc(SIZE); p1 = chHeapAlloc(&test_heap, SIZE);
test_assert(4, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(4, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
chHeapFree(p2); chHeapFree(p2);
chHeapFree(p1); chHeapFree(p1);
test_assert(5, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(5, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
/* Skip fragment handling */ /* Skip fragment handling */
p1 = chHeapAlloc(SIZE); p1 = chHeapAlloc(&test_heap, SIZE);
p2 = chHeapAlloc(SIZE); p2 = chHeapAlloc(&test_heap, SIZE);
chHeapFree(p1); chHeapFree(p1);
test_assert(6, chHeapStatus(&n) == 2, "invalid state"); test_assert(6, chHeapStatus(&test_heap, &n) == 2, "invalid state");
p1 = chHeapAlloc(SIZE * 2); /* Skips first fragment */ p1 = chHeapAlloc(&test_heap, SIZE * 2); /* Skips first fragment */
chHeapFree(p1); chHeapFree(p1);
chHeapFree(p2); chHeapFree(p2);
test_assert(7, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(7, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
/* Allocate all handling */ /* Allocate all handling */
(void)chHeapStatus(&n); (void)chHeapStatus(&test_heap, &n);
p1 = chHeapAlloc(n); p1 = chHeapAlloc(&test_heap, n);
test_assert(8, chHeapStatus(&n) == 0, "not empty"); test_assert(8, chHeapStatus(&test_heap, &n) == 0, "not empty");
chHeapFree(p1); chHeapFree(p1);
test_assert(9, chHeapStatus(&n) == 1, "heap fragmented"); test_assert(9, chHeapStatus(&test_heap, &n) == 1, "heap fragmented");
test_assert(10, n == sz, "size changed"); test_assert(10, n == sz, "size changed");
}
else {
test_print("--- Size : ");
test_printn(sz);
test_println(" bytes, fragmented, test skipped");
}
} }
const struct testcase testheap1 = { const struct testcase testheap1 = {
heap1_gettest, heap1_gettest,
NULL, heap1_setup,
NULL, NULL,
heap1_execute heap1_execute
}; };

View File

@ -59,7 +59,7 @@
* variables are explicitly initialized in each test case. It is done in order * variables are explicitly initialized in each test case. It is done in order
* to test the macros. * 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 * @page test_mbox_001 Queuing and timeouts
@ -77,7 +77,7 @@ static char *mbox1_gettest(void) {
static void mbox1_setup(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) { static void mbox1_execute(void) {

View File

@ -63,8 +63,8 @@ static void notify(void) {}
* variables are explicitly initialized in each test case. It is done in order * variables are explicitly initialized in each test case. It is done in order
* to test the macros. * to test the macros.
*/ */
static INPUTQUEUE_DECL(iq, waT0, TEST_QUEUES_SIZE, notify); static INPUTQUEUE_DECL(iq, test.waT0, TEST_QUEUES_SIZE, notify);
static OUTPUTQUEUE_DECL(oq, waT0, TEST_QUEUES_SIZE, notify); static OUTPUTQUEUE_DECL(oq, test.waT1, TEST_QUEUES_SIZE, notify);
/** /**
* @page test_queues_001 Input Queues functionality and APIs * @page test_queues_001 Input Queues functionality and APIs