import ChibiOS 2.0.8
This commit is contained in:
102
ChibiOS_2.0.8/os/kernel/include/ch.h
Normal file
102
ChibiOS_2.0.8/os/kernel/include/ch.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ch.h
|
||||
* @brief ChibiOS/RT main include file.
|
||||
* @details This header includes all the required kernel headers so it is the
|
||||
* only kernel header you usually want to include in your application.
|
||||
*
|
||||
* @addtogroup kernel_info
|
||||
* @details Kernel related info.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CH_H_
|
||||
#define _CH_H_
|
||||
|
||||
/**
|
||||
* @brief ChibiOS/RT identification macro.
|
||||
*/
|
||||
#define _CHIBIOS_RT_
|
||||
|
||||
/**
|
||||
* @brief Kernel version string.
|
||||
*/
|
||||
#define CH_KERNEL_VERSION "2.0.8"
|
||||
|
||||
/**
|
||||
* @brief Kernel version major number.
|
||||
*/
|
||||
#define CH_KERNEL_MAJOR 2
|
||||
|
||||
/**
|
||||
* @brief Kernel version minor number.
|
||||
*/
|
||||
#define CH_KERNEL_MINOR 0
|
||||
|
||||
/**
|
||||
* @brief Kernel version patch number.
|
||||
*/
|
||||
#define CH_KERNEL_PATCH 8
|
||||
|
||||
/*
|
||||
* Common values.
|
||||
*/
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
#include "chconf.h"
|
||||
#include "chtypes.h"
|
||||
#include "chlists.h"
|
||||
#include "chcore.h"
|
||||
#include "chsys.h"
|
||||
#include "chvt.h"
|
||||
#include "chschd.h"
|
||||
#include "chsem.h"
|
||||
#include "chmtx.h"
|
||||
#include "chcond.h"
|
||||
#include "chevents.h"
|
||||
#include "chmsg.h"
|
||||
#include "chmboxes.h"
|
||||
#include "chmemcore.h"
|
||||
#include "chheap.h"
|
||||
#include "chmempools.h"
|
||||
#include "chthreads.h"
|
||||
#include "chregistry.h"
|
||||
#include "chinline.h"
|
||||
#include "chqueues.h"
|
||||
#include "chstreams.h"
|
||||
#include "chioch.h"
|
||||
#include "chdebug.h"
|
||||
|
||||
#endif /* _CH_H_ */
|
||||
|
||||
/** @} */
|
||||
98
ChibiOS_2.0.8/os/kernel/include/chcond.h
Normal file
98
ChibiOS_2.0.8/os/kernel/include/chcond.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file are contributed by and Copyright (C) 2008
|
||||
of Leon Woestenberg.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chcond.h
|
||||
* @brief Condition Variables macros and structures.
|
||||
*
|
||||
* @addtogroup condvars
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHCOND_H_
|
||||
#define _CHCOND_H_
|
||||
|
||||
#if CH_USE_CONDVARS
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if !CH_USE_MUTEXES
|
||||
#error "CH_USE_CONDVARS requires CH_USE_MUTEXES"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CondVar structure.
|
||||
*/
|
||||
typedef struct CondVar {
|
||||
ThreadsQueue c_queue; /**< @brief CondVar threads queue.*/
|
||||
} CondVar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chCondInit(CondVar *cp);
|
||||
void chCondSignal(CondVar *cp);
|
||||
void chCondSignalI(CondVar *cp);
|
||||
void chCondBroadcast(CondVar *cp);
|
||||
void chCondBroadcastI(CondVar *cp);
|
||||
msg_t chCondWait(CondVar *cp);
|
||||
msg_t chCondWaitS(CondVar *cp);
|
||||
#if CH_USE_CONDVARS_TIMEOUT
|
||||
msg_t chCondWaitTimeout(CondVar *cp, systime_t time);
|
||||
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data part of a static condition variable initializer.
|
||||
* @details This macro should be used when statically initializing a condition
|
||||
* variable that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the condition variable
|
||||
*/
|
||||
#define _CONDVAR_DATA(name) {_THREADSQUEUE_DATA(name.c_queue)}
|
||||
|
||||
/**
|
||||
* @brief Static condition variable initializer.
|
||||
* @details Statically initialized condition variables require no explicit
|
||||
* initialization using @p chCondInit().
|
||||
*
|
||||
* @param[in] name the name of the condition variable
|
||||
*/
|
||||
#define CONDVAR_DECL(name) CondVar name = _CONDVAR_DATA(name)
|
||||
|
||||
#endif /* CH_USE_CONDVARS */
|
||||
|
||||
#endif /* _CHCOND_H_ */
|
||||
|
||||
/** @} */
|
||||
170
ChibiOS_2.0.8/os/kernel/include/chdebug.h
Normal file
170
ChibiOS_2.0.8/os/kernel/include/chdebug.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chdebug.h
|
||||
* @brief Debug macros and structures.
|
||||
*
|
||||
* @addtogroup debug
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHDEBUG_H_
|
||||
#define _CHDEBUG_H_
|
||||
|
||||
/**
|
||||
* @brief Trace buffer entries.
|
||||
*/
|
||||
#ifndef TRACE_BUFFER_SIZE
|
||||
#define TRACE_BUFFER_SIZE 64
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Fill value for thread stack area in debug mode.
|
||||
*/
|
||||
#ifndef STACK_FILL_VALUE
|
||||
#define STACK_FILL_VALUE 0x55
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Fill value for thread area in debug mode.
|
||||
* @note The chosen default value is 0xFF in order to make evident which
|
||||
* thread fields were not initialized when inspecting the memory with
|
||||
* a debugger. A uninitialized field is not an error in itself but it
|
||||
* better to know it.
|
||||
*/
|
||||
#ifndef THREAD_FILL_VALUE
|
||||
#define THREAD_FILL_VALUE 0xFF
|
||||
#endif
|
||||
|
||||
#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Trace buffer record.
|
||||
*/
|
||||
typedef struct {
|
||||
void *cse_wtobjp; /**< @brief Object where going to
|
||||
sleep. */
|
||||
systime_t cse_time; /**< @brief Time of the switch
|
||||
event. */
|
||||
uint16_t cse_state: 4; /**< @brief Switched out thread
|
||||
state. */
|
||||
uint16_t cse_tid: 12; /**< @brief Switched in thread id. */
|
||||
} CtxSwcEvent;
|
||||
|
||||
/**
|
||||
* @brief Trace buffer header.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned tb_size; /**< @brief Trace buffer size
|
||||
(entries). */
|
||||
CtxSwcEvent *tb_ptr; /**< @brief Pointer to the ring buffer
|
||||
front. */
|
||||
/** @brief Ring buffer.*/
|
||||
CtxSwcEvent tb_buffer[TRACE_BUFFER_SIZE];
|
||||
} TraceBuffer;
|
||||
#endif /* CH_DBG_ENABLE_TRACE */
|
||||
|
||||
#define __QUOTE_THIS(p) #p
|
||||
|
||||
#if CH_DBG_ENABLE_CHECKS
|
||||
/**
|
||||
* @brief Function parameter check.
|
||||
* @details If the condition check fails then the kernel panics and halts.
|
||||
* @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch
|
||||
* is specified in @p chconf.h else the macro does nothing.
|
||||
*
|
||||
* @param[in] c the condition to be verified to be true
|
||||
* @param[in] func the undecorated function name
|
||||
*/
|
||||
#define chDbgCheck(c, func) { \
|
||||
if (!(c)) \
|
||||
chDbgPanic(__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__)); \
|
||||
}
|
||||
#else /* !CH_DBG_ENABLE_CHECKS */
|
||||
#define chDbgCheck(c, func) { \
|
||||
(void)(c), (void)__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__); \
|
||||
}
|
||||
#endif /* !CH_DBG_ENABLE_CHECKS */
|
||||
|
||||
#if CH_DBG_ENABLE_ASSERTS
|
||||
/**
|
||||
* @brief Condition assertion.
|
||||
* @details If the condition check fails then the kernel panics with the
|
||||
* specified message and halts.
|
||||
* @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS switch
|
||||
* is specified in @p chconf.h else the macro does nothing.
|
||||
* @note The convention for the message is the following:<br>
|
||||
* @<function_name@>(), #@<assert_number@>
|
||||
* @note The remark string is not currently used except for putting a
|
||||
* comment in the code about the assertion.
|
||||
*
|
||||
* @param[in] c the condition to be verified to be true
|
||||
* @param[in] m the text message
|
||||
* @param[in] r a remark string
|
||||
*/
|
||||
#define chDbgAssert(c, m, r) { \
|
||||
if (!(c)) \
|
||||
chDbgPanic(m); \
|
||||
}
|
||||
#else /* !CH_DBG_ENABLE_ASSERTS */
|
||||
#define chDbgAssert(c, m, r) {(void)(c);}
|
||||
#endif /* !CH_DBG_ENABLE_ASSERTS */
|
||||
|
||||
#if !(CH_DBG_ENABLE_ASSERTS || \
|
||||
CH_DBG_ENABLE_CHECKS || \
|
||||
CH_DBG_ENABLE_STACK_CHECK)
|
||||
/* When the debug features are disabled this function is replaced by an empty
|
||||
macro.*/
|
||||
#define chDbgPanic(msg) {}
|
||||
#endif
|
||||
|
||||
#if !CH_DBG_ENABLE_TRACE
|
||||
/* When the trace feature is disabled this function is replaced by an empty
|
||||
macro.*/
|
||||
#define chDbgTrace(otp) {}
|
||||
#endif
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if CH_DBG_ENABLE_TRACE
|
||||
extern TraceBuffer trace_buffer;
|
||||
void trace_init(void);
|
||||
void chDbgTrace(Thread *otp);
|
||||
#endif
|
||||
#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
|
||||
extern char *panic_msg;
|
||||
void chDbgPanic(char *msg);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(__DOXYGEN__) */
|
||||
|
||||
#endif /* _CHDEBUG_H_ */
|
||||
|
||||
/** @} */
|
||||
164
ChibiOS_2.0.8/os/kernel/include/chevents.h
Normal file
164
ChibiOS_2.0.8/os/kernel/include/chevents.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chevents.h
|
||||
* @brief Events macros and structures.
|
||||
*
|
||||
* @addtogroup events
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHEVENTS_H_
|
||||
#define _CHEVENTS_H_
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
|
||||
typedef struct EventListener EventListener;
|
||||
|
||||
/**
|
||||
* @brief Event Listener structure.
|
||||
*/
|
||||
struct EventListener {
|
||||
EventListener *el_next; /**< @brief Next Event Listener
|
||||
registered on the Event
|
||||
Source. */
|
||||
Thread *el_listener; /**< @brief Thread interested in the
|
||||
Event Source. */
|
||||
eventmask_t el_mask; /**< @brief Event flags mask associated
|
||||
by the thread to the Event
|
||||
Source. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event Source structure.
|
||||
*/
|
||||
typedef struct EventSource {
|
||||
EventListener *es_next; /**< @brief First Event Listener
|
||||
registered on the Event
|
||||
Source. */
|
||||
} EventSource;
|
||||
|
||||
/**
|
||||
* @brief Data part of a static event source initializer.
|
||||
* @details This macro should be used when statically initializing an event
|
||||
* source that is part of a bigger structure.
|
||||
* @param name the name of the event source variable
|
||||
*/
|
||||
#define _EVENTSOURCE_DATA(name) {(void *)(&name)}
|
||||
|
||||
/**
|
||||
* @brief Static event source initializer.
|
||||
* @details Statically initialized event sources require no explicit
|
||||
* initialization using @p chEvtInit().
|
||||
*
|
||||
* @param name the name of the event source variable
|
||||
*/
|
||||
#define EVENTSOURCE_DECL(name) EventSource name = _EVENTSOURCE_DATA(name)
|
||||
|
||||
/** All events allowed mask.*/
|
||||
#define ALL_EVENTS ((eventmask_t)-1)
|
||||
|
||||
/** Returns the event mask from the event identifier.*/
|
||||
#define EVENT_MASK(eid) ((eventmask_t)(1 << (eid)))
|
||||
|
||||
/**
|
||||
* @brief Registers an Event Listener on an Event Source.
|
||||
* @note Multiple Event Listeners can use the same event identifier, the
|
||||
* listener will share the callback function.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
* @param[out] elp pointer to the @p EventListener structure
|
||||
* @param[in] eid numeric identifier assigned to the Event Listener. The
|
||||
* identifier is used as index for the event callback
|
||||
* function.
|
||||
* The value must range between zero and the size, in bit,
|
||||
* of the @p eventid_t type minus one.
|
||||
*/
|
||||
#define chEvtRegister(esp, elp, eid) chEvtRegisterMask(esp, elp, EVENT_MASK(eid))
|
||||
|
||||
/**
|
||||
* @brief Initializes an Event Source.
|
||||
* @note Can be used with interrupts disabled or enabled.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
*/
|
||||
#define chEvtInit(esp) \
|
||||
((esp)->es_next = (EventListener *)(void *)(esp))
|
||||
|
||||
/**
|
||||
* @brief Verifies if there is at least one @p EventListener registered.
|
||||
* @note Can be called with interrupts disabled or enabled.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
*/
|
||||
#define chEvtIsListening(esp) \
|
||||
((void *)(esp) != (void *)(esp)->es_next)
|
||||
|
||||
/**
|
||||
* @brief Event Handler callback function.
|
||||
*/
|
||||
typedef void (*evhandler_t)(eventid_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chEvtRegisterMask(EventSource *esp,
|
||||
EventListener *elp,
|
||||
eventmask_t mask);
|
||||
void chEvtUnregister(EventSource *esp, EventListener *elp);
|
||||
eventmask_t chEvtClear(eventmask_t mask);
|
||||
eventmask_t chEvtPend(eventmask_t mask);
|
||||
void chEvtSignal(Thread *tp, eventmask_t mask);
|
||||
void chEvtSignalI(Thread *tp, eventmask_t mask);
|
||||
void chEvtBroadcast(EventSource *esp);
|
||||
void chEvtBroadcastI(EventSource *esp);
|
||||
void chEvtDispatch(const evhandler_t *handlers, eventmask_t mask);
|
||||
#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT
|
||||
eventmask_t chEvtWaitOne(eventmask_t mask);
|
||||
eventmask_t chEvtWaitAny(eventmask_t mask);
|
||||
eventmask_t chEvtWaitAll(eventmask_t mask);
|
||||
#endif
|
||||
#if CH_USE_EVENTS_TIMEOUT
|
||||
eventmask_t chEvtWaitOneTimeout(eventmask_t mask, systime_t time);
|
||||
eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t time);
|
||||
eventmask_t chEvtWaitAllTimeout(eventmask_t mask, systime_t time);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !CH_OPTIMIZE_SPEED && CH_USE_EVENTS_TIMEOUT
|
||||
#define chEvtWaitOne(mask) chEvtWaitOneTimeout(mask, TIME_INFINITE)
|
||||
#define chEvtWaitAny(mask) chEvtWaitAnyTimeout(mask, TIME_INFINITE)
|
||||
#define chEvtWaitAll(mask) chEvtWaitAllTimeout(mask, TIME_INFINITE)
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
#endif /* _CHEVENTS_H_ */
|
||||
|
||||
/** @} */
|
||||
97
ChibiOS_2.0.8/os/kernel/include/chheap.h
Normal file
97
ChibiOS_2.0.8/os/kernel/include/chheap.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chheap.h
|
||||
* @brief Heaps macros and structures.
|
||||
*
|
||||
* @addtogroup heaps
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHHEAP_H_
|
||||
#define _CHHEAP_H_
|
||||
|
||||
#if CH_USE_HEAP
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if !CH_USE_MEMCORE && !CH_USE_MALLOC_HEAP
|
||||
#error "CH_USE_HEAP requires CH_USE_MEMCORE or CH_USE_MALLOC_HEAP"
|
||||
#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.
|
||||
*/
|
||||
union heap_header {
|
||||
stkalign_t align;
|
||||
struct {
|
||||
union {
|
||||
union heap_header *next; /**< @brief Next block in free list. */
|
||||
MemoryHeap *heap; /**< @brief Block owner heap. */
|
||||
} u; /**< @brief Overlapped fields. */
|
||||
size_t size; /**< @brief Size of the memory block. */
|
||||
} h;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure describing a memory heap.
|
||||
*/
|
||||
struct memory_heap {
|
||||
memgetfunc_t h_provider; /**< @brief Memory blocks provider for
|
||||
this heap. */
|
||||
union 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 chHeapInit(MemoryHeap *heapp, void *buf, size_t size);
|
||||
void *chHeapAlloc(MemoryHeap *heapp, size_t size);
|
||||
void chHeapFree(void *p);
|
||||
size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_HEAP */
|
||||
|
||||
#endif /* _CHHEAP_H_ */
|
||||
|
||||
/** @} */
|
||||
93
ChibiOS_2.0.8/os/kernel/include/chinline.h
Normal file
93
ChibiOS_2.0.8/os/kernel/include/chinline.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chinline.h
|
||||
* @brief Kernel inlined functions.
|
||||
* @details In this file there are a set of inlined functions if the
|
||||
* @p CH_OPTIMIZE_SPEED is enabled.
|
||||
*/
|
||||
|
||||
#ifndef _CHINLINE_H_
|
||||
#define _CHINLINE_H_
|
||||
|
||||
/* If the performance code path has been chosen then all the following
|
||||
functions are inlined into the various kernel modules.*/
|
||||
#if CH_OPTIMIZE_SPEED
|
||||
static INLINE void prio_insert(Thread *tp, ThreadsQueue *tqp) {
|
||||
|
||||
Thread *cp = (Thread *)tqp;
|
||||
do {
|
||||
cp = cp->p_next;
|
||||
} while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
|
||||
tp->p_next = cp;
|
||||
tp->p_prev = cp->p_prev;
|
||||
tp->p_prev->p_next = cp->p_prev = tp;
|
||||
}
|
||||
|
||||
static INLINE void queue_insert(Thread *tp, ThreadsQueue *tqp) {
|
||||
|
||||
tp->p_next = (Thread *)tqp;
|
||||
tp->p_prev = tqp->p_prev;
|
||||
tp->p_prev->p_next = tqp->p_prev = tp;
|
||||
}
|
||||
|
||||
static INLINE Thread *fifo_remove(ThreadsQueue *tqp) {
|
||||
Thread *tp = tqp->p_next;
|
||||
|
||||
(tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
|
||||
return tp;
|
||||
}
|
||||
|
||||
static INLINE Thread *lifo_remove(ThreadsQueue *tqp) {
|
||||
Thread *tp = tqp->p_prev;
|
||||
|
||||
(tqp->p_prev = tp->p_prev)->p_next = (Thread *)tqp;
|
||||
return tp;
|
||||
}
|
||||
|
||||
static INLINE Thread *dequeue(Thread *tp) {
|
||||
|
||||
tp->p_prev->p_next = tp->p_next;
|
||||
tp->p_next->p_prev = tp->p_prev;
|
||||
return tp;
|
||||
}
|
||||
|
||||
static INLINE void list_insert(Thread *tp, ThreadsList *tlp) {
|
||||
|
||||
tp->p_next = tlp->p_next;
|
||||
tlp->p_next = tp;
|
||||
}
|
||||
|
||||
static INLINE Thread *list_remove(ThreadsList *tlp) {
|
||||
|
||||
Thread *tp = tlp->p_next;
|
||||
tlp->p_next = tp->p_next;
|
||||
return tp;
|
||||
}
|
||||
#endif /* CH_OPTIMIZE_SPEED */
|
||||
|
||||
#endif /* _CHINLINE_H_ */
|
||||
284
ChibiOS_2.0.8/os/kernel/include/chioch.h
Normal file
284
ChibiOS_2.0.8/os/kernel/include/chioch.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chioch.h
|
||||
* @brief I/O channels.
|
||||
* @details This header defines abstract interfaces useful to access generic
|
||||
* I/O resources in a standardized way.
|
||||
*
|
||||
* @addtogroup io_channels
|
||||
* @details This module defines an abstract interface for I/O channels by
|
||||
* extending the @p BaseSequentialStream interface. Note that no code
|
||||
* is present, I/O channels are just abstract interface like
|
||||
* structures, you should look at the systems as to a set of abstract
|
||||
* C++ classes (even if written in C). Specific device drivers can
|
||||
* use/extend the interface and implement them.<br>
|
||||
* This system has the advantage to make the access to channels
|
||||
* independent from the implementation logic.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHIOCH_H_
|
||||
#define _CHIOCH_H_
|
||||
|
||||
/**
|
||||
* @brief @p BaseChannel specific methods.
|
||||
*/
|
||||
#define _base_channel_methods \
|
||||
_base_sequential_stream_methods \
|
||||
/* Channel output check.*/ \
|
||||
bool_t (*putwouldblock)(void *instance); \
|
||||
/* Channel input check.*/ \
|
||||
bool_t (*getwouldblock)(void *instance); \
|
||||
/* Channel put method with timeout specification.*/ \
|
||||
msg_t (*put)(void *instance, uint8_t b, systime_t time); \
|
||||
/* Channel get method with timeout specification.*/ \
|
||||
msg_t (*get)(void *instance, systime_t time); \
|
||||
/* Channel write method with timeout specification.*/ \
|
||||
size_t (*writet)(void *instance, const uint8_t *bp, \
|
||||
size_t n, systime_t time); \
|
||||
/* Channel read method with timeout specification.*/ \
|
||||
size_t (*readt)(void *instance, uint8_t *bp, size_t n, systime_t time);
|
||||
|
||||
/**
|
||||
* @brief @p BaseChannel specific data.
|
||||
* @note It is empty because @p BaseChannel is only an interface without
|
||||
* implementation.
|
||||
*/
|
||||
#define _base_channel_data \
|
||||
_base_sequential_stream_data
|
||||
|
||||
/**
|
||||
* @brief @p BaseChannel virtual methods table.
|
||||
*/
|
||||
struct BaseChannelVMT { \
|
||||
_base_channel_methods \
|
||||
};
|
||||
|
||||
/**
|
||||
* @extends BaseSequentialStream
|
||||
*
|
||||
* @brief Base channel class.
|
||||
* @details This class represents a generic, byte-wide, I/O channel. This class
|
||||
* introduces generic I/O primitives with timeout specification.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief Virtual Methods Table.*/
|
||||
const struct BaseChannelVMT *vmt;
|
||||
_base_channel_data
|
||||
} BaseChannel;
|
||||
|
||||
/**
|
||||
* @brief Channel output check.
|
||||
* @details This function verifies if a subsequent put/write operation would
|
||||
* block.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @return The output queue status:
|
||||
* @retval FALSE if the output queue has space and would not block a
|
||||
* write operation.
|
||||
* @retval TRUE if the output queue is full and would block a write
|
||||
* operation.
|
||||
*/
|
||||
#define chIOPutWouldBlock(ip) ((ip)->vmt->putwouldblock(ip))
|
||||
|
||||
/**
|
||||
* @brief Channel input check.
|
||||
* @details This function verifies if a subsequent get/read operation would
|
||||
* block.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @return The input queue status:
|
||||
* @retval FALSE if the input queue contains data and would not block a
|
||||
* read operation.
|
||||
* @retval TRUE if the input queue is empty and would block a read
|
||||
* operation.
|
||||
*/
|
||||
#define chIOGetWouldBlock(ip) ((ip)->vmt->getwouldblock(ip))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking byte write.
|
||||
* @details This function writes a byte value to a channel. If the channel
|
||||
* is not ready to accept data then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @param[in] b the byte value to be written to the channel
|
||||
* @return The operation status:
|
||||
* @retval Q_OK if the operation succeeded.
|
||||
* @retval Q_RESET if the channel associated queue (if any) was reset.
|
||||
*/
|
||||
#define chIOPut(ip, b) ((ip)->vmt->put(ip, b, TIME_INFINITE))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking byte write with timeout.
|
||||
* @details This function writes a byte value to a channel. If the channel
|
||||
* is not ready to accept data then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @param[in] b the byte value to be written to the channel
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status:
|
||||
* @retval Q_OK if the operation succeeded.
|
||||
* @retval Q_TIMEOUT if the specified time expired.
|
||||
* @retval Q_RESET if the channel associated queue (if any) was reset.
|
||||
*/
|
||||
#define chIOPutTimeout(ip, b, time) ((ip)->vmt->put(ip, b, time))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking byte read.
|
||||
* @details This function reads a byte value from a channel. If the data
|
||||
* is not available then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @return A byte value from the queue or:
|
||||
* @retval Q_RESET if the channel associated queue (if any) was reset.
|
||||
*/
|
||||
#define chIOGet(ip) ((ip)->vmt->get(ip, TIME_INFINITE))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking byte read with timeout.
|
||||
* @details This function reads a byte value from a channel. If the data
|
||||
* is not available then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return A byte value from the queue or:
|
||||
* @retval Q_TIMEOUT if the specified time expired.
|
||||
* @retval Q_RESET if the channel associated queue (if any) was reset.
|
||||
*/
|
||||
#define chIOGetTimeout(ip, time) ((ip)->vmt->get(ip, time))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking write with timeout.
|
||||
* @details The function writes data from a buffer to a channel. If the channel
|
||||
* is not ready to accept data then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @param[out] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The number of bytes transferred.
|
||||
*/
|
||||
#define chIOWriteTimeout(ip, bp, n, time) \
|
||||
((ip)->vmt->writet(ip, bp, n, time))
|
||||
|
||||
/**
|
||||
* @brief Channel blocking read with timeout.
|
||||
* @details The function reads data from a channel into a buffer. If the data
|
||||
* is not available then the calling thread is suspended.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseChannel or derived class
|
||||
* @param[in] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The number of bytes transferred.
|
||||
*/
|
||||
#define chIOReadTimeout(ip, bp, n, time) \
|
||||
((ip)->vmt->readt(ip, bp, n, time))
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
/**
|
||||
* @brief @p BaseAsynchronousChannel specific methods.
|
||||
*/
|
||||
#define _base_asynchronous_channel_methods \
|
||||
_base_channel_methods
|
||||
|
||||
/**
|
||||
* @brief @p BaseAsynchronousChannel specific data.
|
||||
*/
|
||||
#define _base_asynchronous_channel_data \
|
||||
_base_channel_data \
|
||||
/* Data Available EventSource.*/ \
|
||||
EventSource ievent; \
|
||||
/* Data Transmitted EventSource.*/ \
|
||||
EventSource oevent;
|
||||
|
||||
/**
|
||||
* @brief @p BaseAsynchronousChannel virtual methods table.
|
||||
*/
|
||||
struct BaseAsynchronousChannelVMT {
|
||||
_base_asynchronous_channel_methods
|
||||
};
|
||||
|
||||
/**
|
||||
* @extends BaseChannel
|
||||
*
|
||||
* @brief Base asynchronous channel class.
|
||||
* @details This class extends @p BaseChannel by adding event sources fields
|
||||
* for asynchronous I/O for use in an event-driven environment.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief Virtual Methods Table.*/
|
||||
const struct BaseAsynchronousChannelVMT *vmt;
|
||||
_base_asynchronous_channel_data
|
||||
} BaseAsynchronousChannel;
|
||||
|
||||
/**
|
||||
* @brief Returns the write event source.
|
||||
* @details The write event source is broadcasted when the channel is ready
|
||||
* for write operations. This usually happens when the internal
|
||||
* output queue becomes empty.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived
|
||||
* class
|
||||
* @return A pointer to an @p EventSource object.
|
||||
*/
|
||||
#define chIOGetWriteEventSource(ip) (&((ip)->vmt->oevent))
|
||||
|
||||
/**
|
||||
* @brief Returns the read event source.
|
||||
* @details The read event source is broadcasted when the channel is ready
|
||||
* for read operations. This usually happens when the internal
|
||||
* input queue becomes non-empty.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived
|
||||
* class
|
||||
* @return A pointer to an @p EventSource object.
|
||||
*/
|
||||
#define chIOGetReadEventSource(ip) (&((ip)->vmt->ievent))
|
||||
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
#endif /* _CHIOCH_H_ */
|
||||
|
||||
/** @} */
|
||||
125
ChibiOS_2.0.8/os/kernel/include/chlists.h
Normal file
125
ChibiOS_2.0.8/os/kernel/include/chlists.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chlists.h
|
||||
* @brief Thread queues/lists macros and structures.
|
||||
* @note All the macros present in this module, while public, are not
|
||||
* an OS API and should not be directly used in the user applications
|
||||
* code.
|
||||
*
|
||||
* @addtogroup internals
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHLISTS_H_
|
||||
#define _CHLISTS_H_
|
||||
|
||||
typedef struct Thread Thread;
|
||||
|
||||
/**
|
||||
* @brief Threads queue initialization.
|
||||
*/
|
||||
#define queue_init(tqp) ((tqp)->p_next = (tqp)->p_prev = (Thread *)(tqp));
|
||||
|
||||
/**
|
||||
* @brief Threads list initialization.
|
||||
*/
|
||||
#define list_init(tlp) ((tlp)->p_next = (Thread *)(tlp))
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p TRUE if the specified threads queue or list is
|
||||
* empty.
|
||||
*/
|
||||
#define isempty(p) ((p)->p_next == (Thread *)(p))
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p TRUE if the specified threads queue or list is
|
||||
* not empty.
|
||||
*/
|
||||
#define notempty(p) ((p)->p_next != (Thread *)(p))
|
||||
|
||||
/**
|
||||
* @brief Data part of a static threads queue initializer.
|
||||
* @details This macro should be used when statically initializing a threads
|
||||
* queue that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the threads queue variable
|
||||
*/
|
||||
#define _THREADSQUEUE_DATA(name) {(Thread *)&name, (Thread *)&name}
|
||||
|
||||
/**
|
||||
* @brief Static threads queue initializer.
|
||||
* @details Statically initialized threads queues require no explicit
|
||||
* initialization using @p queue_init().
|
||||
*
|
||||
* @param[in] name the name of the threads queue variable
|
||||
*/
|
||||
#define THREADSQUEUE_DECL(name) ThreadsQueue name = _THREADSQUEUE_DATA(name)
|
||||
|
||||
/**
|
||||
* @extends ThreadsList
|
||||
*
|
||||
* @brief Generic threads bidirectional linked list header and element.
|
||||
*/
|
||||
typedef struct {
|
||||
Thread *p_next; /**< First @p Thread in the queue, or
|
||||
@p ThreadQueue when empty. */
|
||||
Thread *p_prev; /**< Last @p Thread in the queue, or
|
||||
@p ThreadQueue when empty. */
|
||||
} ThreadsQueue;
|
||||
|
||||
/**
|
||||
* @brief Generic threads single link list, it works like a stack.
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
Thread *p_next; /**< Last pushed @p Thread on the stack
|
||||
list, or pointer to itself if
|
||||
empty. */
|
||||
} ThreadsList;
|
||||
|
||||
#if !CH_OPTIMIZE_SPEED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void prio_insert(Thread *tp, ThreadsQueue *tqp);
|
||||
void queue_insert(Thread *tp, ThreadsQueue *tqp);
|
||||
Thread *fifo_remove(ThreadsQueue *tqp);
|
||||
Thread *lifo_remove(ThreadsQueue *tqp);
|
||||
Thread *dequeue(Thread *tp);
|
||||
void list_insert(Thread *tp, ThreadsList *tlp);
|
||||
Thread *list_remove(ThreadsList *tlp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CH_OPTIMIZE_SPEED */
|
||||
|
||||
#endif /* _CHLISTS_H_ */
|
||||
|
||||
/** @} */
|
||||
150
ChibiOS_2.0.8/os/kernel/include/chmboxes.h
Normal file
150
ChibiOS_2.0.8/os/kernel/include/chmboxes.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmboxes.h
|
||||
* @brief Mailboxes macros and structures.
|
||||
*
|
||||
* @addtogroup mailboxes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHMBOXES_H_
|
||||
#define _CHMBOXES_H_
|
||||
|
||||
#if CH_USE_MAILBOXES
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if !CH_USE_SEMAPHORES
|
||||
#error "CH_USE_MAILBOXES requires CH_USE_SEMAPHORES"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
msg_t *mb_buffer; /**< @brief Pointer to the mailbox
|
||||
buffer. */
|
||||
msg_t *mb_top; /**< @brief Pointer to the location
|
||||
after the buffer. */
|
||||
msg_t *mb_wrptr; /**< @brief Write pointer. */
|
||||
msg_t *mb_rdptr; /**< @brief Read pointer. */
|
||||
Semaphore mb_fullsem; /**< @brief Full counter
|
||||
@p Semaphore. */
|
||||
Semaphore mb_emptysem; /**< @brief Empty counter
|
||||
@p Semaphore. */
|
||||
} Mailbox;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n);
|
||||
void chMBReset(Mailbox *mbp);
|
||||
msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t timeout);
|
||||
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t timeout);
|
||||
msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t timeout);
|
||||
msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t timeout);
|
||||
msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t timeout);
|
||||
msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t timeout);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns the mailbox buffer size.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
*/
|
||||
#define chMBSize(mbp) \
|
||||
((mbp)->mb_top - (mbp)->mb_buffer)
|
||||
|
||||
/**
|
||||
* @brief Returns the free space into the mailbox.
|
||||
* @note Can be invoked in any system state but if invoked out of a locked
|
||||
* state then the returned value may change after reading.
|
||||
* @note The returned value can be less than zero when there are waiting
|
||||
* threads on the internal semaphore.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @return The number of empty message slots.
|
||||
*/
|
||||
#define chMBGetEmpty(mbp) chSemGetCounterI(&(mbp)->mb_emptysem)
|
||||
|
||||
/**
|
||||
* @brief Returns the number of messages into the mailbox.
|
||||
* @note Can be invoked in any system state but if invoked out of a locked
|
||||
* state then the returned value may change after reading.
|
||||
* @note The returned value can be less than zero when there are waiting
|
||||
* threads on the internal semaphore.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @return The number of queued messages.
|
||||
*/
|
||||
#define chMBGetFull(mbp) chSemGetCounterI(&(mbp)->mb_fullsem)
|
||||
|
||||
/**
|
||||
* @brief Returns the next message in the queue without removing it.
|
||||
* @note A message must be waiting in the queue for this function to work or
|
||||
* it would return garbage. The correct way to use this macro is to
|
||||
* use @p chMBGetFull() and then use this macro, all within a lock
|
||||
* state.
|
||||
*/
|
||||
#define chMBPeek(mbp) (*(mbp)->mb_rdptr)
|
||||
|
||||
/**
|
||||
* @brief Data part of a static mailbox initializer.
|
||||
* @details This macro should be used when statically initializing a
|
||||
* mailbox that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the mailbox variable
|
||||
* @param[in] buffer pointer to the mailbox buffer area
|
||||
* @param[in] size size of the mailbox buffer area
|
||||
*/
|
||||
#define _MAILBOX_DATA(name, buffer, size) { \
|
||||
(msg_t *)(buffer), \
|
||||
(msg_t *)(buffer) + size, \
|
||||
(msg_t *)(buffer), \
|
||||
(msg_t *)(buffer), \
|
||||
_SEMAPHORE_DATA(name.mb_fullsem, 0), \
|
||||
_SEMAPHORE_DATA(name.mb_emptysem, size), \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Static mailbox initializer.
|
||||
* @details Statically initialized mailboxes require no explicit
|
||||
* initialization using @p chMBInit().
|
||||
*
|
||||
* @param[in] name the name of the mailbox variable
|
||||
* @param[in] buffer pointer to the mailbox buffer area
|
||||
* @param[in] size size of the mailbox buffer area
|
||||
*/
|
||||
#define MAILBOX_DECL(name, buffer, size) \
|
||||
Mailbox name = _MAILBOX_DATA(name, buffer, size)
|
||||
|
||||
#endif /* CH_USE_MAILBOXES */
|
||||
|
||||
#endif /* _CHMBOXES_H_ */
|
||||
|
||||
/** @} */
|
||||
78
ChibiOS_2.0.8/os/kernel/include/chmemcore.h
Normal file
78
ChibiOS_2.0.8/os/kernel/include/chmemcore.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmemcore.h
|
||||
* @brief Core memory manager macros and structures.
|
||||
*
|
||||
* @addtogroup memcore
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHMEMCORE_H_
|
||||
#define _CHMEMCORE_H_
|
||||
|
||||
/**
|
||||
* @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(stkalign_t) - 1)
|
||||
|
||||
/**
|
||||
* @brief Alignment helper macro.
|
||||
*/
|
||||
#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)
|
||||
|
||||
#if CH_USE_MEMCORE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void core_init(void);
|
||||
void *chCoreAlloc(size_t size);
|
||||
void *chCoreAllocI(size_t size);
|
||||
size_t chCoreStatus(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_MEMCORE */
|
||||
|
||||
#endif /* _CHMEMCORE_H_ */
|
||||
|
||||
/** @} */
|
||||
100
ChibiOS_2.0.8/os/kernel/include/chmempools.h
Normal file
100
ChibiOS_2.0.8/os/kernel/include/chmempools.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmempools.h
|
||||
* @brief Memory Pools macros and structures.
|
||||
*
|
||||
* @addtogroup pools
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHMEMPOOLS_H_
|
||||
#define _CHMEMPOOLS_H_
|
||||
|
||||
#if CH_USE_MEMPOOLS
|
||||
|
||||
/**
|
||||
* @brief Memory pool free object header.
|
||||
*/
|
||||
struct pool_header {
|
||||
struct pool_header *ph_next; /**< @brief Pointer to the next pool
|
||||
header in the list. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Memory pool descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
struct pool_header *mp_next; /**< @brief Pointer to the header. */
|
||||
size_t mp_object_size; /**< @brief Memory pool objects
|
||||
size. */
|
||||
memgetfunc_t mp_provider; /**< @brief Memory blocks provider for
|
||||
this pool. */
|
||||
} MemoryPool;
|
||||
|
||||
/**
|
||||
* @brief Data part of a static memory pool initializer.
|
||||
* @details This macro should be used when statically initializing a
|
||||
* memory pool that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the memory pool variable
|
||||
* @param[in] size size of the memory pool contained objects
|
||||
* @param[in] provider memory provider function for the memory pool
|
||||
*/
|
||||
#define _MEMORYPOOL_DATA(name, size, provider) \
|
||||
{NULL, MEM_ALIGN_SIZE(size), provider}
|
||||
|
||||
/**
|
||||
* @brief Static memory pool initializer in hungry mode.
|
||||
* @details Statically initialized memory pools require no explicit
|
||||
* initialization using @p chPoolInit().
|
||||
*
|
||||
* @param[in] name the name of the memory pool variable
|
||||
* @param[in] size size of the memory pool contained objects
|
||||
* @param[in] provider memory provider function for the memory pool or @p NULL
|
||||
* if the pool is not allowed to grow automatically
|
||||
*/
|
||||
#define MEMORYPOOL_DECL(name, size, provider) \
|
||||
MemoryPool name = _MEMORYPOOL_DATA(name, size, provider)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chPoolInit(MemoryPool *mp, size_t size, memgetfunc_t provider);
|
||||
void *chPoolAllocI(MemoryPool *mp);
|
||||
void *chPoolAlloc(MemoryPool *mp);
|
||||
void chPoolFreeI(MemoryPool *mp, void *objp);
|
||||
void chPoolFree(MemoryPool *mp, void *objp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_MEMPOOLS */
|
||||
|
||||
#endif /* _CHMEMPOOLS_H_ */
|
||||
|
||||
/** @} */
|
||||
67
ChibiOS_2.0.8/os/kernel/include/chmsg.h
Normal file
67
ChibiOS_2.0.8/os/kernel/include/chmsg.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmsg.h
|
||||
* @brief Messages macros and structures.
|
||||
*
|
||||
* @addtogroup messages
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHMSG_H_
|
||||
#define _CHMSG_H_
|
||||
|
||||
#if CH_USE_MESSAGES
|
||||
|
||||
/**
|
||||
* @brief Evaluates to TRUE if the thread has pending messages.
|
||||
*/
|
||||
#define chMsgIsPendingI(tp) \
|
||||
((tp)->p_msgqueue.p_next != (Thread *)&(tp)->p_msgqueue)
|
||||
|
||||
/**
|
||||
* @brief Returns the first message in the queue.
|
||||
*/
|
||||
#define chMsgGetI(tp) \
|
||||
((tp)->p_msgqueue.p_next->p_msg)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
msg_t chMsgSend(Thread *tp, msg_t msg);
|
||||
msg_t chMsgWait(void);
|
||||
msg_t chMsgGet(void);
|
||||
void chMsgRelease(msg_t msg);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_MESSAGES */
|
||||
|
||||
#endif /* _CHMSG_H_ */
|
||||
|
||||
/** @} */
|
||||
95
ChibiOS_2.0.8/os/kernel/include/chmtx.h
Normal file
95
ChibiOS_2.0.8/os/kernel/include/chmtx.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmtx.h
|
||||
* @brief Mutexes macros and structures.
|
||||
*
|
||||
* @addtogroup mutexes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHMTX_H_
|
||||
#define _CHMTX_H_
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
|
||||
/**
|
||||
* @brief Mutex structure.
|
||||
*/
|
||||
typedef struct Mutex {
|
||||
ThreadsQueue m_queue; /**< @brief Queue of the threads sleeping
|
||||
on this Mutex. */
|
||||
Thread *m_owner; /**< @brief Owner @p Thread pointer or
|
||||
@p NULL. */
|
||||
struct Mutex *m_next; /**< @brief Next @p Mutex into an
|
||||
owner-list or @p NULL. */
|
||||
} Mutex;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chMtxInit(Mutex *mp);
|
||||
void chMtxLock(Mutex *mp);
|
||||
void chMtxLockS(Mutex *mp);
|
||||
bool_t chMtxTryLock(Mutex *mp);
|
||||
bool_t chMtxTryLockS(Mutex *mp);
|
||||
Mutex *chMtxUnlock(void);
|
||||
Mutex *chMtxUnlockS(void);
|
||||
void chMtxUnlockAll(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data part of a static mutex initializer.
|
||||
* @details This macro should be used when statically initializing a mutex
|
||||
* that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the mutex variable
|
||||
*/
|
||||
#define _MUTEX_DATA(name) {_THREADSQUEUE_DATA(name.m_queue), NULL, NULL}
|
||||
|
||||
/**
|
||||
* @brief Static mutex initializer.
|
||||
* @details Statically initialized mutexes require no explicit initialization
|
||||
* using @p chMtxInit().
|
||||
*
|
||||
* @param[in] name the name of the mutex variable
|
||||
*/
|
||||
#define MUTEX_DECL(name) Mutex name = _MUTEX_DATA(name)
|
||||
|
||||
/**
|
||||
* @brief Returns @p TRUE if the mutex queue contains at least a waiting
|
||||
* thread.
|
||||
*/
|
||||
#define chMtxQueueNotEmptyS(mp) notempty(&(mp)->m_queue)
|
||||
|
||||
#endif /* CH_USE_MUTEXES */
|
||||
|
||||
#endif /* _CHMTX_H_ */
|
||||
|
||||
/** @} */
|
||||
249
ChibiOS_2.0.8/os/kernel/include/chqueues.h
Normal file
249
ChibiOS_2.0.8/os/kernel/include/chqueues.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chqueues.h I/O
|
||||
* @brief Queues macros and structures.
|
||||
*
|
||||
* @addtogroup io_queues
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHQUEUES_H_
|
||||
#define _CHQUEUES_H_
|
||||
|
||||
#if CH_USE_QUEUES
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if !CH_USE_SEMAPHORES
|
||||
#error "CH_USE_QUEUES requires CH_USE_SEMAPHORES"
|
||||
#endif
|
||||
|
||||
/** @brief Queue notification callback type.*/
|
||||
typedef void (*qnotify_t)(void);
|
||||
|
||||
/** @brief Returned by the queue functions if the operation is successful.*/
|
||||
#define Q_OK RDY_OK
|
||||
/** @brief Returned by the queue functions if a timeout occurs.*/
|
||||
#define Q_TIMEOUT RDY_TIMEOUT
|
||||
/** @brief Returned by the queue functions if the queue is reset.*/
|
||||
#define Q_RESET RDY_RESET
|
||||
/** @brief Returned by the queue functions if the queue is empty.*/
|
||||
#define Q_EMPTY -3
|
||||
/** @brief Returned by the queue functions if the queue is full.*/
|
||||
#define Q_FULL -4
|
||||
|
||||
/**
|
||||
* @brief Generic I/O queue structure.
|
||||
* @details This structure represents a generic Input or Output asymmetrical
|
||||
* queue. The queue is asymmetrical because one end is meant to be
|
||||
* accessed from a thread context, and thus can be blocking, the other
|
||||
* end is accessible from interrupt handlers or from within a kernel
|
||||
* lock zone (see <b>I-Locked</b> and <b>S-Locked</b> states in
|
||||
* @ref system_states) and is non-blocking.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *q_buffer; /**< @brief Pointer to the queue buffer.*/
|
||||
uint8_t *q_top; /**< @brief Pointer to the first location
|
||||
after the buffer. */
|
||||
uint8_t *q_wrptr; /**< @brief Write pointer. */
|
||||
uint8_t *q_rdptr; /**< @brief Read pointer. */
|
||||
Semaphore q_sem; /**< @brief Counter @p Semaphore. */
|
||||
qnotify_t q_notify; /**< @brief Data notification callback. */
|
||||
} GenericQueue;
|
||||
|
||||
/**
|
||||
* @brief Returns the queue's buffer size.
|
||||
*/
|
||||
#define chQSize(q) ((q)->q_top - (q)->q_buffer)
|
||||
|
||||
/**
|
||||
* @brief Queue space.
|
||||
* @details Returns the used space if used on an Input Queue and the empty
|
||||
* space if used on an Output Queue.
|
||||
* @note The returned value can be less than zero when there are waiting
|
||||
* threads on the internal semaphore.
|
||||
*/
|
||||
#define chQSpace(q) chSemGetCounterI(&(q)->q_sem)
|
||||
|
||||
/**
|
||||
* @extends GenericQueue
|
||||
*
|
||||
* @brief Input queue structure.
|
||||
* @details This structure represents a generic asymmetrical input queue.
|
||||
* Writing in the queue is non-blocking and can be performed from
|
||||
* interrupt handlers or from within a kernel lock zone (see
|
||||
* <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
|
||||
* Reading the queue can be a blocking operation and is supposed to
|
||||
* be performed by a system thread.
|
||||
*/
|
||||
typedef GenericQueue InputQueue;
|
||||
|
||||
/** @brief Evaluates to @p TRUE if the specified Input Queue is empty.*/
|
||||
#define chIQIsEmpty(q) ((bool_t)(chQSpace(q) <= 0))
|
||||
|
||||
/** @brief Evaluates to @p TRUE if the specified Input Queue is full.*/
|
||||
#define chIQIsFull(q) ((bool_t)(chQSpace(q) >= chQSize(q)))
|
||||
|
||||
/**
|
||||
* @brief Input queue read.
|
||||
* @details This function reads a byte value from an input queue. If the queue
|
||||
* is empty then the calling thread is suspended until a byte arrives
|
||||
* in the queue.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
* @return A byte value from the queue or:
|
||||
* @retval Q_RESET if the queue was reset.
|
||||
*/
|
||||
#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE)
|
||||
|
||||
/**
|
||||
* @brief Data part of a static input queue initializer.
|
||||
* @details This macro should be used when statically initializing an
|
||||
* input queue that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the input queue variable
|
||||
* @param[in] buffer pointer to the queue buffer area
|
||||
* @param[in] size size of the queue buffer area
|
||||
* @param[in] inotify input notification callback pointer
|
||||
*/
|
||||
#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \
|
||||
(uint8_t *)(buffer), \
|
||||
(uint8_t *)(buffer) + size, \
|
||||
(uint8_t *)(buffer), \
|
||||
(uint8_t *)(buffer), \
|
||||
_SEMAPHORE_DATA(name.q_sem, 0), \
|
||||
inotify \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Static input queue initializer.
|
||||
* @details Statically initialized input queues require no explicit
|
||||
* initialization using @p chIQInit().
|
||||
*
|
||||
* @param[in] name the name of the input queue variable
|
||||
* @param[in] buffer pointer to the queue buffer area
|
||||
* @param[in] size size of the queue buffer area
|
||||
* @param[in] inotify input notification callback pointer
|
||||
*/
|
||||
#define INPUTQUEUE_DECL(name, buffer, size, inotify) \
|
||||
InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify)
|
||||
|
||||
/**
|
||||
* @extends GenericQueue
|
||||
*
|
||||
* @brief Output queue structure.
|
||||
* @details This structure represents a generic asymmetrical output queue.
|
||||
* Reading from the queue is non-blocking and can be performed from
|
||||
* interrupt handlers or from within a kernel lock zone (see
|
||||
* <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
|
||||
* Writing the queue can be a blocking operation and is supposed to
|
||||
* be performed by a system thread.
|
||||
*/
|
||||
typedef GenericQueue OutputQueue;
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p TRUE if the specified Output Queue is empty.
|
||||
*/
|
||||
#define chOQIsEmpty(q) ((bool_t)(chQSpace(q) >= chQSize(q)))
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p TRUE if the specified Output Queue is full.
|
||||
*/
|
||||
#define chOQIsFull(q) ((bool_t)(chQSpace(q) <= 0))
|
||||
|
||||
/**
|
||||
* @brief Output queue write.
|
||||
* @details This function writes a byte value to an output queue. If the queue
|
||||
* is full then the calling thread is suspended until there is space
|
||||
* in the queue.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
* @param[in] b the byte value to be written in the queue
|
||||
* @return The operation status:
|
||||
* @retval Q_OK if the operation succeeded.
|
||||
* @retval Q_RESET if the queue was reset.
|
||||
*/
|
||||
#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE)
|
||||
|
||||
/**
|
||||
* @brief Data part of a static output queue initializer.
|
||||
* @details This macro should be used when statically initializing an
|
||||
* output queue that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the output queue variable.
|
||||
* @param[in] buffer pointer to the queue buffer area
|
||||
* @param[in] size size of the queue buffer area
|
||||
* @param[in] onotify output notification callback pointer
|
||||
*/
|
||||
#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \
|
||||
(uint8_t *)(buffer), \
|
||||
(uint8_t *)(buffer) + size, \
|
||||
(uint8_t *)(buffer), \
|
||||
(uint8_t *)(buffer), \
|
||||
_SEMAPHORE_DATA(name.q_sem, size), \
|
||||
onotify \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Static output queue initializer.
|
||||
* @details Statically initialized output queues require no explicit
|
||||
* initialization using @p chOQInit().
|
||||
*
|
||||
* @param[in] name the name of the output queue variable
|
||||
* @param[in] buffer pointer to the queue buffer area
|
||||
* @param[in] size size of the queue buffer area
|
||||
* @param[in] onotify output notification callback pointer
|
||||
*/
|
||||
#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \
|
||||
InputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chIQInit(InputQueue *qp, uint8_t *bp, size_t size, qnotify_t infy);
|
||||
void chIQResetI(InputQueue *qp);
|
||||
msg_t chIQPutI(InputQueue *qp, uint8_t b);
|
||||
msg_t chIQGetTimeout(InputQueue *qp, systime_t time);
|
||||
size_t chIQReadTimeout(InputQueue *qp, uint8_t *bp,
|
||||
size_t n, systime_t time);
|
||||
|
||||
void chOQInit(OutputQueue *queue, uint8_t *bp, size_t size, qnotify_t onfy);
|
||||
void chOQResetI(OutputQueue *queue);
|
||||
msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t time);
|
||||
msg_t chOQGetI(OutputQueue *queue);
|
||||
size_t chOQWriteTimeout(OutputQueue *queue, const uint8_t *bp,
|
||||
size_t n, systime_t time);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* CH_USE_QUEUES */
|
||||
|
||||
#endif /* _CHQUEUES_H_ */
|
||||
|
||||
/** @} */
|
||||
76
ChibiOS_2.0.8/os/kernel/include/chregistry.h
Normal file
76
ChibiOS_2.0.8/os/kernel/include/chregistry.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chregistry.h
|
||||
* @brief Threads registry macros and structures.
|
||||
*
|
||||
* @addtogroup registry
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHREGISTRY_H_
|
||||
#define _CHREGISTRY_H_
|
||||
|
||||
#if CH_USE_REGISTRY
|
||||
|
||||
/**
|
||||
* @brief Removes a thread from the registry list.
|
||||
* @note This macro is not meant for use in application code.
|
||||
*
|
||||
* @param[in] tp thread to remove from the registry
|
||||
*/
|
||||
#define REG_REMOVE(tp) { \
|
||||
(tp)->p_older->p_newer = (tp)->p_newer; \
|
||||
(tp)->p_newer->p_older = (tp)->p_older; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a thread to the registry list.
|
||||
* @note This macro is not meant for use in application code.
|
||||
*
|
||||
* @param[in] tp thread to add to the registry
|
||||
*/
|
||||
#define REG_INSERT(tp) { \
|
||||
(tp)->p_newer = (Thread *)&rlist; \
|
||||
(tp)->p_older = rlist.r_older; \
|
||||
(tp)->p_older->p_newer = rlist.r_older = (tp); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
Thread *chRegFirstThread(void);
|
||||
Thread *chRegNextThread(Thread *tp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_USE_REGISTRY */
|
||||
|
||||
#endif /* _CHREGISTRY_H_ */
|
||||
|
||||
/** @} */
|
||||
190
ChibiOS_2.0.8/os/kernel/include/chschd.h
Normal file
190
ChibiOS_2.0.8/os/kernel/include/chschd.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chschd.h
|
||||
* @brief Scheduler macros and structures.
|
||||
*
|
||||
* @addtogroup scheduler
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHSCHD_H_
|
||||
#define _CHSCHD_H_
|
||||
|
||||
/** @brief Default thread wakeup low level message.*/
|
||||
#define RDY_OK 0
|
||||
/** @brief Low level message sent to a thread awakened by a timeout.*/
|
||||
#define RDY_TIMEOUT -1
|
||||
/** @brief Low level message sent to a thread awakened by a reset operation.*/
|
||||
#define RDY_RESET -2
|
||||
|
||||
#define NOPRIO 0 /**< @brief Ready list header priority. */
|
||||
#define IDLEPRIO 1 /**< @brief Idle thread priority. */
|
||||
#define LOWPRIO 2 /**< @brief Lowest user priority. */
|
||||
#define NORMALPRIO 64 /**< @brief Normal user priority. */
|
||||
#define HIGHPRIO 127 /**< @brief Highest user priority. */
|
||||
#define ABSPRIO 255 /**< @brief Greatest possible priority. */
|
||||
|
||||
/**
|
||||
* @brief Zero time specification for some syscalls with a timeout
|
||||
* specification.
|
||||
* @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
|
||||
* see the specific function documentation.
|
||||
*/
|
||||
#define TIME_IMMEDIATE ((systime_t)-1)
|
||||
|
||||
/**
|
||||
* @brief Infinite time specification for all the syscalls with a timeout
|
||||
* specification.
|
||||
*/
|
||||
#define TIME_INFINITE ((systime_t)0)
|
||||
|
||||
/**
|
||||
* @brief Returns the priority of the first thread on the given ready list.
|
||||
*/
|
||||
#define firstprio(rlp) ((rlp)->p_next->p_prio)
|
||||
|
||||
/**
|
||||
* @extends ThreadsQueue
|
||||
*
|
||||
* @brief Ready list header.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_READYLIST_STRUCT) || defined(__DOXYGEN__)
|
||||
typedef struct {
|
||||
ThreadsQueue r_queue; /**< @brief Threads queue. */
|
||||
tprio_t r_prio; /**< @brief This field must be
|
||||
initialized to zero. */
|
||||
struct context r_ctx; /**< @brief Not used, present because
|
||||
offsets. */
|
||||
#if CH_USE_REGISTRY
|
||||
Thread *r_newer; /**< @brief Newer registry element. */
|
||||
Thread *r_older; /**< @brief Older registry element. */
|
||||
#endif
|
||||
/* End of the fields shared with the Thread structure.*/
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
cnt_t r_preempt; /**< @brief Round robin counter. */
|
||||
#endif
|
||||
#ifndef CH_CURRP_REGISTER_CACHE
|
||||
Thread *r_current; /**< @brief The currently running
|
||||
thread. */
|
||||
#endif
|
||||
} ReadyList;
|
||||
#endif /* !defined(PORT_OPTIMIZED_READYLIST_STRUCT) */
|
||||
|
||||
#if !defined(PORT_OPTIMIZED_RLIST_EXT) && !defined(__DOXYGEN__)
|
||||
extern ReadyList rlist;
|
||||
#endif /* !defined(PORT_OPTIMIZED_RLIST_EXT) */
|
||||
|
||||
/**
|
||||
* @brief Current thread pointer access macro.
|
||||
* @note This macro is not meant to be used in the application code but
|
||||
* only from within the kernel, use the @p chThdSelf() API instead.
|
||||
* @note It is forbidden to use this macro in order to change the pointer
|
||||
* (currp = something), use @p setcurrp() instead.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_CURRP) || defined(__DOXYGEN__)
|
||||
#if !defined(CH_CURRP_REGISTER_CACHE) || defined(__DOXYGEN__)
|
||||
#define currp rlist.r_current
|
||||
#else /* defined(CH_CURRP_REGISTER_CACHE) */
|
||||
register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
|
||||
#endif /* defined(CH_CURRP_REGISTER_CACHE) */
|
||||
#endif /* !defined(PORT_OPTIMIZED_CURRP) */
|
||||
|
||||
/**
|
||||
* @brief Current thread pointer change macro.
|
||||
* @note This macro is not meant to be used in the application code but
|
||||
* only from within the kernel.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_SETCURRP) || defined(__DOXYGEN__)
|
||||
#define setcurrp(tp) (currp = (tp))
|
||||
#endif /* !defined(PORT_OPTIMIZED_SETCURRP) */
|
||||
|
||||
/*
|
||||
* Scheduler APIs.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void scheduler_init(void);
|
||||
#if !defined(PORT_OPTIMIZED_READYI)
|
||||
Thread *chSchReadyI(Thread *tp);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_GOSLEEPS)
|
||||
void chSchGoSleepS(tstate_t newstate);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_GOSLEEPTIMEOUTS)
|
||||
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_WAKEUPS)
|
||||
void chSchWakeupS(Thread *tp, msg_t msg);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_DORESCHEDULEI)
|
||||
void chSchDoRescheduleI(void);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_RESCHEDULES)
|
||||
void chSchRescheduleS(void);
|
||||
#endif
|
||||
#if !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI)
|
||||
bool_t chSchIsRescRequiredExI(void);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Determines if the current thread must reschedule.
|
||||
* @details This function returns @p TRUE if there is a ready thread with
|
||||
* higher priority.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_ISRESCHREQUIREDI) || defined(__DOXYGEN__)
|
||||
#define chSchIsRescRequiredI() (firstprio(&rlist.r_queue) > currp->p_prio)
|
||||
#endif /* !defined(PORT_OPTIMIZED_ISRESCHREQUIREDI) */
|
||||
|
||||
/**
|
||||
* @brief Determines if yielding is possible.
|
||||
* @details This function returns @p TRUE if there is a ready thread with
|
||||
* equal or higher priority.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_CANYIELDS) || defined(__DOXYGEN__)
|
||||
#define chSchCanYieldS() (firstprio(&rlist.r_queue) >= currp->p_prio)
|
||||
#endif /* !defined(PORT_OPTIMIZED_CANYIELDS) */
|
||||
|
||||
/**
|
||||
* @brief Yields the time slot.
|
||||
* @details Yields the CPU control to the next thread in the ready list with
|
||||
* equal or higher priority, if any.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_DOYIELDS) || defined(__DOXYGEN__)
|
||||
#define chSchDoYieldS() { \
|
||||
if (chSchCanYieldS()) \
|
||||
chSchDoRescheduleI(); \
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_DOYIELDS) */
|
||||
|
||||
#endif /* _CHSCHD_H_ */
|
||||
|
||||
/** @} */
|
||||
111
ChibiOS_2.0.8/os/kernel/include/chsem.h
Normal file
111
ChibiOS_2.0.8/os/kernel/include/chsem.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chsem.h
|
||||
* @brief Semaphores macros and structures.
|
||||
*
|
||||
* @addtogroup semaphores
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHSEM_H_
|
||||
#define _CHSEM_H_
|
||||
|
||||
#if CH_USE_SEMAPHORES
|
||||
|
||||
/**
|
||||
* @brief Semaphore structure.
|
||||
*/
|
||||
typedef struct Semaphore {
|
||||
ThreadsQueue s_queue; /**< @brief Queue of the threads sleeping
|
||||
on this semaphore. */
|
||||
cnt_t s_cnt; /**< @brief The semaphore counter. */
|
||||
} Semaphore;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chSemInit(Semaphore *sp, cnt_t n);
|
||||
void chSemReset(Semaphore *sp, cnt_t n);
|
||||
void chSemResetI(Semaphore *sp, cnt_t n);
|
||||
msg_t chSemWait(Semaphore *sp);
|
||||
msg_t chSemWaitS(Semaphore *sp);
|
||||
msg_t chSemWaitTimeout(Semaphore *sp, systime_t time);
|
||||
msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time);
|
||||
void chSemSignal(Semaphore *sp);
|
||||
void chSemSignalI(Semaphore *sp);
|
||||
#if CH_USE_SEMSW
|
||||
msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data part of a static semaphore initializer.
|
||||
* @details This macro should be used when statically initializing a semaphore
|
||||
* that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the semaphore variable
|
||||
* @param[in] n the counter initial value, this value must be
|
||||
* non-negative
|
||||
*/
|
||||
#define _SEMAPHORE_DATA(name, n) {_THREADSQUEUE_DATA(name.s_queue), n}
|
||||
|
||||
/**
|
||||
* @brief Static semaphore initializer.
|
||||
* @details Statically initialized semaphores require no explicit
|
||||
* initialization using @p chSemInit().
|
||||
*
|
||||
* @param[in] name the name of the semaphore variable
|
||||
* @param[in] n the counter initial value, this value must be
|
||||
* non-negative
|
||||
*/
|
||||
#define SEMAPHORE_DECL(name, n) Semaphore name = _SEMAPHORE_DATA(name, n)
|
||||
|
||||
/**
|
||||
* @brief Decreases the semaphore counter.
|
||||
* @details This macro can be used when the counter is known to be positive.
|
||||
*/
|
||||
#define chSemFastWaitI(sp) ((sp)->s_cnt--)
|
||||
|
||||
/**
|
||||
* @brief Increases the semaphore counter.
|
||||
* @details This macro can be used when the counter is known to be not negative.
|
||||
*/
|
||||
#define chSemFastSignalI(sp) ((sp)->s_cnt++)
|
||||
|
||||
/**
|
||||
* @brief Returns the semaphore counter current value.
|
||||
*/
|
||||
#define chSemGetCounterI(sp) ((sp)->s_cnt)
|
||||
|
||||
#endif /* CH_USE_SEMAPHORES */
|
||||
|
||||
#endif /* _CHSEM_H_ */
|
||||
|
||||
/** @} */
|
||||
111
ChibiOS_2.0.8/os/kernel/include/chstreams.h
Normal file
111
ChibiOS_2.0.8/os/kernel/include/chstreams.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chstreams.h
|
||||
* @brief Data streams.
|
||||
* @details This header defines abstract interfaces useful to access generic
|
||||
* data streams in a standardized way.
|
||||
*
|
||||
* @addtogroup data_streams
|
||||
* @details This module define an abstract interface for generic data streams.
|
||||
* Note that no code is present, streams are just abstract interfaces
|
||||
* like structures, you should look at the systems as to a set of
|
||||
* abstract C++ classes (even if written in C). This system has the
|
||||
* advantage to make the access to streams independent from the
|
||||
* implementation logic.<br>
|
||||
* The stream interface can be used as base class for high level
|
||||
* object types such as files, sockets, serial ports, pipes etc.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHSTREAMS_H_
|
||||
#define _CHSTREAMS_H_
|
||||
|
||||
/**
|
||||
* @brief BaseSequentialStream specific methods.
|
||||
*/
|
||||
#define _base_sequential_stream_methods \
|
||||
/* Stream write buffer method.*/ \
|
||||
size_t (*write)(void *instance, const uint8_t *bp, size_t n); \
|
||||
/* Stream read buffer method.*/ \
|
||||
size_t (*read)(void *instance, uint8_t *bp, size_t n);
|
||||
|
||||
/**
|
||||
* @brief @p BaseSequentialStream specific data.
|
||||
* @note It is empty because @p BaseSequentialStream is only an interface
|
||||
* without implementation.
|
||||
*/
|
||||
#define _base_sequential_stream_data
|
||||
|
||||
/**
|
||||
* @brief @p BaseSequentialStream virtual methods table.
|
||||
*/
|
||||
struct BaseSequentialStreamVMT {
|
||||
_base_sequential_stream_methods
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base stream class.
|
||||
* @details This class represents a generic blocking unbuffered sequential
|
||||
* data stream.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief Virtual Methods Table.*/
|
||||
const struct BaseSequentialStreamVMT *vmt;
|
||||
_base_sequential_stream_data
|
||||
} BaseSequentialStream;
|
||||
|
||||
/**
|
||||
* @brief Sequential Stream write.
|
||||
* @details The function writes data from a buffer to a stream.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseSequentialStream or derived class
|
||||
* @param[in] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred
|
||||
* @return The number of bytes transferred. The return value can
|
||||
* be less than the specified number of bytes if the
|
||||
* stream reaches a physical end of file and cannot be
|
||||
* extended.
|
||||
*/
|
||||
#define chSequentialStreamWrite(ip, bp, n) ((ip)->vmt->write(ip, bp, n))
|
||||
|
||||
/**
|
||||
* @brief Sequential Stream read.
|
||||
* @details The function reads data from a stream into a buffer.
|
||||
*
|
||||
* @param[in] ip pointer to a @p BaseSequentialStream or derived class
|
||||
* @param[out] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred
|
||||
* @return The number of bytes transferred. The return value can
|
||||
* be less than the specified number of bytes if the
|
||||
* stream reaches the end of the available data.
|
||||
*/
|
||||
#define chSequentialStreamRead(ip, bp, n) ((ip)->vmt->read(ip, bp, n))
|
||||
|
||||
#endif /* _CHSTREAMS_H_ */
|
||||
|
||||
/** @} */
|
||||
193
ChibiOS_2.0.8/os/kernel/include/chsys.h
Normal file
193
ChibiOS_2.0.8/os/kernel/include/chsys.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chsys.h
|
||||
* @brief System related macros and structures.
|
||||
*
|
||||
* @addtogroup system
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHSYS_H_
|
||||
#define _CHSYS_H_
|
||||
|
||||
/**
|
||||
* @brief Halts the system.
|
||||
* @details This function is invoked by the operating system when an
|
||||
* unrecoverable error is detected, as example because a programming
|
||||
* error in the application code that triggers an assertion while
|
||||
* in debug mode.
|
||||
*/
|
||||
#define chSysHalt() port_halt()
|
||||
|
||||
/**
|
||||
* @brief Performs a context switch.
|
||||
*
|
||||
* @param[in] ntp the thread to be switched in
|
||||
* @param[in] otp the thread to be switched out
|
||||
*/
|
||||
#define chSysSwitchI(ntp, otp) port_switch(ntp, otp)
|
||||
|
||||
/**
|
||||
* @brief Raises the system interrupt priority mask to the maximum level.
|
||||
* @details All the maskable interrupt sources are disabled regardless their
|
||||
* hardware priority.
|
||||
* @note The implementation is architecture dependent, it may just disable
|
||||
* the interrupts or be exactly equivalent to @p chSysDisable().
|
||||
* @note Do not invoke this API from within a kernel lock.
|
||||
*/
|
||||
#define chSysDisable() port_disable()
|
||||
|
||||
/**
|
||||
* @brief Raises the system interrupt priority mask to system level.
|
||||
* @details The interrupt sources that should not be able to preempt the kernel
|
||||
* are disabled, interrupt sources with higher priority are still
|
||||
* enabled.
|
||||
* @note The implementation is architecture dependent, it may just disable
|
||||
* the interrupts.
|
||||
* @note Do not invoke this API from within a kernel lock.
|
||||
* @note This API is no replacement for @p chSysLock(), the @p chSysLock()
|
||||
* could do more than just disable the interrupts.
|
||||
*/
|
||||
#define chSysSuspend() port_suspend()
|
||||
|
||||
/**
|
||||
* @brief Lowers the system interrupt priority mask to user level.
|
||||
* @details All the interrupt sources are enabled.
|
||||
* @note The implementation is architecture dependent, it may just enable
|
||||
* the interrupts.
|
||||
* @note Do not invoke this API from within a kernel lock.
|
||||
* @note This API is no replacement for @p chSysUnlock(), the
|
||||
* @p chSysUnlock() could do more than just enable the interrupts.
|
||||
*/
|
||||
#define chSysEnable() port_enable()
|
||||
|
||||
/**
|
||||
* @brief Enters the kernel lock mode.
|
||||
* @note The use of kernel lock mode is not recommended in the user code,
|
||||
* it is a better idea to use the semaphores or mutexes instead.
|
||||
* @see CH_USE_NESTED_LOCKS
|
||||
*/
|
||||
#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
|
||||
#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
|
||||
#define chSysLock() { \
|
||||
if (currp->p_locks++ == 0) \
|
||||
port_lock(); \
|
||||
}
|
||||
#endif /* CH_OPTIMIZE_SPEED */
|
||||
#else /* !CH_USE_NESTED_LOCKS */
|
||||
#define chSysLock() port_lock()
|
||||
#endif /* !CH_USE_NESTED_LOCKS */
|
||||
|
||||
/**
|
||||
* @brief Leaves the kernel lock mode.
|
||||
* @note The use of kernel lock mode is not recommended in the user code,
|
||||
* it is a better idea to use the semaphores or mutexes instead.
|
||||
* @see CH_USE_NESTED_LOCKS
|
||||
*/
|
||||
#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
|
||||
#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
|
||||
#define chSysUnlock() { \
|
||||
if (--currp->p_locks == 0) \
|
||||
port_unlock(); \
|
||||
}
|
||||
#endif /* CH_OPTIMIZE_SPEED */
|
||||
#else /* !CH_USE_NESTED_LOCKS */
|
||||
#define chSysUnlock() port_unlock()
|
||||
#endif /* !CH_USE_NESTED_LOCKS */
|
||||
|
||||
/**
|
||||
* @brief Enters the kernel lock mode from within an interrupt handler.
|
||||
* @note This API may do nothing on some architectures, it is required
|
||||
* because on ports that support preemptable interrupt handlers
|
||||
* it is required to raise the interrupt mask to the same level of
|
||||
* the system mutual exclusion zone.<br>
|
||||
* It is good practice to invoke this API before invoking any I-class
|
||||
* syscall from an interrupt handler.
|
||||
* @note This API must be invoked exclusively from interrupt handlers.
|
||||
*/
|
||||
#define chSysLockFromIsr() port_lock_from_isr()
|
||||
|
||||
/**
|
||||
* @brief Leaves the kernel lock mode from within an interrupt handler.
|
||||
*
|
||||
* @note This API may do nothing on some architectures, it is required
|
||||
* because on ports that support preemptable interrupt handlers
|
||||
* it is required to raise the interrupt mask to the same level of
|
||||
* the system mutual exclusion zone.<br>
|
||||
* It is good practice to invoke this API after invoking any I-class
|
||||
* syscall from an interrupt handler.
|
||||
* @note This API must be invoked exclusively from interrupt handlers.
|
||||
*/
|
||||
#define chSysUnlockFromIsr() port_unlock_from_isr()
|
||||
|
||||
/**
|
||||
* @brief IRQ handler enter code.
|
||||
* @note Usually IRQ handlers functions are also declared naked.
|
||||
* @note On some architectures this macro can be empty.
|
||||
*/
|
||||
#define CH_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE()
|
||||
|
||||
/**
|
||||
* @brief IRQ handler exit code.
|
||||
* @note Usually IRQ handlers function are also declared naked.
|
||||
* @note This macro usually performs the final reschedule by using
|
||||
* @p chSchRescRequiredI() and @p chSchDoRescheduleI().
|
||||
*/
|
||||
#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE()
|
||||
|
||||
/**
|
||||
* @brief Standard normal IRQ handler declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
|
||||
|
||||
/**
|
||||
* @brief Standard fast IRQ handler declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
* @note Not all architectures support fast interrupts.
|
||||
*/
|
||||
#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chSysInit(void);
|
||||
void chSysTimerHandlerI(void);
|
||||
#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
|
||||
void chSysLock(void);
|
||||
void chSysUnlock(void);
|
||||
#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CHSYS_H_ */
|
||||
|
||||
/** @} */
|
||||
337
ChibiOS_2.0.8/os/kernel/include/chthreads.h
Normal file
337
ChibiOS_2.0.8/os/kernel/include/chthreads.h
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chthreads.h
|
||||
* @brief Threads macros and structures.
|
||||
*
|
||||
* @addtogroup threads
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHTHREADS_H_
|
||||
#define _CHTHREADS_H_
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if CH_USE_DYNAMIC && !CH_USE_WAITEXIT
|
||||
#error "CH_USE_DYNAMIC requires CH_USE_WAITEXIT"
|
||||
#endif
|
||||
#if CH_USE_DYNAMIC && !CH_USE_HEAP && !CH_USE_MEMPOOLS
|
||||
#error "CH_USE_DYNAMIC requires CH_USE_HEAP and/or CH_USE_MEMPOOLS"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @extends ThreadsQueue
|
||||
*
|
||||
* @brief Structure representing a thread.
|
||||
* @note Not all the listed fields are always needed, by switching off some
|
||||
* not needed ChibiOS/RT subsystems it is possible to save RAM space
|
||||
* by shrinking the @p Thread structure.
|
||||
*/
|
||||
struct Thread {
|
||||
Thread *p_next; /**< @brief Next in the list/queue. */
|
||||
/* End of the fields shared with the ThreadsList structure. */
|
||||
Thread *p_prev; /**< @brief Previous in the queue. */
|
||||
/* End of the fields shared with the ThreadsQueue structure. */
|
||||
tprio_t p_prio; /**< @brief Thread priority. */
|
||||
struct context p_ctx; /**< @brief Processor context. */
|
||||
#if CH_USE_REGISTRY
|
||||
Thread *p_newer; /**< @brief Newer registry element. */
|
||||
Thread *p_older; /**< @brief Older registry element. */
|
||||
#endif
|
||||
/* End of the fields shared with the ReadyList structure. */
|
||||
/**
|
||||
* @brief Current thread state.
|
||||
*/
|
||||
tstate_t p_state;
|
||||
/**
|
||||
* @brief Various thread flags.
|
||||
*/
|
||||
tmode_t p_flags;
|
||||
#if CH_USE_DYNAMIC
|
||||
/**
|
||||
* @brief References to this thread.
|
||||
*/
|
||||
trefs_t p_refs;
|
||||
#endif
|
||||
#if CH_USE_NESTED_LOCKS
|
||||
/**
|
||||
* @brief Number of nested locks.
|
||||
*/
|
||||
cnt_t p_locks;
|
||||
#endif
|
||||
#if CH_DBG_THREADS_PROFILING
|
||||
/**
|
||||
* @brief Thread consumed time in ticks.
|
||||
* @note This field can overflow.
|
||||
*/
|
||||
volatile systime_t p_time;
|
||||
#endif
|
||||
/**
|
||||
* @brief State-specific fields.
|
||||
* @note All the fields declared in this union are only valid in the
|
||||
* specified state or condition and are thus volatile.
|
||||
*/
|
||||
union {
|
||||
/**
|
||||
* @brief Thread wakeup code.
|
||||
* @note This field contains the low level message sent to the thread
|
||||
* by the waking thread or interrupt handler. The value is valid
|
||||
* after exiting the @p chSchWakeupS() function.
|
||||
*/
|
||||
msg_t rdymsg;
|
||||
/**
|
||||
* @brief Thread exit code.
|
||||
* @note The thread termination code is stored in this field in order
|
||||
* to be retrieved by the thread performing a @p chThdWait() on
|
||||
* this thread.
|
||||
*/
|
||||
msg_t exitcode;
|
||||
/**
|
||||
* @brief Pointer to a generic "wait" object.
|
||||
* @note This field is used to get a generic pointer to a synchronization
|
||||
* object and is valid when the thread is in one of the wait
|
||||
* states.
|
||||
*/
|
||||
void *wtobjp;
|
||||
#if CH_USE_EVENTS
|
||||
/**
|
||||
* @brief Enabled events mask.
|
||||
* @note This field is only valied while the thread is in the
|
||||
* @p THD_STATE_WTOREVT or @p THD_STATE_WTANDEVT states.
|
||||
*/
|
||||
eventmask_t ewmask;
|
||||
#endif
|
||||
} p_u;
|
||||
#if CH_USE_WAITEXIT
|
||||
/**
|
||||
* @brief Termination waiting list.
|
||||
*/
|
||||
ThreadsList p_waiting;
|
||||
#endif
|
||||
#if CH_USE_MESSAGES
|
||||
/**
|
||||
* @brief Messages queue.
|
||||
*/
|
||||
ThreadsQueue p_msgqueue;
|
||||
/**
|
||||
* @brief Thread message.
|
||||
*/
|
||||
msg_t p_msg;
|
||||
#endif
|
||||
#if CH_USE_EVENTS
|
||||
/**
|
||||
* @brief Pending events mask.
|
||||
*/
|
||||
eventmask_t p_epending;
|
||||
#endif
|
||||
#if CH_USE_MUTEXES
|
||||
/**
|
||||
* @brief List of the mutexes owned by this thread.
|
||||
* @note The list is terminated by a @p NULL in this field.
|
||||
*/
|
||||
Mutex *p_mtxlist;
|
||||
/**
|
||||
* @brief Thread's own, non-inherited, priority.
|
||||
*/
|
||||
tprio_t p_realprio;
|
||||
#endif
|
||||
#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS
|
||||
/**
|
||||
* @brief Memory Pool where the thread workspace is returned.
|
||||
*/
|
||||
void *p_mpool;
|
||||
#endif
|
||||
/* Extra fields defined in chconf.h.*/
|
||||
THREAD_EXT_FIELDS
|
||||
};
|
||||
|
||||
/** @brief Thread state: Ready to run, waiting on the ready list.*/
|
||||
#define THD_STATE_READY 0
|
||||
/** @brief Thread state: Currently running.*/
|
||||
#define THD_STATE_CURRENT 1
|
||||
/** @brief Thread state: Thread created in suspended state.*/
|
||||
#define THD_STATE_SUSPENDED 2
|
||||
/** @brief Thread state: Waiting on a semaphore.*/
|
||||
#define THD_STATE_WTSEM 3
|
||||
/** @brief Thread state: Waiting on a mutex.*/
|
||||
#define THD_STATE_WTMTX 4
|
||||
/** @brief Thread state: Waiting in @p chCondWait().*/
|
||||
#define THD_STATE_WTCOND 5
|
||||
/** @brief Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil().*/
|
||||
#define THD_STATE_SLEEPING 6
|
||||
/** @brief Thread state: Waiting in @p chThdWait().*/
|
||||
#define THD_STATE_WTEXIT 7
|
||||
/** @brief Thread state: Waiting in @p chEvtWaitXXX().*/
|
||||
#define THD_STATE_WTOREVT 8
|
||||
/** @brief Thread state: Waiting in @p chEvtWaitAllTimeout().*/
|
||||
#define THD_STATE_WTANDEVT 9
|
||||
/** @brief Thread state: Waiting in @p chMsgSend().*/
|
||||
#define THD_STATE_SNDMSG 10
|
||||
/** @brief Thread state: Waiting in @p chMsgWait().*/
|
||||
#define THD_STATE_WTMSG 11
|
||||
/** @brief Thread state: After termination.*/
|
||||
#define THD_STATE_FINAL 12
|
||||
|
||||
/*
|
||||
* Various flags into the thread p_flags field.
|
||||
*/
|
||||
#define THD_MEM_MODE_MASK 3 /**< @brief Thread memory mode mask. */
|
||||
#define THD_MEM_MODE_STATIC 0 /**< @brief Thread memory mode: static. */
|
||||
#define THD_MEM_MODE_HEAP 1 /**< @brief Thread memory mode: heap. */
|
||||
#define THD_MEM_MODE_MEMPOOL 2 /**< @brief Thread memory mode: pool. */
|
||||
#define THD_TERMINATE 4 /**< @brief Termination requested. */
|
||||
|
||||
/** @brief Thread function.*/
|
||||
typedef msg_t (*tfunc_t)(void *);
|
||||
|
||||
/*
|
||||
* Threads APIs.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
Thread *init_thread(Thread *tp, tprio_t prio);
|
||||
Thread *chThdCreateI(void *wsp, size_t size,
|
||||
tprio_t prio, tfunc_t pf, void *arg);
|
||||
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(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,
|
||||
tfunc_t pf, void *arg);
|
||||
#endif
|
||||
tprio_t chThdSetPriority(tprio_t newprio);
|
||||
Thread *chThdResume(Thread *tp);
|
||||
void chThdTerminate(Thread *tp);
|
||||
void chThdSleep(systime_t time);
|
||||
void chThdSleepUntil(systime_t time);
|
||||
void chThdYield(void);
|
||||
void chThdExit(msg_t msg);
|
||||
#if CH_USE_DYNAMIC
|
||||
Thread *chThdAddRef(Thread *tp);
|
||||
void chThdRelease(Thread *tp);
|
||||
#endif
|
||||
#if CH_USE_WAITEXIT
|
||||
msg_t chThdWait(Thread *tp);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the current @p Thread.
|
||||
*/
|
||||
#define chThdSelf() currp
|
||||
|
||||
/**
|
||||
* @brief Returns the current thread priority.
|
||||
*/
|
||||
#define chThdGetPriority() (currp->p_prio)
|
||||
|
||||
/**
|
||||
* @brief Returns the pointer to the @p Thread local storage area, if any.
|
||||
*/
|
||||
#define chThdLS() (void *)(currp + 1)
|
||||
|
||||
/**
|
||||
* @brief Verifies if the specified thread is in the @p THD_STATE_FINAL state.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread
|
||||
* @retval TRUE thread terminated.
|
||||
* @retval FALSE thread not terminated.
|
||||
*/
|
||||
#define chThdTerminated(tp) ((tp)->p_state == THD_STATE_FINAL)
|
||||
|
||||
/**
|
||||
* @brief Verifies if the current thread has a termination request pending.
|
||||
*
|
||||
* @retval TRUE termination request pended.
|
||||
* @retval FALSE termination request not pended.
|
||||
*/
|
||||
#define chThdShouldTerminate() (currp->p_flags & THD_TERMINATE)
|
||||
|
||||
/**
|
||||
* @brief Resumes a thread created with @p chThdInit().
|
||||
*
|
||||
* @param[in] tp the pointer to the thread
|
||||
*/
|
||||
#define chThdResumeI(tp) chSchReadyI(tp)
|
||||
|
||||
/**
|
||||
* @brief Suspends the invoking thread for the specified time.
|
||||
*
|
||||
* @param[in] time the delay in system ticks, the special values are
|
||||
* handled as follow:
|
||||
* - @a TIME_INFINITE the thread enters an infinite sleep
|
||||
* state.
|
||||
* - @a TIME_IMMEDIATE this value is accepted but
|
||||
* interpreted as a normal time specification not as
|
||||
* an immediate timeout specification.
|
||||
* .
|
||||
*/
|
||||
#define chThdSleepS(time) chSchGoSleepTimeoutS(THD_STATE_SLEEPING, time)
|
||||
|
||||
/**
|
||||
* @brief Delays the invoking thread for the specified number of seconds.
|
||||
* @note The specified time is rounded up to a value allowed by the real
|
||||
* system clock.
|
||||
* @note The maximum specified value is implementation dependent.
|
||||
*
|
||||
* @param[in] sec the time in seconds
|
||||
*/
|
||||
#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec))
|
||||
|
||||
/**
|
||||
* @brief Delays the invoking thread for the specified number of
|
||||
* milliseconds.
|
||||
* @note The specified time is rounded up to a value allowed by the real
|
||||
* system clock.
|
||||
* @note The maximum specified value is implementation dependent.
|
||||
*
|
||||
* @param[in] msec the time in milliseconds
|
||||
*/
|
||||
#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec))
|
||||
|
||||
/**
|
||||
* @brief Delays the invoking thread for the specified number of
|
||||
* microseconds.
|
||||
* @note The specified time is rounded up to a value allowed by the real
|
||||
* system clock.
|
||||
* @note The maximum specified value is implementation dependent.
|
||||
*
|
||||
* @param[in] usec the time in microseconds
|
||||
*/
|
||||
#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec))
|
||||
|
||||
#endif /* _CHTHREADS_H_ */
|
||||
|
||||
/** @} */
|
||||
154
ChibiOS_2.0.8/os/kernel/include/chvt.h
Normal file
154
ChibiOS_2.0.8/os/kernel/include/chvt.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chvt.h
|
||||
* @brief Time macros and structures.
|
||||
*
|
||||
* @addtogroup time
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHVT_H_
|
||||
#define _CHVT_H_
|
||||
|
||||
/**
|
||||
* @brief Time conversion utility.
|
||||
* @details Converts from seconds to system ticks number.
|
||||
* @note The result is rounded upward to the next tick boundary.
|
||||
*/
|
||||
#define S2ST(sec) ((systime_t)((sec) * CH_FREQUENCY))
|
||||
|
||||
/**
|
||||
* @brief Time conversion utility.
|
||||
* @details Converts from milliseconds to system ticks number.
|
||||
* @note The result is rounded upward to the next tick boundary.
|
||||
*/
|
||||
#define MS2ST(msec) ((systime_t)(((((msec) - 1L) * CH_FREQUENCY) / 1000L) + 1L))
|
||||
|
||||
/**
|
||||
* @brief Time conversion utility.
|
||||
* @details Converts from microseconds to system ticks number.
|
||||
* @note The result is rounded upward to the next tick boundary.
|
||||
*/
|
||||
#define US2ST(usec) ((systime_t)(((((usec) - 1L) * CH_FREQUENCY) / 1000000L) + 1L))
|
||||
|
||||
/**
|
||||
* @brief Virtual Timer callback function.
|
||||
*/
|
||||
typedef void (*vtfunc_t)(void *);
|
||||
|
||||
/**
|
||||
* @brief Virtual Timer structure type.
|
||||
*/
|
||||
typedef struct VirtualTimer VirtualTimer;
|
||||
|
||||
/**
|
||||
* @extends DeltaList
|
||||
*
|
||||
* @brief Virtual Timer descriptor structure.
|
||||
*/
|
||||
struct VirtualTimer {
|
||||
VirtualTimer *vt_next; /**< @brief Next timer in the delta
|
||||
list. */
|
||||
VirtualTimer *vt_prev; /**< @brief Previous timer in the delta
|
||||
list. */
|
||||
systime_t vt_time; /**< @brief Time delta before timeout. */
|
||||
vtfunc_t vt_func; /**< @brief Timer callback function
|
||||
pointer. */
|
||||
void *vt_par; /**< @brief Timer callback function
|
||||
parameter. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Virtual timers list header.
|
||||
* @note The delta list is implemented as a double link bidirectional list
|
||||
* in order to make the unlink time constant, the reset of a virtual
|
||||
* timer is often used in the code.
|
||||
*/
|
||||
typedef struct {
|
||||
VirtualTimer *vt_next; /**< @brief Next timer in the delta
|
||||
list. */
|
||||
VirtualTimer *vt_prev; /**< @brief Last timer in the delta
|
||||
list. */
|
||||
systime_t vt_time; /**< @brief Must be initialized to -1. */
|
||||
volatile systime_t vt_systime; /**< @brief System Time counter. */
|
||||
} VTList;
|
||||
|
||||
extern VTList vtlist;
|
||||
|
||||
/**
|
||||
* @brief Virtual timers ticker.
|
||||
*/
|
||||
#define chVTDoTickI() { \
|
||||
vtlist.vt_systime++; \
|
||||
if (&vtlist != (VTList *)vtlist.vt_next) { \
|
||||
VirtualTimer *vtp; \
|
||||
\
|
||||
--vtlist.vt_next->vt_time; \
|
||||
while (!(vtp = vtlist.vt_next)->vt_time) { \
|
||||
vtfunc_t fn = vtp->vt_func; \
|
||||
vtp->vt_func = (vtfunc_t)NULL; \
|
||||
vtp->vt_next->vt_prev = (void *)&vtlist; \
|
||||
(&vtlist)->vt_next = vtp->vt_next; \
|
||||
fn(vtp->vt_par); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Virtual Timers APIs.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void vt_init(void);
|
||||
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par);
|
||||
void chVTResetI(VirtualTimer *vtp);
|
||||
bool_t chTimeIsWithin(systime_t start, systime_t end);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns TRUE if the speciified timer is armed.
|
||||
*/
|
||||
#define chVTIsArmedI(vtp) ((vtp)->vt_func != NULL)
|
||||
|
||||
/**
|
||||
* @brief Current system time.
|
||||
* @details Returns the number of system ticks since the @p chSysInit()
|
||||
* invocation.
|
||||
* @note The counter can reach its maximum and then restart from zero.
|
||||
* @note This function is designed to work with the @p chThdSleepUntil().
|
||||
*
|
||||
* @return The system time in ticks.r
|
||||
*/
|
||||
#define chTimeNow() (vtlist.vt_systime)
|
||||
|
||||
#endif /* _CHVT_H_ */
|
||||
|
||||
/** @} */
|
||||
172
ChibiOS_2.0.8/os/kernel/kernel.dox
Normal file
172
ChibiOS_2.0.8/os/kernel/kernel.dox
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup kernel Kernel
|
||||
* @details The kernel is the portable part of ChibiOS/RT, this section
|
||||
* documents the various kernel subsystems.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup kernel_info Version Numbers and Identification
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup config Configuration
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup types Types
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup base Base Kernel Services
|
||||
* @details Base kernel services, the base subsystems are always included in
|
||||
* the OS builds.
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup system System Management
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup scheduler Scheduler
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup threads Threads
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup time Time and Virtual Timers
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup synchronization Synchronization
|
||||
* @details Synchronization services.
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup semaphores Semaphores
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mutexes Mutexes
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup condvars Condition Variables
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup events Event Flags
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup messages Synchronous Messages
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mailboxes Mailboxes
|
||||
* @ingroup synchronization
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup memory Memory Management
|
||||
* @details Memory Management services.
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup memcore Core Memory Manager
|
||||
* @ingroup memory
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup heaps Heaps
|
||||
* @ingroup memory
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup pools Memory Pools
|
||||
* @ingroup memory
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup io_support I/O Support
|
||||
* @details I/O related services.
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup data_streams Data Streams
|
||||
* @ingroup io_support
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup io_channels I/O Channels
|
||||
* @ingroup io_support
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup io_queues I/O Queues
|
||||
* @ingroup io_support
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup registry Registry
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup debug Debug
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup core Port Templates
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup internals Internals
|
||||
* @ingroup kernel
|
||||
*/
|
||||
|
||||
22
ChibiOS_2.0.8/os/kernel/kernel.mk
Normal file
22
ChibiOS_2.0.8/os/kernel/kernel.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
# List of all the ChibiOS/RT kernel files, there is no need to remove the files
|
||||
# from this list, you can disable parts of the kernel by editing chconf.h.
|
||||
KERNSRC = ${CHIBIOS}/os/kernel/src/chsys.c \
|
||||
${CHIBIOS}/os/kernel/src/chdebug.c \
|
||||
${CHIBIOS}/os/kernel/src/chlists.c \
|
||||
${CHIBIOS}/os/kernel/src/chvt.c \
|
||||
${CHIBIOS}/os/kernel/src/chschd.c \
|
||||
${CHIBIOS}/os/kernel/src/chthreads.c \
|
||||
${CHIBIOS}/os/kernel/src/chregistry.c \
|
||||
${CHIBIOS}/os/kernel/src/chsem.c \
|
||||
${CHIBIOS}/os/kernel/src/chmtx.c \
|
||||
${CHIBIOS}/os/kernel/src/chcond.c \
|
||||
${CHIBIOS}/os/kernel/src/chevents.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
|
||||
|
||||
# Required include directories
|
||||
KERNINC = ${CHIBIOS}/os/kernel/include
|
||||
252
ChibiOS_2.0.8/os/kernel/src/chcond.c
Normal file
252
ChibiOS_2.0.8/os/kernel/src/chcond.c
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Leon Woestenberg.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chcond.c
|
||||
* @brief Condition Variables code.
|
||||
*
|
||||
* @addtogroup condvars Condition Variables
|
||||
* @details This module implements the Condition Variables mechanism. Condition
|
||||
* variables are an extensions to the Mutex subsystem and cannot
|
||||
* work alone.
|
||||
* <h2>Operation mode</h2>
|
||||
* The condition variable is a synchronization object meant to be
|
||||
* used inside a zone protected by a @p Mutex. Mutexes and CondVars
|
||||
* together can implement a Monitor construct.<br>
|
||||
* In order to use the Condition Variables APIs the @p CH_USE_CONDVARS
|
||||
* option must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_CONDVARS && CH_USE_MUTEXES
|
||||
|
||||
/**
|
||||
* @brief Initializes s @p CondVar structure.
|
||||
* @note This function can be invoked from within an interrupt handler even
|
||||
* if it is not an I-Class API because it does not touch any critical
|
||||
* kernel data structure.
|
||||
*
|
||||
* @param[out] cp pointer to a @p CondVar structure
|
||||
*/
|
||||
void chCondInit(CondVar *cp) {
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondInit");
|
||||
|
||||
queue_init(&cp->c_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals one thread that is waiting on the condition variable.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
*/
|
||||
void chCondSignal(CondVar *cp) {
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondSignal");
|
||||
|
||||
chSysLock();
|
||||
if (notempty(&cp->c_queue))
|
||||
chSchWakeupS(fifo_remove(&cp->c_queue), RDY_OK);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals one thread that is waiting on the condition variable.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
*/
|
||||
void chCondSignalI(CondVar *cp) {
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondSignalI");
|
||||
|
||||
if (notempty(&cp->c_queue))
|
||||
chSchReadyI(fifo_remove(&cp->c_queue))->p_u.rdymsg = RDY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals all threads that are waiting on the condition variable.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
*/
|
||||
void chCondBroadcast(CondVar *cp) {
|
||||
|
||||
chSysLock();
|
||||
chCondBroadcastI(cp);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals all threads that are waiting on the condition variable.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
*/
|
||||
void chCondBroadcastI(CondVar *cp) {
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondBroadcastI");
|
||||
|
||||
/* Empties the condition variable queue and inserts all the Threads into the
|
||||
ready list in FIFO order. The wakeup message is set to @p RDY_RESET in
|
||||
order to make a chCondBroadcast() detectable from a chCondSignal().*/
|
||||
while (cp->c_queue.p_next != (void *)&cp->c_queue)
|
||||
chSchReadyI(fifo_remove(&cp->c_queue))->p_u.rdymsg = RDY_RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits on the condition variable releasing the mutex lock.
|
||||
* @details Releases the currently owned mutex, waits on the condition
|
||||
* variable, and finally acquires the mutex again. All the sequence
|
||||
* is performed atomically.
|
||||
* @note The invoking thread <b>must</b> have at least one owned mutex on
|
||||
* entry.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
* @return The wakep mode.
|
||||
* @retval RDY_OK if the condvar was signaled using @p chCondSignal().
|
||||
* @retval RDY_RESET if the condvar was signaled using @p chCondBroadcast().
|
||||
*/
|
||||
msg_t chCondWait(CondVar *cp) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
msg = chCondWaitS(cp);
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits on the condition variable releasing the mutex lock.
|
||||
* @details Releases the currently owned mutex, waits on the condition
|
||||
* variable, and finally acquires the mutex again. All the sequence
|
||||
* is performed atomically.
|
||||
* @note The invoking thread <b>must</b> have at least one owned mutex on
|
||||
* entry.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
* @return The wakep mode.
|
||||
* @retval RDY_OK if the condvar was signaled using @p chCondSignal().
|
||||
* @retval RDY_RESET if the condvar was signaled using @p chCondBroadcast().
|
||||
*/
|
||||
msg_t chCondWaitS(CondVar *cp) {
|
||||
Thread *ctp = currp;
|
||||
Mutex *mp;
|
||||
msg_t msg;
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondWaitS");
|
||||
chDbgAssert(ctp->p_mtxlist != NULL,
|
||||
"chCondWaitS(), #1",
|
||||
"not owning a mutex");
|
||||
|
||||
mp = chMtxUnlockS();
|
||||
ctp->p_u.wtobjp = cp;
|
||||
prio_insert(ctp, &cp->c_queue);
|
||||
chSchGoSleepS(THD_STATE_WTCOND);
|
||||
msg = ctp->p_u.rdymsg;
|
||||
chMtxLockS(mp);
|
||||
return msg;
|
||||
}
|
||||
|
||||
#if CH_USE_CONDVARS_TIMEOUT
|
||||
/**
|
||||
* @brief Waits on the condition variable releasing the mutex lock.
|
||||
* @details Releases the currently owned mutex, waits on the condition
|
||||
* variable, and finally acquires the mutex again. All the sequence
|
||||
* is performed atomically.
|
||||
* @note The invoking thread <b>must</b> have at least one owned mutex on
|
||||
* entry.
|
||||
* @note Exiting the function because a timeout does not re-acquire the
|
||||
* mutex, the mutex ownership is lost.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the special value @p TIME_INFINITE is allowed.
|
||||
* It is not possible to specify zero @p TIME_IMMEDIATE
|
||||
* as timeout specification because it would make no sense
|
||||
* in this function.
|
||||
* @return The wakep mode.
|
||||
* @retval RDY_OK if the condvar was signaled using @p chCondSignal().
|
||||
* @retval RDY_RESET if the condvar was signaled using @p chCondBroadcast().
|
||||
* @retval RDY_TIMEOUT if the condvar was not signaled @p within the specified
|
||||
* timeout.
|
||||
*/
|
||||
msg_t chCondWaitTimeout(CondVar *cp, systime_t time) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
msg = chCondWaitTimeoutS(cp, time);
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits on the condition variable releasing the mutex lock.
|
||||
* @details Releases the currently owned mutex, waits on the condition
|
||||
* variable, and finally acquires the mutex again. All the sequence
|
||||
* is performed atomically.
|
||||
* @note The invoking thread <b>must</b> have at least one owned mutex on
|
||||
* entry.
|
||||
* @note Exiting the function because a timeout does not re-acquire the
|
||||
* mutex, the mutex ownership is lost.
|
||||
*
|
||||
* @param[in] cp pointer to the @p CondVar structure
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the special value @p TIME_INFINITE is allowed.
|
||||
* It is not possible to specify zero @p TIME_IMMEDIATE
|
||||
* as timeout specification because it would make no sense
|
||||
* in this function.
|
||||
* @return The wakep mode.
|
||||
* @retval RDY_OK if the condvar was signaled using @p chCondSignal().
|
||||
* @retval RDY_RESET if the condvar was signaled using @p chCondBroadcast().
|
||||
* @retval RDY_TIMEOUT if the condvar was not signaled within the specified
|
||||
* timeout.
|
||||
*/
|
||||
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
|
||||
Mutex *mp;
|
||||
msg_t msg;
|
||||
|
||||
chDbgCheck(cp != NULL, "chCondWaitTimeoutS");
|
||||
chDbgAssert(currp->p_mtxlist != NULL,
|
||||
"chCondWaitTimeoutS(), #1",
|
||||
"not owning a mutex");
|
||||
|
||||
mp = chMtxUnlockS();
|
||||
currp->p_u.wtobjp = cp;
|
||||
prio_insert(currp, &cp->c_queue);
|
||||
msg = chSchGoSleepTimeoutS(THD_STATE_WTCOND, time);
|
||||
if (msg != RDY_TIMEOUT)
|
||||
chMtxLockS(mp);
|
||||
return msg;
|
||||
}
|
||||
#endif /* CH_USE_CONDVARS_TIMEOUT */
|
||||
|
||||
#endif /* CH_USE_CONDVARS && CH_USE_MUTEXES */
|
||||
|
||||
/** @} */
|
||||
94
ChibiOS_2.0.8/os/kernel/src/chdebug.c
Normal file
94
ChibiOS_2.0.8/os/kernel/src/chdebug.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chdebug.c
|
||||
* @brief ChibiOS/RT Debug code.
|
||||
*
|
||||
* @addtogroup debug
|
||||
* @details Debug APIs and services:
|
||||
* - Trace buffer.
|
||||
* - Parameters check.
|
||||
* - Kernel assertions.
|
||||
* .
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_DBG_ENABLE_TRACE
|
||||
/**
|
||||
* @brief Public trace buffer.
|
||||
*/
|
||||
TraceBuffer trace_buffer;
|
||||
|
||||
/**
|
||||
* @brief Trace circular buffer subsystem initialization.
|
||||
*/
|
||||
void trace_init(void) {
|
||||
|
||||
trace_buffer.tb_size = TRACE_BUFFER_SIZE;
|
||||
trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts in the circular debug trace buffer a context switch record.
|
||||
*
|
||||
* @param[in] otp the thread being switched out
|
||||
*/
|
||||
void chDbgTrace(Thread *otp) {
|
||||
|
||||
trace_buffer.tb_ptr->cse_wtobjp = otp->p_u.wtobjp;
|
||||
trace_buffer.tb_ptr->cse_time = chTimeNow();
|
||||
trace_buffer.tb_ptr->cse_state = otp->p_state;
|
||||
trace_buffer.tb_ptr->cse_tid = (unsigned)currp >> 6;
|
||||
if (++trace_buffer.tb_ptr >= &trace_buffer.tb_buffer[TRACE_BUFFER_SIZE])
|
||||
trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
|
||||
}
|
||||
#endif /* CH_DBG_ENABLE_TRACE */
|
||||
|
||||
#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
|
||||
/**
|
||||
* @brief Pointer to the panic message.
|
||||
* @details This pointer is meant to be accessed through the debugger, it is
|
||||
* written once and then the system is halted. This variable can be
|
||||
* set to @p NULL if the halt is caused by a stack overflow.
|
||||
*/
|
||||
char *panic_msg;
|
||||
|
||||
/**
|
||||
* @brief Prints a panic message on the console and then halts the system.
|
||||
*
|
||||
* @param[in] msg the pointer to the panic message string
|
||||
*/
|
||||
void chDbgPanic(char *msg) {
|
||||
|
||||
panic_msg = msg;
|
||||
chSysHalt();
|
||||
}
|
||||
#endif /* CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK */
|
||||
|
||||
/** @} */
|
||||
449
ChibiOS_2.0.8/os/kernel/src/chevents.c
Normal file
449
ChibiOS_2.0.8/os/kernel/src/chevents.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chevents.c
|
||||
* @brief Events code.
|
||||
*
|
||||
* @addtogroup events
|
||||
* @details Event Flags, Event Sources and Event Listeners.
|
||||
* <h2>Operation mode</h2>
|
||||
* Each thread has a mask of pending event flags inside its @p Thread
|
||||
* structure.
|
||||
* Operations defined for event flags:
|
||||
* - <b>Wait</b>, the invoking thread goes to sleep until a certain
|
||||
* AND/OR combination of event flags becomes pending.
|
||||
* - <b>Clear</b>, a mask of event flags is cleared from the pending
|
||||
* events mask, the cleared event flags mask is returned (only the
|
||||
* flags that were actually pending and then cleared).
|
||||
* - <b>Signal</b>, an event mask is directly ORed to the mask of the
|
||||
* signaled thread.
|
||||
* - <b>Broadcast</b>, each thread registered on an Event Source is
|
||||
* signaled with the event flags specified in its Event Listener.
|
||||
* - <b>Dispatch</b>, an events mask is scanned and for each bit set
|
||||
* to one an associated handler function is invoked. Bit masks are
|
||||
* scanned from bit zero upward.
|
||||
* .
|
||||
* An Event Source is a special object that can be "broadcasted" by
|
||||
* a thread or an interrupt service routine. Broadcasting an Event
|
||||
* Source has the effect that all the threads registered on the
|
||||
* Event Source will be signaled with an events mask.<br>
|
||||
* An unlimited number of Event Sources can exists in a system and
|
||||
* each thread can be listening on an unlimited number of
|
||||
* them.<br><br>
|
||||
* In order to use the Events APIs the @p CH_USE_EVENTS option must be
|
||||
* enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
/**
|
||||
* @brief Registers an Event Listener on an Event Source.
|
||||
* @note Multiple Event Listeners can specify the same bits to be pended.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
* @param[in] elp pointer to the @p EventListener structure
|
||||
* @param[in] mask the mask of event flags to be pended to the thread when
|
||||
* the event source is broadcasted
|
||||
*/
|
||||
void chEvtRegisterMask(EventSource *esp, EventListener *elp, eventmask_t mask) {
|
||||
|
||||
chDbgCheck((esp != NULL) && (elp != NULL), "chEvtRegisterMask");
|
||||
|
||||
chSysLock();
|
||||
elp->el_next = esp->es_next;
|
||||
esp->es_next = elp;
|
||||
elp->el_listener = currp;
|
||||
elp->el_mask = mask;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregisters an Event Listener from its Event Source.
|
||||
* @note If the event listener is not registered on the specified event
|
||||
* source then the function does nothing.
|
||||
* @note For optimal performance it is better to perform the unregister
|
||||
* operations in inverse order of the register operations (elements
|
||||
* are found on top of the list).
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
* @param[in] elp pointer to the @p EventListener structure
|
||||
*/
|
||||
void chEvtUnregister(EventSource *esp, EventListener *elp) {
|
||||
EventListener *p;
|
||||
|
||||
chDbgCheck((esp != NULL) && (elp != NULL), "chEvtUnregister");
|
||||
|
||||
p = (EventListener *)esp;
|
||||
chSysLock();
|
||||
while (p->el_next != (EventListener *)esp) {
|
||||
if (p->el_next == elp) {
|
||||
p->el_next = elp->el_next;
|
||||
break;
|
||||
}
|
||||
p = p->el_next;
|
||||
}
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the pending events specified in the mask.
|
||||
*
|
||||
* @param[in] mask the events to be cleared
|
||||
* @return The pending events that were cleared.
|
||||
*/
|
||||
eventmask_t chEvtClear(eventmask_t mask) {
|
||||
eventmask_t m;
|
||||
|
||||
chSysLock();
|
||||
|
||||
m = currp->p_epending & mask;
|
||||
currp->p_epending &= ~mask;
|
||||
|
||||
chSysUnlock();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pends a set of event flags on the current thread, this is @b much
|
||||
* faster than using @p chEvtBroadcast() or @p chEvtSignal().
|
||||
*
|
||||
* @param[in] mask the events to be pended
|
||||
* @return The current pending events mask.
|
||||
*/
|
||||
eventmask_t chEvtPend(eventmask_t mask) {
|
||||
|
||||
chSysLock();
|
||||
|
||||
mask = (currp->p_epending |= mask);
|
||||
|
||||
chSysUnlock();
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pends a set of event flags on the specified @p Thread.
|
||||
*
|
||||
* @param[in] tp the thread to be signaled
|
||||
* @param[in] mask the event flags set to be pended
|
||||
*/
|
||||
void chEvtSignal(Thread *tp, eventmask_t mask) {
|
||||
|
||||
chDbgCheck(tp != NULL, "chEvtSignal");
|
||||
|
||||
chSysLock();
|
||||
chEvtSignalI(tp, mask);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pends a set of event flags on the specified @p Thread.
|
||||
*
|
||||
* @param[in] tp the thread to be signaled
|
||||
* @param[in] mask the event flags set to be pended
|
||||
*/
|
||||
void chEvtSignalI(Thread *tp, eventmask_t mask) {
|
||||
|
||||
chDbgCheck(tp != NULL, "chEvtSignalI");
|
||||
|
||||
tp->p_epending |= mask;
|
||||
/* Test on the AND/OR conditions wait states.*/
|
||||
if (((tp->p_state == THD_STATE_WTOREVT) &&
|
||||
((tp->p_epending & tp->p_u.ewmask) != 0)) ||
|
||||
((tp->p_state == THD_STATE_WTANDEVT) &&
|
||||
((tp->p_epending & tp->p_u.ewmask) == tp->p_u.ewmask)))
|
||||
chSchReadyI(tp)->p_u.rdymsg = RDY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals all the Event Listeners registered on the specified Event
|
||||
* Source.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
*/
|
||||
void chEvtBroadcast(EventSource *esp) {
|
||||
|
||||
chSysLock();
|
||||
chEvtBroadcastI(esp);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals all the Event Listeners registered on the specified Event
|
||||
* Source.
|
||||
*
|
||||
* @param[in] esp pointer to the @p EventSource structure
|
||||
*/
|
||||
void chEvtBroadcastI(EventSource *esp) {
|
||||
EventListener *elp;
|
||||
|
||||
chDbgCheck(esp != NULL, "chEvtBroadcastI");
|
||||
|
||||
elp = esp->es_next;
|
||||
while (elp != (EventListener *)esp) {
|
||||
chEvtSignalI(elp->el_listener, elp->el_mask);
|
||||
elp = elp->el_next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invokes the event handlers associated to an event flags mask.
|
||||
*
|
||||
* @param[in] mask mask of the events to be dispatched
|
||||
* @param[in] handlers an array of @p evhandler_t. The array must have size
|
||||
* equal to the number of bits in eventmask_t.
|
||||
*/
|
||||
void chEvtDispatch(const evhandler_t *handlers, eventmask_t mask) {
|
||||
eventid_t eid;
|
||||
|
||||
chDbgCheck(handlers != NULL, "chEvtDispatch");
|
||||
|
||||
eid = 0;
|
||||
while (mask) {
|
||||
if (mask & EVENT_MASK(eid)) {
|
||||
chDbgAssert(handlers[eid] != NULL,
|
||||
"chEvtDispatch(), #1",
|
||||
"null handler");
|
||||
mask &= ~EVENT_MASK(eid);
|
||||
handlers[eid](eid);
|
||||
}
|
||||
eid++;
|
||||
}
|
||||
}
|
||||
|
||||
#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waits for exactly one of the specified events.
|
||||
* @details The function waits for one event among those specified in
|
||||
* @p mask to become pending then the event is cleared and returned.
|
||||
* @note One and only one event is served in the function, the one with the
|
||||
* lowest event id. The function is meant to be invoked into a loop in
|
||||
* order to serve all the pending events.<br>
|
||||
* This means that Event Listeners with a lower event identifier have
|
||||
* an higher priority.
|
||||
*
|
||||
* @param[in] mask mask of the events that the function should wait for,
|
||||
* @p ALL_EVENTS enables all the events
|
||||
* @return The mask of the lowest id served and cleared event.
|
||||
*/
|
||||
eventmask_t chEvtWaitOne(eventmask_t mask) {
|
||||
Thread *ctp = currp;
|
||||
eventmask_t m;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((m = (ctp->p_epending & mask)) == 0) {
|
||||
ctp->p_u.ewmask = mask;
|
||||
chSchGoSleepS(THD_STATE_WTOREVT);
|
||||
m = ctp->p_epending & mask;
|
||||
}
|
||||
m &= -m;
|
||||
ctp->p_epending &= ~m;
|
||||
|
||||
chSysUnlock();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for any of the specified events.
|
||||
* @details The function waits for any event among those specified in
|
||||
* @p mask to become pending then the events are cleared and returned.
|
||||
*
|
||||
* @param[in] mask mask of the events that the function should wait for,
|
||||
* @p ALL_EVENTS enables all the events
|
||||
* @return The mask of the served and cleared events.
|
||||
*/
|
||||
eventmask_t chEvtWaitAny(eventmask_t mask) {
|
||||
Thread *ctp = currp;
|
||||
eventmask_t m;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((m = (ctp->p_epending & mask)) == 0) {
|
||||
ctp->p_u.ewmask = mask;
|
||||
chSchGoSleepS(THD_STATE_WTOREVT);
|
||||
m = ctp->p_epending & mask;
|
||||
}
|
||||
ctp->p_epending &= ~m;
|
||||
|
||||
chSysUnlock();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for all the specified events.
|
||||
* @details The function waits for all the events specified in @p mask to
|
||||
* become pending then the events are cleared and returned.
|
||||
*
|
||||
* @param[in] mask mask of the event ids that the function should wait for
|
||||
* @return The mask of the served and cleared events.
|
||||
*/
|
||||
eventmask_t chEvtWaitAll(eventmask_t mask) {
|
||||
Thread *ctp = currp;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((ctp->p_epending & mask) != mask) {
|
||||
ctp->p_u.ewmask = mask;
|
||||
chSchGoSleepS(THD_STATE_WTANDEVT);
|
||||
}
|
||||
ctp->p_epending &= ~mask;
|
||||
|
||||
chSysUnlock();
|
||||
return mask;
|
||||
}
|
||||
#endif /* CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT */
|
||||
|
||||
#if CH_USE_EVENTS_TIMEOUT
|
||||
/**
|
||||
* @brief Waits for exactly one of the specified events.
|
||||
* @details The function waits for one event among those specified in
|
||||
* @p mask to become pending then the event is cleared and returned.
|
||||
* @note One and only one event is served in the function, the one with the
|
||||
* lowest event id. The function is meant to be invoked into a loop in
|
||||
* order to serve all the pending events.<br>
|
||||
* This means that Event Listeners with a lower event identifier have
|
||||
* an higher priority.
|
||||
*
|
||||
* @param[in] mask mask of the events that the function should wait for,
|
||||
* @p ALL_EVENTS enables all the events
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The mask of the lowest id served and cleared event.
|
||||
* @retval 0 if the specified timeout expired.
|
||||
*/
|
||||
eventmask_t chEvtWaitOneTimeout(eventmask_t mask, systime_t time) {
|
||||
Thread *ctp = currp;
|
||||
eventmask_t m;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((m = (ctp->p_epending & mask)) == 0) {
|
||||
if (TIME_IMMEDIATE == time) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
ctp->p_u.ewmask = mask;
|
||||
if (chSchGoSleepTimeoutS(THD_STATE_WTOREVT, time) < RDY_OK) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
m = ctp->p_epending & mask;
|
||||
}
|
||||
m &= -m;
|
||||
ctp->p_epending &= ~m;
|
||||
|
||||
chSysUnlock();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for any of the specified events.
|
||||
* @details The function waits for any event among those specified in
|
||||
* @p mask to become pending then the events are cleared and
|
||||
* returned.
|
||||
*
|
||||
* @param[in] mask mask of the events that the function should wait for,
|
||||
* @p ALL_EVENTS enables all the events
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The mask of the served and cleared events.
|
||||
* @retval 0 if the specified timeout expired.
|
||||
*/
|
||||
eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t time) {
|
||||
Thread *ctp = currp;
|
||||
eventmask_t m;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((m = (ctp->p_epending & mask)) == 0) {
|
||||
if (TIME_IMMEDIATE == time) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
ctp->p_u.ewmask = mask;
|
||||
if (chSchGoSleepTimeoutS(THD_STATE_WTOREVT, time) < RDY_OK) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
m = ctp->p_epending & mask;
|
||||
}
|
||||
ctp->p_epending &= ~m;
|
||||
|
||||
chSysUnlock();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for all the specified events.
|
||||
* @details The function waits for all the events specified in @p mask to
|
||||
* become pending then the events are cleared and returned.
|
||||
*
|
||||
* @param[in] mask mask of the event ids that the function should wait for
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The mask of the served and cleared events.
|
||||
* @retval 0 if the specified timeout expired.
|
||||
*/
|
||||
eventmask_t chEvtWaitAllTimeout(eventmask_t mask, systime_t time) {
|
||||
Thread *ctp = currp;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if ((ctp->p_epending & mask) != mask) {
|
||||
if (TIME_IMMEDIATE == time) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
ctp->p_u.ewmask = mask;
|
||||
if (chSchGoSleepTimeoutS(THD_STATE_WTANDEVT, time) < RDY_OK) {
|
||||
chSysUnlock();
|
||||
return (eventmask_t)0;
|
||||
}
|
||||
}
|
||||
ctp->p_epending &= ~mask;
|
||||
|
||||
chSysUnlock();
|
||||
return mask;
|
||||
}
|
||||
#endif /* CH_USE_EVENTS_TIMEOUT */
|
||||
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
/** @} */
|
||||
313
ChibiOS_2.0.8/os/kernel/src/chheap.c
Normal file
313
ChibiOS_2.0.8/os/kernel/src/chheap.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chheap.c
|
||||
* @brief Heaps code.
|
||||
*
|
||||
* @addtogroup heaps
|
||||
* @details Heap Allocator related APIs.
|
||||
* <h2>Operation mode</h2>
|
||||
* The heap allocator implements a first-fit strategy and its APIs
|
||||
* are functionally equivalent to the usual @p malloc() and @p free()
|
||||
* library functions. The main difference is that the OS heap APIs
|
||||
* are guaranteed to be thread safe.<br>
|
||||
* By enabling the @p CH_USE_MALLOC_HEAP option the heap manager
|
||||
* will use the runtime-provided @p malloc() and @p free() as
|
||||
* backend for the heap APIs instead of the system provided
|
||||
* allocator.<br>
|
||||
* In order to use the heap APIs the @p CH_USE_HEAP option must
|
||||
* be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_HEAP
|
||||
|
||||
#if !CH_USE_MALLOC_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
|
||||
|
||||
/**
|
||||
* @brief Default heap descriptor.
|
||||
*/
|
||||
static MemoryHeap default_heap;
|
||||
|
||||
/**
|
||||
* @brief Initializes the default heap.
|
||||
* @note Internal use only.
|
||||
*/
|
||||
void heap_init(void) {
|
||||
default_heap.h_provider = chCoreAlloc;
|
||||
default_heap.h_free.h.u.next = (union heap_header *)NULL;
|
||||
default_heap.h_free.h.size = 0;
|
||||
#if CH_USE_MUTEXES
|
||||
chMtxInit(&default_heap.h_mtx);
|
||||
#else
|
||||
chSemInit(&default_heap.h_sem, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes a memory heap from a static memory area.
|
||||
* @note Both the heap buffer base and the heap size must be aligned to
|
||||
* the @p align_t type size.
|
||||
*
|
||||
* @param[out] heapp pointer to the memory heap descriptor to be initialized
|
||||
* @param[in] buf heap buffer base
|
||||
* @param[in] size heap size
|
||||
*/
|
||||
void chHeapInit(MemoryHeap *heapp, void *buf, size_t size) {
|
||||
union heap_header *hp;
|
||||
|
||||
chDbgCheck(MEM_IS_ALIGNED(buf) && MEM_IS_ALIGNED(size), "chHeapInit");
|
||||
|
||||
heapp->h_provider = (memgetfunc_t)NULL;
|
||||
heapp->h_free.h.u.next = hp = buf;
|
||||
heapp->h_free.h.size = 0;
|
||||
hp->h.u.next = NULL;
|
||||
hp->h.size = size - sizeof(union heap_header);
|
||||
#if CH_USE_MUTEXES
|
||||
chMtxInit(&heapp->h_mtx);
|
||||
#else
|
||||
chSemInit(&heapp->h_sem, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 (@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(MemoryHeap *heapp, size_t size) {
|
||||
union heap_header *qp, *hp, *fp;
|
||||
|
||||
if (heapp == NULL)
|
||||
heapp = &default_heap;
|
||||
|
||||
size = MEM_ALIGN_SIZE(size);
|
||||
qp = &heapp->h_free;
|
||||
H_LOCK(heapp);
|
||||
|
||||
while (qp->h.u.next != NULL) {
|
||||
hp = qp->h.u.next;
|
||||
if (hp->h.size >= size) {
|
||||
if (hp->h.size < size + sizeof(union 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.u.next = hp->h.u.next;
|
||||
}
|
||||
else {
|
||||
/* Block bigger enough, must split it.*/
|
||||
fp = (void *)((uint8_t *)(hp) + sizeof(union heap_header) + size);
|
||||
fp->h.u.next = hp->h.u.next;
|
||||
fp->h.size = hp->h.size - sizeof(union heap_header) - size;
|
||||
qp->h.u.next = fp;
|
||||
hp->h.size = size;
|
||||
}
|
||||
hp->h.u.heap = heapp;
|
||||
|
||||
H_UNLOCK(heapp);
|
||||
return (void *)(hp + 1);
|
||||
}
|
||||
qp = hp;
|
||||
}
|
||||
|
||||
H_UNLOCK(heapp);
|
||||
|
||||
/* More memory is required, tries to get it from the associated provider
|
||||
else fails.*/
|
||||
if (heapp->h_provider) {
|
||||
hp = heapp->h_provider(size + sizeof(union heap_header));
|
||||
if (hp != NULL) {
|
||||
hp->h.u.heap = heapp;
|
||||
hp->h.size = size;
|
||||
hp++;
|
||||
return (void *)hp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define LIMIT(p) (union heap_header *)((uint8_t *)(p) + \
|
||||
sizeof(union heap_header) + \
|
||||
(p)->h.size)
|
||||
|
||||
/**
|
||||
* @brief Frees a previously allocated memory block.
|
||||
*
|
||||
* @param[in] p pointer to the memory block to be freed
|
||||
*/
|
||||
void chHeapFree(void *p) {
|
||||
union heap_header *qp, *hp;
|
||||
MemoryHeap *heapp;
|
||||
|
||||
chDbgCheck(p != NULL, "chHeapFree");
|
||||
|
||||
hp = (union heap_header *)p - 1;
|
||||
heapp = hp->h.u.heap;
|
||||
qp = &heapp->h_free;
|
||||
H_LOCK(heapp);
|
||||
|
||||
while (TRUE) {
|
||||
chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
|
||||
"chHeapFree(), #1",
|
||||
"within free block");
|
||||
|
||||
if (((qp == &heapp->h_free) || (hp > qp)) &&
|
||||
((qp->h.u.next == NULL) || (hp < qp->h.u.next))) {
|
||||
/* Insertion after qp.*/
|
||||
hp->h.u.next = qp->h.u.next;
|
||||
qp->h.u.next = hp;
|
||||
/* Verifies if the newly inserted block should be merged.*/
|
||||
if (LIMIT(hp) == hp->h.u.next) {
|
||||
/* Merge with the next block.*/
|
||||
hp->h.size += hp->h.u.next->h.size + sizeof(union heap_header);
|
||||
hp->h.u.next = hp->h.u.next->h.u.next;
|
||||
}
|
||||
if ((LIMIT(qp) == hp)) {
|
||||
/* Merge with the previous block.*/
|
||||
qp->h.size += hp->h.size + sizeof(union heap_header);
|
||||
qp->h.u.next = hp->h.u.next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
qp = qp->h.u.next;
|
||||
}
|
||||
|
||||
H_UNLOCK(heapp);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reports the heap status.
|
||||
* @note This function is meant to be used in the test suite, it should
|
||||
* not be really useful for the application code.
|
||||
* @note This function is not implemented when the @p CH_USE_MALLOC_HEAP
|
||||
* configuration option is used (it always returns zero).
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
|
||||
union heap_header *qp;
|
||||
size_t n, sz;
|
||||
|
||||
if (heapp == NULL)
|
||||
heapp = &default_heap;
|
||||
|
||||
H_LOCK(heapp);
|
||||
|
||||
sz = 0;
|
||||
for (n = 0, qp = &heapp->h_free; qp->h.u.next; n++, qp = qp->h.u.next)
|
||||
sz += qp->h.u.next->h.size;
|
||||
if (sizep)
|
||||
*sizep = sz;
|
||||
|
||||
H_UNLOCK(heapp);
|
||||
return n;
|
||||
}
|
||||
|
||||
#else /* CH_USE_MALLOC_HEAP */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
#define H_LOCK() chMtxLock(&hmtx)
|
||||
#define H_UNLOCK() chMtxUnlock()
|
||||
static Mutex hmtx;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
#define H_LOCK() chSemWait(&hsem)
|
||||
#define H_UNLOCK() chSemSignal(&hsem)
|
||||
static Semaphore hsem;
|
||||
#endif
|
||||
|
||||
void heap_init(void) {
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
chMtxInit(&hmtx);
|
||||
#else
|
||||
chSemInit(&hsem, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
|
||||
void *p;
|
||||
|
||||
chDbgCheck(heapp == NULL, "chHeapAlloc");
|
||||
|
||||
H_LOCK();
|
||||
p = malloc(size);
|
||||
H_UNLOCK();
|
||||
return p;
|
||||
}
|
||||
|
||||
void chHeapFree(void *p) {
|
||||
|
||||
chDbgCheck(p != NULL, "chHeapFree");
|
||||
|
||||
H_LOCK();
|
||||
free(p);
|
||||
H_UNLOCK();
|
||||
}
|
||||
|
||||
size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
|
||||
|
||||
chDbgCheck(heapp == NULL, "chHeapStatus");
|
||||
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CH_USE_MALLOC_HEAP */
|
||||
|
||||
#endif /* CH_USE_HEAP */
|
||||
|
||||
/** @} */
|
||||
155
ChibiOS_2.0.8/os/kernel/src/chlists.c
Normal file
155
ChibiOS_2.0.8/os/kernel/src/chlists.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chlists.c
|
||||
* @brief Thread queues/lists code.
|
||||
*
|
||||
* @addtogroup internals
|
||||
* @details All the functions present in this module, while public, are not
|
||||
* an OS API and should not be directly used in the user applications
|
||||
* code.
|
||||
* @{
|
||||
*/
|
||||
#include "ch.h"
|
||||
|
||||
#if !CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Inserts a thread into a priority ordered queue.
|
||||
* @note The insertion is done by scanning the list from the highest priority
|
||||
* toward the lowest.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread to be inserted in the list
|
||||
* @param[in] tqp the pointer to the threads list header
|
||||
*/
|
||||
void prio_insert(Thread *tp, ThreadsQueue *tqp) {
|
||||
|
||||
/* cp iterates over the queue.*/
|
||||
Thread *cp = (Thread *)tqp;
|
||||
do {
|
||||
/* Iterate to next thread in queue.*/
|
||||
cp = cp->p_next;
|
||||
/* Not end of queue? and cp has equal or higher priority than tp?.*/
|
||||
} while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
|
||||
/* Insertion on p_prev.*/
|
||||
tp->p_next = cp;
|
||||
tp->p_prev = cp->p_prev;
|
||||
tp->p_prev->p_next = cp->p_prev = tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a Thread into a queue.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread to be inserted in the list
|
||||
* @param[in] tqp the pointer to the threads list header
|
||||
*/
|
||||
void queue_insert(Thread *tp, ThreadsQueue *tqp) {
|
||||
|
||||
tp->p_next = (Thread *)tqp;
|
||||
tp->p_prev = tqp->p_prev;
|
||||
tp->p_prev->p_next = tqp->p_prev = tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the first-out Thread from a queue and returns it.
|
||||
* @note If the queue is priority ordered then this function returns the
|
||||
* thread with the highest priority.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tqp the pointer to the threads list header
|
||||
* @return The removed thread pointer.
|
||||
*/
|
||||
Thread *fifo_remove(ThreadsQueue *tqp) {
|
||||
Thread *tp = tqp->p_next;
|
||||
|
||||
(tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the last-out Thread from a queue and returns it.
|
||||
* @note If the queue is priority ordered then this function returns the
|
||||
* thread with the lowest priority.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tqp the pointer to the threads list header
|
||||
* @return The removed thread pointer.
|
||||
*/
|
||||
Thread *lifo_remove(ThreadsQueue *tqp) {
|
||||
Thread *tp = tqp->p_prev;
|
||||
|
||||
(tqp->p_prev = tp->p_prev)->p_next = (Thread *)tqp;
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes a Thread from a queue and returns it.
|
||||
* @details The thread is removed from the queue regardless of its relative
|
||||
* position and regardless the used insertion method.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread to be removed from the queue
|
||||
* @return The removed thread pointer.
|
||||
*/
|
||||
Thread *dequeue(Thread *tp) {
|
||||
|
||||
tp->p_prev->p_next = tp->p_next;
|
||||
tp->p_next->p_prev = tp->p_prev;
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes a Thread on top of a stack list.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread to be inserted in the list
|
||||
* @param[in] tlp the pointer to the threads list header
|
||||
*/
|
||||
void list_insert(Thread *tp, ThreadsList *tlp) {
|
||||
|
||||
tp->p_next = tlp->p_next;
|
||||
tlp->p_next = tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pops a Thread from the top of a stack list and returns it.
|
||||
* @note The list must be non-empty before calling this function.
|
||||
* @note This function is @b not an API.
|
||||
*
|
||||
* @param[in] tlp the pointer to the threads list header
|
||||
* @return The removed thread pointer.
|
||||
*/
|
||||
Thread *list_remove(ThreadsList *tlp) {
|
||||
|
||||
Thread *tp = tlp->p_next;
|
||||
tlp->p_next = tp->p_next;
|
||||
return tp;
|
||||
}
|
||||
#endif /* CH_OPTIMIZE_SPEED */
|
||||
|
||||
/** @} */
|
||||
276
ChibiOS_2.0.8/os/kernel/src/chmboxes.c
Normal file
276
ChibiOS_2.0.8/os/kernel/src/chmboxes.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmboxes.c
|
||||
* @brief Mailboxes code.
|
||||
*
|
||||
* @addtogroup mailboxes
|
||||
* @details Asynchronous messages.
|
||||
* <h2>Operation mode</h2>
|
||||
* A mailbox is an asynchronous communication mechanism.<br>
|
||||
* Operations defined for mailboxes:
|
||||
* - <b>Post</b>: Posts a message on the mailbox in FIFO order.
|
||||
* - <b>Post Ahead</b>: Posts a message on the mailbox with urgent
|
||||
* priority.
|
||||
* - <b>Fetch</b>: A message is fetched from the mailbox and removed
|
||||
* from the queue.
|
||||
* - <b>Reset</b>: The mailbox is emptied and all the stored messages
|
||||
* are lost.
|
||||
* .
|
||||
* A message is a variable of type msg_t that is guaranteed to have
|
||||
* the same size of and be compatible with (data) pointers (anyway an
|
||||
* explicit cast is needed).
|
||||
* If larger messages need to be exchanged then a pointer to a
|
||||
* structure can be posted in the mailbox but the posting side has
|
||||
* no predefined way to know when the message has been processed. A
|
||||
* possible approach is to allocate memory (from a memory pool as
|
||||
* example) from the posting side and free it on the fetching side.
|
||||
* Another approach is to set a "done" flag into the structure pointed
|
||||
* by the message.<br>
|
||||
* In order to use the mailboxes APIs the @p CH_USE_MAILBOXES option
|
||||
* must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_MAILBOXES
|
||||
/**
|
||||
* @brief Initializes a Mailbox object.
|
||||
*
|
||||
* @param[out] mbp the pointer to the Mailbox structure to be initialized
|
||||
* @param[in] buf the circular messages buffer
|
||||
* @param[in] n the buffer size as number of @p msg_t
|
||||
*/
|
||||
void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) {
|
||||
|
||||
chDbgCheck((mbp != NULL) && (buf != NULL) && (n > 0), "chMBInit");
|
||||
|
||||
mbp->mb_buffer = mbp->mb_wrptr = mbp->mb_rdptr = buf;
|
||||
mbp->mb_top = &buf[n];
|
||||
chSemInit(&mbp->mb_emptysem, n);
|
||||
chSemInit(&mbp->mb_fullsem, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets a Mailbox object.
|
||||
* @details All the waiting threads are resumed with status @p RDY_RESET and
|
||||
* the queued messages are lost.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
*/
|
||||
void chMBReset(Mailbox *mbp) {
|
||||
|
||||
chDbgCheck(mbp != NULL, "chMBReset");
|
||||
|
||||
chSysLock();
|
||||
mbp->mb_wrptr = mbp->mb_rdptr = mbp->mb_buffer;
|
||||
chSemResetI(&mbp->mb_emptysem, mbp->mb_top - mbp->mb_buffer);
|
||||
chSemResetI(&mbp->mb_fullsem, 0);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Posts a message into a mailbox.
|
||||
* @details The invoking thread waits until a empty slot in the mailbox becomes
|
||||
* available or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[in] msg the message to be posted on the mailbox
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if the message was correctly posted.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chSysLock();
|
||||
rdymsg = chMBPostS(mbp, msg, time);
|
||||
chSysUnlock();
|
||||
return rdymsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Posts a message into a mailbox.
|
||||
* @details The invoking thread waits until a empty slot in the mailbox becomes
|
||||
* available or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[in] msg the message to be posted on the mailbox
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if the message was correctly posted.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chDbgCheck(mbp != NULL, "chMBPostS");
|
||||
|
||||
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
|
||||
if (rdymsg == RDY_OK) {
|
||||
*mbp->mb_wrptr++ = msg;
|
||||
if (mbp->mb_wrptr >= mbp->mb_top)
|
||||
mbp->mb_wrptr = mbp->mb_buffer;
|
||||
chSemSignalI(&mbp->mb_fullsem);
|
||||
chSchRescheduleS();
|
||||
}
|
||||
return rdymsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Posts an high priority message into a mailbox.
|
||||
* @details The invoking thread waits until a empty slot in the mailbox becomes
|
||||
* available or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[in] msg the message to be posted on the mailbox
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if the message was correctly posted.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chSysLock();
|
||||
rdymsg = chMBPostAheadS(mbp, msg, time);
|
||||
chSysUnlock();
|
||||
return rdymsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Posts an high priority message into a mailbox.
|
||||
* @details The invoking thread waits until a empty slot in the mailbox becomes
|
||||
* available or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[in] msg the message to be posted on the mailbox
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if the message was correctly posted.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chDbgCheck(mbp != NULL, "chMBPostAheadS");
|
||||
|
||||
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
|
||||
if (rdymsg == RDY_OK) {
|
||||
if (--mbp->mb_rdptr < mbp->mb_buffer)
|
||||
mbp->mb_rdptr = mbp->mb_top - 1;
|
||||
*mbp->mb_rdptr = msg;
|
||||
chSemSignalI(&mbp->mb_fullsem);
|
||||
chSchRescheduleS();
|
||||
}
|
||||
return rdymsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a message from a mailbox.
|
||||
* @details The invoking thread waits until a message is posted in the mailbox
|
||||
* or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[out] msgp pointer to a message variable for the received message
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if a message was correctly fetched.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chSysLock();
|
||||
rdymsg = chMBFetchS(mbp, msgp, time);
|
||||
chSysUnlock();
|
||||
return rdymsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a message from a mailbox.
|
||||
* @details The invoking thread waits until a message is posted in the mailbox
|
||||
* or the specified time runs out.
|
||||
*
|
||||
* @param[in] mbp the pointer to an initialized Mailbox object
|
||||
* @param[out] msgp pointer to a message variable for the received message
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval RDY_OK if a message was correctly fetched.
|
||||
* @retval RDY_RESET if the mailbox was reset while waiting.
|
||||
* @retval RDY_TIMEOUT if the operation timed out.
|
||||
*/
|
||||
msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) {
|
||||
msg_t rdymsg;
|
||||
|
||||
chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS");
|
||||
|
||||
rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time);
|
||||
if (rdymsg == RDY_OK) {
|
||||
*msgp = *mbp->mb_rdptr++;
|
||||
if (mbp->mb_rdptr >= mbp->mb_top)
|
||||
mbp->mb_rdptr = mbp->mb_buffer;
|
||||
chSemSignalI(&mbp->mb_emptysem);
|
||||
chSchRescheduleS();
|
||||
}
|
||||
return rdymsg;
|
||||
}
|
||||
#endif /* CH_USE_MAILBOXES */
|
||||
|
||||
/** @} */
|
||||
129
ChibiOS_2.0.8/os/kernel/src/chmemcore.c
Normal file
129
ChibiOS_2.0.8/os/kernel/src/chmemcore.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmemcore.c
|
||||
* @brief Core memory manager code.
|
||||
*
|
||||
* @addtogroup memcore
|
||||
* @details Core Memory Manager related APIs and services.
|
||||
* <h2>Operation mode</h2>
|
||||
* The core memory manager is a simplified allocator that only allows
|
||||
* to allocate memory blocks without the possibility to free them.<br>
|
||||
* This allocator is meant as a memory blocks provider for the other
|
||||
* allocators such as:
|
||||
* - C-Runtime allocator (through a compiler specific adapter module).
|
||||
* - Heap allocator (see @ref heaps).
|
||||
* - Memory pools allocator (see @ref pools).
|
||||
* .
|
||||
* By having a centralized memory provider the various allocators can
|
||||
* coexist and share the main memory.<br>
|
||||
* This allocator, alone, is also useful for very simple applications
|
||||
* that just require a simple way to get memory blocks.<br>
|
||||
* In order to use the core memory manager APIs the @p CH_USE_MEMCORE
|
||||
* option must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_MEMCORE
|
||||
|
||||
static uint8_t *nextmem;
|
||||
static uint8_t *endmem;
|
||||
|
||||
/**
|
||||
* @brief Low level memory manager initialization.
|
||||
* @note Internal use only.
|
||||
*/
|
||||
void core_init(void) {
|
||||
#if CH_MEMCORE_SIZE == 0
|
||||
extern uint8_t __heap_base__;
|
||||
extern uint8_t __heap_end__;
|
||||
nextmem = &__heap_base__;
|
||||
endmem = &__heap_end__;
|
||||
#else
|
||||
static stkalign_t buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) /
|
||||
sizeof(stkalign_t)];
|
||||
nextmem = (uint8_t *)&buffer[0];
|
||||
endmem = (uint8_t *)&buffer[MEM_ALIGN_SIZE(CH_MEMCORE_SIZE) /
|
||||
sizeof(stkalign_t)];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a memory block.
|
||||
* @details The size of the returned block is aligned to the alignment
|
||||
* type @p stkalign_t so it is not possible to allocate less
|
||||
* than <code>sizeof(stkalign_t)</code>.
|
||||
*
|
||||
*
|
||||
* @param[in] size the size of the block to be allocated
|
||||
* @return A pointer to the allocated memory block.
|
||||
* @retval NULL allocation failed, core memory exhausted.
|
||||
*/
|
||||
void *chCoreAlloc(size_t size) {
|
||||
void *p;
|
||||
|
||||
chSysLock();
|
||||
p = chCoreAllocI(size);
|
||||
chSysUnlock();
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a memory block.
|
||||
* @details The size of the returned block is aligned to the alignment
|
||||
* type @p align_t so it is not possible to allocate less than
|
||||
* <code>sizeof(align_t)</code>.
|
||||
*
|
||||
* @param[in] size the size of the block to be allocated.
|
||||
* @return A pointer to the allocated memory block.
|
||||
* @retval NULL allocation failed, core memory exhausted.
|
||||
*/
|
||||
void *chCoreAllocI(size_t size) {
|
||||
void *p;
|
||||
|
||||
size = MEM_ALIGN_SIZE(size);
|
||||
if ((size_t)(endmem - nextmem) < size)
|
||||
return NULL;
|
||||
p = nextmem;
|
||||
nextmem += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Core memory status.
|
||||
*
|
||||
* @return The size, in bytes, of the free core memory.
|
||||
*/
|
||||
size_t chCoreStatus(void) {
|
||||
|
||||
return (size_t)(endmem - nextmem);
|
||||
}
|
||||
#endif /* CH_USE_MEMCORE */
|
||||
|
||||
/** @} */
|
||||
140
ChibiOS_2.0.8/os/kernel/src/chmempools.c
Normal file
140
ChibiOS_2.0.8/os/kernel/src/chmempools.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmempools.c
|
||||
* @brief Memory Pools code.
|
||||
*
|
||||
* @addtogroup pools
|
||||
* @details Memory Pools related APIs and services.
|
||||
* <h2>Operation mode</h2>
|
||||
* The Memory Pools APIs allow to allocate/free fixed size objects in
|
||||
* <b>constant time</b> and reliably without memory fragmentation
|
||||
* problems.<br>
|
||||
* In order to use the memory pools APIs the @p CH_USE_MEMPOOLS option
|
||||
* must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_MEMPOOLS
|
||||
/**
|
||||
* @brief Initializes an empty memory pool.
|
||||
* @note The size is internally aligned to be a multiple of the @p align_t
|
||||
* type size.
|
||||
*
|
||||
* @param[out] mp pointer to a @p MemoryPool structure
|
||||
* @param[in] size the size of the objects contained in this memory pool,
|
||||
* the minimum accepted size is the size of a pointer to
|
||||
* void.
|
||||
* @param[in] provider memory provider function for the memory pool or
|
||||
* @p NULL if the pool is not allowed to grow
|
||||
* automatically
|
||||
*/
|
||||
void chPoolInit(MemoryPool *mp, size_t size, memgetfunc_t provider) {
|
||||
|
||||
chDbgCheck((mp != NULL) && (size >= sizeof(void *)), "chPoolInit");
|
||||
|
||||
mp->mp_next = NULL;
|
||||
mp->mp_object_size = MEM_ALIGN_SIZE(size);
|
||||
mp->mp_provider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates an object from a memory pool.
|
||||
*
|
||||
* @param[in] mp pointer to a @p MemoryPool structure
|
||||
* @return The pointer to the allocated object.
|
||||
* @retval NULL if pool is empty.
|
||||
*/
|
||||
void *chPoolAllocI(MemoryPool *mp) {
|
||||
void *objp;
|
||||
|
||||
chDbgCheck(mp != NULL, "chPoolAllocI");
|
||||
|
||||
if ((objp = mp->mp_next) != NULL)
|
||||
mp->mp_next = mp->mp_next->ph_next;
|
||||
#if CH_USE_MEMCORE
|
||||
else if (mp->mp_provider != NULL)
|
||||
objp = mp->mp_provider(mp->mp_object_size);
|
||||
#endif
|
||||
return objp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates an object from a memory pool.
|
||||
*
|
||||
* @param[in] mp pointer to a @p MemoryPool structure
|
||||
* @return The pointer to the allocated object.
|
||||
* @retval NULL if pool is empty.
|
||||
*/
|
||||
void *chPoolAlloc(MemoryPool *mp) {
|
||||
void *objp;
|
||||
|
||||
chSysLock();
|
||||
objp = chPoolAllocI(mp);
|
||||
chSysUnlock();
|
||||
return objp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases (or adds) an object into (to) a memory pool.
|
||||
* @note The object is assumed to be of the right size for the specified
|
||||
* memory pool.
|
||||
* @note The object is assumed to be memory aligned to the size of @p align_t
|
||||
* type.
|
||||
*
|
||||
* @param[in] mp pointer to a @p MemoryPool structure
|
||||
* @param[in] objp the pointer to the object to be released or added
|
||||
*/
|
||||
void chPoolFreeI(MemoryPool *mp, void *objp) {
|
||||
struct pool_header *php = objp;
|
||||
|
||||
chDbgCheck((mp != NULL) && (objp != NULL) && MEM_IS_ALIGNED(objp),
|
||||
"chPoolFreeI");
|
||||
|
||||
php->ph_next = mp->mp_next;
|
||||
mp->mp_next = php;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases (or adds) an object into (to) a memory pool.
|
||||
* @note The object is assumed to be of the right size for the specified
|
||||
* memory pool.
|
||||
*
|
||||
* @param[in] mp pointer to a @p MemoryPool structure
|
||||
* @param[in] objp the pointer to the object to be released or added
|
||||
*/
|
||||
void chPoolFree(MemoryPool *mp, void *objp) {
|
||||
|
||||
chSysLock();
|
||||
chPoolFreeI(mp, objp);
|
||||
chSysUnlock();
|
||||
}
|
||||
#endif /* CH_USE_MEMPOOLS */
|
||||
|
||||
/** @} */
|
||||
157
ChibiOS_2.0.8/os/kernel/src/chmsg.c
Normal file
157
ChibiOS_2.0.8/os/kernel/src/chmsg.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmsg.c
|
||||
* @brief Messages code.
|
||||
*
|
||||
* @addtogroup messages
|
||||
* @details Synchronous inter-thread messages APIs and services.
|
||||
* <h2>Operation Mode</h2>
|
||||
* Synchronous messages are an easy to use and fast IPC mechanism,
|
||||
* threads can both act as message servers and/or message clients,
|
||||
* the mechanism allows data to be carried in both directions. Note
|
||||
* that messages are not copied between the client and server threads
|
||||
* but just a pointer passed so the exchange is very time
|
||||
* efficient.<br>
|
||||
* Messages are usually processed in FIFO order but it is possible to
|
||||
* process them in priority order by enabling the
|
||||
* @p CH_USE_MESSAGES_PRIORITY option in @p chconf.h.<br>
|
||||
* Applications do not need to allocate buffers for synchronous
|
||||
* message queues, the mechanism just requires two extra pointers in
|
||||
* the @p Thread structure (the message queue header).<br>
|
||||
* In order to use the Messages APIs the @p CH_USE_MESSAGES option
|
||||
* must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_MESSAGES
|
||||
|
||||
#if CH_USE_MESSAGES_PRIORITY
|
||||
#define msg_insert(tp, qp) prio_insert(tp, qp)
|
||||
#else
|
||||
#define msg_insert(tp, qp) queue_insert(tp, qp)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sends a message to the specified thread.
|
||||
* @details The sender is stopped until the receiver executes a
|
||||
* @p chMsgRelease()after receiving the message.
|
||||
*
|
||||
* @param[in] tp the pointer to the thread
|
||||
* @param[in] msg the message
|
||||
* @return The answer message from @p chMsgRelease().
|
||||
*/
|
||||
msg_t chMsgSend(Thread *tp, msg_t msg) {
|
||||
Thread *ctp = currp;
|
||||
|
||||
chDbgCheck(tp != NULL, "chMsgSend");
|
||||
|
||||
chSysLock();
|
||||
ctp->p_msg = msg;
|
||||
ctp->p_u.wtobjp = &tp->p_msgqueue;
|
||||
msg_insert(ctp, &tp->p_msgqueue);
|
||||
if (tp->p_state == THD_STATE_WTMSG)
|
||||
chSchReadyI(tp);
|
||||
chSchGoSleepS(THD_STATE_SNDMSG);
|
||||
msg = ctp->p_u.rdymsg;
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspends the thread and waits for an incoming message.
|
||||
* @note You can assume that the data contained in the message is stable
|
||||
* until you invoke @p chMsgRelease() because the sending thread is
|
||||
* suspended until then.
|
||||
*
|
||||
* @return The pointer to the message structure. Note, it is
|
||||
* always the message associated to the thread on the
|
||||
* top of the messages queue.
|
||||
*/
|
||||
msg_t chMsgWait(void) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
if (!chMsgIsPendingI(currp))
|
||||
chSchGoSleepS(THD_STATE_WTMSG);
|
||||
#if defined(CH_ARCHITECTURE_STM8)
|
||||
msg = chMsgGetI((volatile Thread *)currp); /* Temporary hack.*/
|
||||
#else
|
||||
msg = chMsgGetI(currp);
|
||||
#endif
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the next message in the queue.
|
||||
* @note You can assume that the data pointed by the message is stable until
|
||||
* you invoke @p chMsgRelease() because the sending thread is
|
||||
* suspended until then. Always remember that the message data is not
|
||||
* copied between the sender and the receiver, just a pointer is
|
||||
* passed.
|
||||
*
|
||||
* @return The pointer to the message structure. Note, it is
|
||||
* always the message associated to the thread on the
|
||||
* top of the messages queue.
|
||||
* @retval NULL if the queue is empty.
|
||||
*/
|
||||
msg_t chMsgGet(void) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
msg = chMsgIsPendingI(currp) ? chMsgGetI(currp) : (msg_t)NULL;
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases the thread waiting on top of the messages queue.
|
||||
* @note You can call this function only if there is a message already in
|
||||
* the queue else the result will be unpredictable (a crash most likely).
|
||||
* Exiting from the @p chMsgWait() ensures you have at least one
|
||||
* message in the queue so it is not a big deal.<br>
|
||||
* The condition is only tested in debug mode in order to make this
|
||||
* code as fast as possible.
|
||||
*
|
||||
* @param[in] msg the message returned to the message sender
|
||||
*/
|
||||
void chMsgRelease(msg_t msg) {
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(chMsgIsPendingI(currp),
|
||||
"chMsgRelease(), #1",
|
||||
"no message pending");
|
||||
chSchWakeupS(fifo_remove(&currp->p_msgqueue), msg);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
#endif /* CH_USE_MESSAGES */
|
||||
|
||||
/** @} */
|
||||
348
ChibiOS_2.0.8/os/kernel/src/chmtx.c
Normal file
348
ChibiOS_2.0.8/os/kernel/src/chmtx.c
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chmtx.c
|
||||
* @brief Mutexes code.
|
||||
*
|
||||
* @addtogroup mutexes
|
||||
* @details Mutexes related APIs and services.
|
||||
*
|
||||
* <h2>Operation mode</h2>
|
||||
* A mutex is a threads synchronization object that can be in two
|
||||
* distinct states:
|
||||
* - Not owned.
|
||||
* - Owned by a thread.
|
||||
* .
|
||||
* Operations defined for mutexes:
|
||||
* - <b>Lock</b>: The mutex is checked, if the mutex is not owned by
|
||||
* some other thread then it is associated to the locking thread
|
||||
* else the thread is queued on the mutex in a list ordered by
|
||||
* priority.
|
||||
* - <b>Unlock</b>: The mutex is released by the owner and the highest
|
||||
* priority thread waiting in the queue, if any, is resumed and made
|
||||
* owner of the mutex.
|
||||
* .
|
||||
* In order to use the Mutexes APIs the @p CH_USE_MUTEXES option must
|
||||
* be enabled in @p chconf.h.
|
||||
* <h2>Constraints</h2>
|
||||
* In ChibiOS/RT the Unlock operations are always performed in
|
||||
* lock-reverse order. The unlock API does not even have a parameter,
|
||||
* the mutex to unlock is selected from an internal, per-thread, stack
|
||||
* of owned mutexes. This both improves the performance and is
|
||||
* required for an efficient implementation of the priority
|
||||
* inheritance mechanism.
|
||||
*
|
||||
* <h2>The priority inversion problem</h2>
|
||||
* The mutexes in ChibiOS/RT implements the <b>full</b> priority
|
||||
* inheritance mechanism in order handle the priority inversion
|
||||
* problem.<br>
|
||||
* When a thread is queued on a mutex, any thread, directly or
|
||||
* indirectly, holding the mutex gains the same priority of the
|
||||
* waiting thread (if their priority was not already equal or higher).
|
||||
* The mechanism works with any number of nested mutexes and any
|
||||
* number of involved threads. The algorithm complexity (worst case)
|
||||
* is N with N equal to the number of nested mutexes.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
|
||||
/**
|
||||
* @brief Initializes s @p Mutex structure.
|
||||
*
|
||||
* @param[out] mp pointer to a @p Mutex structure
|
||||
*/
|
||||
void chMtxInit(Mutex *mp) {
|
||||
|
||||
chDbgCheck(mp != NULL, "chMtxInit");
|
||||
|
||||
queue_init(&mp->m_queue);
|
||||
mp->m_owner = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the specified mutex.
|
||||
*
|
||||
* @param[in] mp pointer to the @p Mutex structure
|
||||
*/
|
||||
void chMtxLock(Mutex *mp) {
|
||||
|
||||
chSysLock();
|
||||
|
||||
chMtxLockS(mp);
|
||||
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the specified mutex.
|
||||
*
|
||||
* @param[in] mp pointer to the @p Mutex structure
|
||||
*/
|
||||
void chMtxLockS(Mutex *mp) {
|
||||
Thread *ctp = currp;
|
||||
|
||||
chDbgCheck(mp != NULL, "chMtxLockS");
|
||||
|
||||
/* Ia the mutex already locked? */
|
||||
if (mp->m_owner != NULL) {
|
||||
/* Priority inheritance protocol; explores the thread-mutex dependencies
|
||||
boosting the priority of all the affected threads to equal the priority
|
||||
of the running thread requesting the mutex.*/
|
||||
Thread *tp = mp->m_owner;
|
||||
/* Does the running thread have higher priority than the mutex
|
||||
ownning thread? */
|
||||
while (tp->p_prio < ctp->p_prio) {
|
||||
/* Make priority of thread tp match the running thread's priority.*/
|
||||
tp->p_prio = ctp->p_prio;
|
||||
/* The following states need priority queues reordering.*/
|
||||
switch (tp->p_state) {
|
||||
case THD_STATE_WTMTX:
|
||||
/* Re-enqueues the mutex owner with its new priority.*/
|
||||
prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp);
|
||||
tp = ((Mutex *)tp->p_u.wtobjp)->m_owner;
|
||||
continue;
|
||||
#if CH_USE_CONDVARS | CH_USE_SEMAPHORES_PRIORITY | CH_USE_MESSAGES_PRIORITY
|
||||
#if CH_USE_CONDVARS
|
||||
case THD_STATE_WTCOND:
|
||||
#endif
|
||||
#if CH_USE_SEMAPHORES_PRIORITY
|
||||
case THD_STATE_WTSEM:
|
||||
#endif
|
||||
#if CH_USE_MESSAGES_PRIORITY
|
||||
case THD_STATE_SNDMSG:
|
||||
#endif
|
||||
/* Re-enqueues tp with its new priority on the queue.*/
|
||||
prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp);
|
||||
break;
|
||||
#endif
|
||||
case THD_STATE_READY:
|
||||
/* Re-enqueues tp with its new priority on the ready list.*/
|
||||
chSchReadyI(dequeue(tp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Sleep on the mutex.*/
|
||||
prio_insert(ctp, &mp->m_queue);
|
||||
ctp->p_u.wtobjp = mp;
|
||||
chSchGoSleepS(THD_STATE_WTMTX);
|
||||
/* It is assumed that the thread performing the unlock operation assigns
|
||||
the mutex to this thread.*/
|
||||
chDbgAssert(mp->m_owner == ctp, "chMtxLockS(), #1", "not owner");
|
||||
chDbgAssert(ctp->p_mtxlist == mp, "chMtxLockS(), #2", "not owned");
|
||||
}
|
||||
else {
|
||||
/* It was not owned, inserted in the owned mutexes list.*/
|
||||
mp->m_owner = ctp;
|
||||
mp->m_next = ctp->p_mtxlist;
|
||||
ctp->p_mtxlist = mp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to lock a mutex.
|
||||
* @details This function does not have any overhead related to
|
||||
* the priority inheritance mechanism because it does not try to
|
||||
* enter a sleep state on the mutex.
|
||||
*
|
||||
* @param[in] mp pointer to the @p Mutex structure
|
||||
* @retval TRUE if the mutex was successfully acquired
|
||||
* @retval FALSE if the lock attempt failed.
|
||||
*/
|
||||
bool_t chMtxTryLock(Mutex *mp) {
|
||||
bool_t b;
|
||||
|
||||
chSysLock();
|
||||
|
||||
b = chMtxTryLockS(mp);
|
||||
|
||||
chSysUnlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to lock a mutex.
|
||||
* @details This function does not have any overhead related to
|
||||
* the priority inheritance mechanism because it does not try to
|
||||
* enter a sleep state on the mutex.
|
||||
*
|
||||
* @param[in] mp pointer to the @p Mutex structure
|
||||
* @retval TRUE if the mutex was successfully acquired
|
||||
* @retval FALSE if the lock attempt failed.
|
||||
*/
|
||||
bool_t chMtxTryLockS(Mutex *mp) {
|
||||
|
||||
chDbgCheck(mp != NULL, "chMtxTryLockS");
|
||||
|
||||
if (mp->m_owner != NULL)
|
||||
return FALSE;
|
||||
mp->m_owner = currp;
|
||||
mp->m_next = currp->p_mtxlist;
|
||||
currp->p_mtxlist = mp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks the next owned mutex in reverse lock order.
|
||||
*
|
||||
* @return The pointer to the unlocked mutex.
|
||||
*/
|
||||
Mutex *chMtxUnlock(void) {
|
||||
Thread *ctp = currp;
|
||||
Mutex *ump, *mp;
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(ctp->p_mtxlist != NULL,
|
||||
"chMtxUnlock(), #1",
|
||||
"owned mutexes list empty");
|
||||
chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
|
||||
"chMtxUnlock(), #2",
|
||||
"ownership failure");
|
||||
/* Removes the top Mutex from the Threads's owned mutexes list and matk it
|
||||
as not owned.*/
|
||||
ump = ctp->p_mtxlist;
|
||||
ctp->p_mtxlist = ump->m_next;
|
||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||
if (chMtxQueueNotEmptyS(ump)) {
|
||||
Thread *tp;
|
||||
|
||||
/* Recalculates the optimal thread priority by scanning the owned
|
||||
mutexes list.*/
|
||||
tprio_t newprio = ctp->p_realprio;
|
||||
mp = ctp->p_mtxlist;
|
||||
while (mp != NULL) {
|
||||
/* If the highest priority thread waiting in the mutexes list has a
|
||||
greater priority than the current thread base priority then the final
|
||||
priority will have at least that priority.*/
|
||||
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
|
||||
newprio = mp->m_queue.p_next->p_prio;
|
||||
mp = mp->m_next;
|
||||
}
|
||||
/* Assigns to the current thread the highest priority among all the
|
||||
waiting threads.*/
|
||||
ctp->p_prio = newprio;
|
||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||
assigns the mutex to it.*/
|
||||
tp = fifo_remove(&ump->m_queue);
|
||||
ump->m_owner = tp;
|
||||
ump->m_next = tp->p_mtxlist;
|
||||
tp->p_mtxlist = ump;
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
}
|
||||
else
|
||||
ump->m_owner = NULL;
|
||||
chSysUnlock();
|
||||
return ump;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks the next owned mutex in reverse lock order.
|
||||
* @note This function does not reschedule internally.
|
||||
*
|
||||
* @return The pointer to the unlocked mutex.
|
||||
*/
|
||||
Mutex *chMtxUnlockS(void) {
|
||||
Thread *ctp = currp;
|
||||
Mutex *ump, *mp;
|
||||
|
||||
chDbgAssert(ctp->p_mtxlist != NULL,
|
||||
"chMtxUnlockS(), #1",
|
||||
"owned mutexes list empty");
|
||||
chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
|
||||
"chMtxUnlockS(), #2",
|
||||
"ownership failure");
|
||||
|
||||
/* Removes the top Mutex from the owned mutexes list and marks it as not
|
||||
owned.*/
|
||||
ump = ctp->p_mtxlist;
|
||||
ctp->p_mtxlist = ump->m_next;
|
||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||
if (chMtxQueueNotEmptyS(ump)) {
|
||||
Thread *tp;
|
||||
|
||||
/* Recalculates the optimal thread priority by scanning the owned
|
||||
mutexes list.*/
|
||||
tprio_t newprio = ctp->p_realprio;
|
||||
mp = ctp->p_mtxlist;
|
||||
while (mp != NULL) {
|
||||
/* If the highest priority thread waiting in the mutexes list has a
|
||||
greater priority than the current thread base priority then the final
|
||||
priority will have at least that priority.*/
|
||||
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
|
||||
newprio = mp->m_queue.p_next->p_prio;
|
||||
mp = mp->m_next;
|
||||
}
|
||||
ctp->p_prio = newprio;
|
||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||
assigns the mutex to it.*/
|
||||
tp = fifo_remove(&ump->m_queue);
|
||||
ump->m_owner = tp;
|
||||
ump->m_next = tp->p_mtxlist;
|
||||
tp->p_mtxlist = ump;
|
||||
chSchReadyI(tp);
|
||||
}
|
||||
else
|
||||
ump->m_owner = NULL;
|
||||
return ump;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks all the mutexes owned by the invoking thread.
|
||||
* @details This function is <b>MUCH MORE</b> efficient than releasing the
|
||||
* mutexes one by one and not just because the call overhead,
|
||||
* this function does not have any overhead related to the priority
|
||||
* inheritance mechanism.
|
||||
*/
|
||||
void chMtxUnlockAll(void) {
|
||||
Thread *ctp = currp;
|
||||
|
||||
chSysLock();
|
||||
if (ctp->p_mtxlist != NULL) {
|
||||
do {
|
||||
Mutex *ump = ctp->p_mtxlist;
|
||||
ctp->p_mtxlist = ump->m_next;
|
||||
if (chMtxQueueNotEmptyS(ump)) {
|
||||
Thread *tp = fifo_remove(&ump->m_queue);
|
||||
ump->m_owner = tp;
|
||||
ump->m_next = tp->p_mtxlist;
|
||||
tp->p_mtxlist = ump;
|
||||
chSchReadyI(tp);
|
||||
}
|
||||
else
|
||||
ump->m_owner = NULL;
|
||||
} while (ctp->p_mtxlist != NULL);
|
||||
ctp->p_prio = ctp->p_realprio;
|
||||
chSchRescheduleS();
|
||||
}
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
#endif /* CH_USE_MUTEXES */
|
||||
|
||||
/** @} */
|
||||
363
ChibiOS_2.0.8/os/kernel/src/chqueues.c
Normal file
363
ChibiOS_2.0.8/os/kernel/src/chqueues.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chqueues.c
|
||||
* @brief I/O Queues code.
|
||||
*
|
||||
* @addtogroup io_queues
|
||||
* @details ChibiOS/RT queues are mostly used in serial-like device drivers.
|
||||
* The device drivers are usually designed to have a lower side
|
||||
* (lower driver, it is usually an interrupt service routine) and an
|
||||
* upper side (upper driver, accessed by the application threads).<br>
|
||||
* There are several kind of queues:<br>
|
||||
* - <b>Input queue</b>, unidirectional queue where the writer is the
|
||||
* lower side and the reader is the upper side.
|
||||
* - <b>Output queue</b>, unidirectional queue where the writer is the
|
||||
* upper side and the reader is the lower side.
|
||||
* - <b>Full duplex queue</b>, bidirectional queue. Full duplex queues
|
||||
* are implemented by pairing an input queue and an output queue
|
||||
* together.
|
||||
* .
|
||||
* In order to use the I/O queues the @p CH_USE_QUEUES option must
|
||||
* be enabled in @p chconf.h.<br>
|
||||
* I/O queues are usually used as an implementation layer for the I/O
|
||||
* channels interface, also see @ref io_channels.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_QUEUES
|
||||
|
||||
/**
|
||||
* @brief Initializes an input queue.
|
||||
* @details A Semaphore is internally initialized and works as a counter of
|
||||
* the bytes contained in the queue.
|
||||
* @note The callback is invoked from within the S-Locked system state,
|
||||
* see @ref system_states.
|
||||
*
|
||||
* @param[out] iqp pointer to an @p InputQueue structure
|
||||
* @param[in] bp pointer to a memory area allocated as queue buffer
|
||||
* @param[in] size size of the queue buffer
|
||||
* @param[in] infy pointer to a callback function that is invoked when
|
||||
* data is read from the queue. The value can be @p NULL.
|
||||
*/
|
||||
void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy) {
|
||||
|
||||
iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp;
|
||||
iqp->q_top = bp + size;
|
||||
iqp->q_notify = infy;
|
||||
chSemInit(&iqp->q_sem, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets an input queue.
|
||||
* @details All the data in the input queue is erased and lost, any waiting
|
||||
* thread is resumed with status @p Q_RESET.
|
||||
* @note A reset operation can be used by a low level driver in order to
|
||||
* obtain immediate attention from the high level layers.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
*/
|
||||
void chIQResetI(InputQueue *iqp) {
|
||||
|
||||
iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer;
|
||||
chSemResetI(&iqp->q_sem, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Input queue write.
|
||||
* @details A byte value is written into the low end of an input queue.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
* @param[in] b the byte value to be written in the queue
|
||||
* @return The operation status, it can be one of:
|
||||
* @retval Q_OK if the operation has been completed with success.
|
||||
* @retval Q_FULL if the queue is full and the operation cannot be
|
||||
* completed.
|
||||
*/
|
||||
msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
|
||||
|
||||
if (chIQIsFull(iqp))
|
||||
return Q_FULL;
|
||||
|
||||
*iqp->q_wrptr++ = b;
|
||||
if (iqp->q_wrptr >= iqp->q_top)
|
||||
iqp->q_wrptr = iqp->q_buffer;
|
||||
chSemSignalI(&iqp->q_sem);
|
||||
return Q_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Input queue read with timeout.
|
||||
* @details This function reads a byte value from an input queue. If the queue
|
||||
* is empty then the calling thread is suspended until a byte arrives
|
||||
* in the queue or a timeout occurs.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return A byte value from the queue or:
|
||||
* @retval Q_TIMEOUT if the specified time expired.
|
||||
* @retval Q_RESET if the queue was reset.
|
||||
*/
|
||||
msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) {
|
||||
uint8_t b;
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
|
||||
if (iqp->q_notify)
|
||||
iqp->q_notify();
|
||||
|
||||
if ((msg = chSemWaitTimeoutS(&iqp->q_sem, time)) < RDY_OK) {
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
b = *iqp->q_rdptr++;
|
||||
if (iqp->q_rdptr >= iqp->q_top)
|
||||
iqp->q_rdptr = iqp->q_buffer;
|
||||
|
||||
chSysUnlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Input queue read with timeout.
|
||||
* @details The function reads data from an input queue into a buffer. The
|
||||
* operation completes when the specified amount of data has been
|
||||
* transferred or after the specified timeout or if the queue has
|
||||
* been reset.
|
||||
* @note The function is not atomic, if you need atomicity it is suggested
|
||||
* to use a semaphore or a mutex for mutual exclusion.
|
||||
* @note The queue callback is invoked before entering a sleep state and at
|
||||
* the end of the transfer.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
* @param[out] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred, the
|
||||
* value 0 is reserved
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The number of bytes effectively transferred.
|
||||
*/
|
||||
size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
|
||||
size_t n, systime_t time) {
|
||||
qnotify_t nfy = iqp->q_notify;
|
||||
size_t r = 0;
|
||||
|
||||
chDbgCheck(n > 0, "chIQReadTimeout");
|
||||
|
||||
chSysLock();
|
||||
while (TRUE) {
|
||||
if (chIQIsEmpty(iqp)) {
|
||||
if (nfy)
|
||||
nfy();
|
||||
if ((chSemWaitTimeoutS(&iqp->q_sem, time) != RDY_OK)) {
|
||||
chSysUnlock();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
else
|
||||
chSemFastWaitI(&iqp->q_sem);
|
||||
*bp++ = *iqp->q_rdptr++;
|
||||
if (iqp->q_rdptr >= iqp->q_top)
|
||||
iqp->q_rdptr = iqp->q_buffer;
|
||||
if (nfy)
|
||||
nfy();
|
||||
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
|
||||
r++;
|
||||
if (--n == 0) {
|
||||
chSysLock();
|
||||
if (nfy)
|
||||
nfy();
|
||||
chSysUnlock();
|
||||
return r;
|
||||
}
|
||||
chSysLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes an output queue.
|
||||
* @details A Semaphore is internally initialized and works as a counter of
|
||||
* the free bytes in the queue.
|
||||
* @note The callback is invoked from within the S-Locked system state,
|
||||
* see @ref system_states.
|
||||
*
|
||||
* @param[out] oqp pointer to an @p OutputQueue structure
|
||||
* @param[in] bp pointer to a memory area allocated as queue buffer
|
||||
* @param[in] size size of the queue buffer
|
||||
* @param[in] onfy pointer to a callback function that is invoked when
|
||||
* data is written to the queue. The value can be @p NULL.
|
||||
*/
|
||||
void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy) {
|
||||
|
||||
oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp;
|
||||
oqp->q_top = bp + size;
|
||||
oqp->q_notify = onfy;
|
||||
chSemInit(&oqp->q_sem, (cnt_t)size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets an output queue.
|
||||
* @details All the data in the output queue is erased and lost, any waiting
|
||||
* thread is resumed with status @p Q_RESET.
|
||||
* @note A reset operation can be used by a low level driver in order to
|
||||
* obtain immediate attention from the high level layers.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
*/
|
||||
void chOQResetI(OutputQueue *oqp) {
|
||||
|
||||
oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer;
|
||||
chSemResetI(&oqp->q_sem, (cnt_t)(oqp->q_top - oqp->q_buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Output queue write with timeout.
|
||||
* @details This function writes a byte value to an output queue. If the queue
|
||||
* is full then the calling thread is suspended until there is space
|
||||
* in the queue or a timeout occurs.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
* @param[in] b the byte value to be written in the queue
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status:
|
||||
* @retval Q_OK if the operation succeeded.
|
||||
* @retval Q_TIMEOUT if the specified time expired.
|
||||
* @retval Q_RESET if the queue was reset.
|
||||
*/
|
||||
msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
if ((msg = chSemWaitTimeoutS(&oqp->q_sem, time)) < RDY_OK) {
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
*oqp->q_wrptr++ = b;
|
||||
if (oqp->q_wrptr >= oqp->q_top)
|
||||
oqp->q_wrptr = oqp->q_buffer;
|
||||
|
||||
if (oqp->q_notify)
|
||||
oqp->q_notify();
|
||||
|
||||
chSysUnlock();
|
||||
return Q_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Output queue read.
|
||||
* @details A byte value is read from the low end of an output queue.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
* @return The byte value from the queue or:
|
||||
* @retval Q_EMPTY if the queue is empty.
|
||||
*/
|
||||
msg_t chOQGetI(OutputQueue *oqp) {
|
||||
uint8_t b;
|
||||
|
||||
if (chOQIsEmpty(oqp))
|
||||
return Q_EMPTY;
|
||||
|
||||
b = *oqp->q_rdptr++;
|
||||
if (oqp->q_rdptr >= oqp->q_top)
|
||||
oqp->q_rdptr = oqp->q_buffer;
|
||||
chSemSignalI(&oqp->q_sem);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Output queue write with timeout.
|
||||
* @details The function writes data from a buffer to an output queue. The
|
||||
* operation completes when the specified amount of data has been
|
||||
* transferred or after the specified timeout or if the queue has
|
||||
* been reset.
|
||||
* @note The function is not atomic, if you need atomicity it is suggested
|
||||
* to use a semaphore or a mutex for mutual exclusion.
|
||||
* @note The queue callback is invoked before entering a sleep state and at
|
||||
* the end of the transfer.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
* @param[out] bp pointer to the data buffer
|
||||
* @param[in] n the maximum amount of data to be transferred, the
|
||||
* value 0 is reserved
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The number of bytes effectively transferred.
|
||||
*/
|
||||
size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp,
|
||||
size_t n, systime_t time) {
|
||||
qnotify_t nfy = oqp->q_notify;
|
||||
size_t w = 0;
|
||||
|
||||
chDbgCheck(n > 0, "chOQWriteTimeout");
|
||||
|
||||
chSysLock();
|
||||
while (TRUE) {
|
||||
if (chOQIsFull(oqp)) {
|
||||
if (nfy)
|
||||
nfy();
|
||||
if ((chSemWaitTimeoutS(&oqp->q_sem, time) != RDY_OK)) {
|
||||
chSysUnlock();
|
||||
return w;
|
||||
}
|
||||
}
|
||||
else
|
||||
chSemFastWaitI(&oqp->q_sem);
|
||||
*oqp->q_wrptr++ = *bp++;
|
||||
if (oqp->q_wrptr >= oqp->q_top)
|
||||
oqp->q_wrptr = oqp->q_buffer;
|
||||
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
|
||||
w++;
|
||||
if (--n == 0) {
|
||||
chSysLock();
|
||||
if (nfy)
|
||||
nfy();
|
||||
chSysUnlock();
|
||||
return w;
|
||||
}
|
||||
chSysLock();
|
||||
}
|
||||
}
|
||||
#endif /* CH_USE_QUEUES */
|
||||
|
||||
/** @} */
|
||||
114
ChibiOS_2.0.8/os/kernel/src/chregistry.c
Normal file
114
ChibiOS_2.0.8/os/kernel/src/chregistry.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chregistry.c
|
||||
* @brief Threads registry code.
|
||||
*
|
||||
* @addtogroup registry
|
||||
* @details Threads Registry related APIs and services.
|
||||
*
|
||||
* <h2>Operation mode</h2>
|
||||
* The Threads Registry is a double linked list that holds all the
|
||||
* active threads in the system.<br>
|
||||
* Operations defined for the registry:
|
||||
* - <b>First</b>, returns the first, in creation order, active thread
|
||||
* in the system.
|
||||
* - <b>Next</b>, returns the next, in creation order, active thread
|
||||
* in the system.
|
||||
* .
|
||||
* The registry is meant to be mainly a debug feature, as example,
|
||||
* using the registry a debugger can enumerate the active threads
|
||||
* in any given moment or the shell can print the active threads
|
||||
* and their state.<br>
|
||||
* Another possible use is for centralized threads memory management,
|
||||
* terminating threads can pulse an event source and an event handler
|
||||
* can perform a scansion of the registry in order to recover the
|
||||
* memory.<br>
|
||||
* In order to use the threads registry the @p CH_USE_REGISTRY option
|
||||
* must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_REGISTRY
|
||||
|
||||
/**
|
||||
* @brief Returns the first thread in the system.
|
||||
* @details Returns the most ancient thread in the system, usually this is
|
||||
* the main thread unless it terminated.
|
||||
* @note A reference is added to the returned thread in order to make sure
|
||||
* it status is not lost.
|
||||
* @note This function cannot return @p NULL because there is always at
|
||||
* least one thread in the system.
|
||||
*
|
||||
* @return A reference to the first thread.
|
||||
*/
|
||||
Thread *chRegFirstThread(void) {
|
||||
Thread *tp;
|
||||
|
||||
chSysLock();
|
||||
tp = rlist.r_newer;
|
||||
#if CH_USE_DYNAMIC
|
||||
tp->p_refs++;
|
||||
#endif
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the thread next to the specified one.
|
||||
* @details The reference counter of the specified thread is decremented and
|
||||
* the reference counter of the returned thread is incremented.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
* @return A reference to the next thread.
|
||||
* @retval NULL if there is no next thread.
|
||||
*/
|
||||
Thread *chRegNextThread(Thread *tp) {
|
||||
Thread *ntp;
|
||||
|
||||
chSysLock();
|
||||
ntp = tp->p_newer;
|
||||
if (ntp == (Thread *)&rlist)
|
||||
ntp = NULL;
|
||||
#if CH_USE_DYNAMIC
|
||||
else {
|
||||
chDbgAssert(ntp->p_refs < 255, "chRegNextThread(), #1",
|
||||
"too many references");
|
||||
ntp->p_refs++;
|
||||
}
|
||||
#endif
|
||||
chSysUnlock();
|
||||
#if CH_USE_DYNAMIC
|
||||
chThdRelease(tp);
|
||||
#endif
|
||||
return ntp;
|
||||
}
|
||||
|
||||
#endif /* CH_USE_REGISTRY */
|
||||
|
||||
/** @} */
|
||||
282
ChibiOS_2.0.8/os/kernel/src/chschd.c
Normal file
282
ChibiOS_2.0.8/os/kernel/src/chschd.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chschd.c
|
||||
* @brief Scheduler code.
|
||||
*
|
||||
* @addtogroup scheduler
|
||||
* @details This module provides the default portable scheduler code,
|
||||
* scheduler functions can be individually captured by the port
|
||||
* layer in order to provide architecture optimized equivalents.
|
||||
* When a function is captured its default code is not built into
|
||||
* the OS image, the optimized version is included instead.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
/**
|
||||
* @brief Ready list header.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_RLIST_VAR) || defined(__DOXYGEN__)
|
||||
ReadyList rlist;
|
||||
#endif /* !defined(PORT_OPTIMIZED_RLIST_VAR) */
|
||||
|
||||
/**
|
||||
* @brief Scheduler initialization.
|
||||
* @note Internally invoked by the @p chSysInit(), not an API.
|
||||
*/
|
||||
void scheduler_init(void) {
|
||||
|
||||
queue_init(&rlist.r_queue);
|
||||
rlist.r_prio = NOPRIO;
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
#endif
|
||||
#if CH_USE_REGISTRY
|
||||
rlist.r_newer = rlist.r_older = (Thread *)&rlist;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a thread in the Ready List.
|
||||
* @note The function does not reschedule, the @p chSchRescheduleS() should
|
||||
* be called soon after.
|
||||
*
|
||||
* @param[in] tp the Thread to be made ready
|
||||
* @return The Thread pointer.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_READYI) || defined(__DOXYGEN__)
|
||||
#if CH_OPTIMIZE_SPEED
|
||||
/* NOTE: it is inlined in this module only.*/
|
||||
INLINE Thread *chSchReadyI(Thread *tp) {
|
||||
#else
|
||||
Thread *chSchReadyI(Thread *tp) {
|
||||
#endif
|
||||
Thread *cp;
|
||||
|
||||
tp->p_state = THD_STATE_READY;
|
||||
cp = (Thread *)&rlist.r_queue;
|
||||
do {
|
||||
cp = cp->p_next;
|
||||
} while (cp->p_prio >= tp->p_prio);
|
||||
/* Insertion on p_prev.*/
|
||||
tp->p_next = cp;
|
||||
tp->p_prev = cp->p_prev;
|
||||
tp->p_prev->p_next = cp->p_prev = tp;
|
||||
return tp;
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_READYI) */
|
||||
|
||||
/**
|
||||
* @brief Puts the current thread to sleep into the specified state.
|
||||
* @details The thread goes into a sleeping state. The @ref thread_states are
|
||||
* described into @p threads.h.
|
||||
*
|
||||
* @param[in] newstate the new thread state
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_GOSLEEPS) || defined(__DOXYGEN__)
|
||||
void chSchGoSleepS(tstate_t newstate) {
|
||||
Thread *otp;
|
||||
|
||||
(otp = currp)->p_state = newstate;
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
#endif
|
||||
setcurrp(fifo_remove(&rlist.r_queue));
|
||||
currp->p_state = THD_STATE_CURRENT;
|
||||
chDbgTrace(otp);
|
||||
chSysSwitchI(currp, otp);
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_GOSLEEPS) */
|
||||
|
||||
#if !defined(PORT_OPTIMIZED_GOSLEEPTIMEOUTS) || defined(__DOXYGEN__)
|
||||
/*
|
||||
* Timeout wakeup callback.
|
||||
*/
|
||||
static void wakeup(void *p) {
|
||||
Thread *tp = (Thread *)p;
|
||||
|
||||
switch (tp->p_state) {
|
||||
case THD_STATE_READY:
|
||||
/* Handling the special case where the thread has been made ready by
|
||||
another thread with higher priority.*/
|
||||
return;
|
||||
#if CH_USE_SEMAPHORES || (CH_USE_CONDVARS && CH_USE_CONDVARS_TIMEOUT)
|
||||
#if CH_USE_SEMAPHORES
|
||||
case THD_STATE_WTSEM:
|
||||
chSemFastSignalI((Semaphore *)tp->p_u.wtobjp);
|
||||
/* Falls into, intentional. */
|
||||
#endif
|
||||
#if CH_USE_CONDVARS && CH_USE_CONDVARS_TIMEOUT
|
||||
case THD_STATE_WTCOND:
|
||||
#endif
|
||||
/* States requiring dequeuing.*/
|
||||
dequeue(tp);
|
||||
#endif
|
||||
}
|
||||
tp->p_u.rdymsg = RDY_TIMEOUT;
|
||||
chSchReadyI(tp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Puts the current thread to sleep into the specified state with
|
||||
* timeout specification.
|
||||
* @details The thread goes into a sleeping state, if it is not awakened
|
||||
* explicitly within the specified timeout then it is forcibly
|
||||
* awakened with a @p RDY_TIMEOUT low level message. The @ref
|
||||
* thread_states are described into @p threads.h.
|
||||
*
|
||||
* @param[in] newstate the new thread state
|
||||
* @param[in] time the number of ticks before the operation timeouts, the
|
||||
* special values are handled as follow:
|
||||
* - @a TIME_INFINITE the thread enters an infinite sleep
|
||||
* state, this is equivalent to invoking
|
||||
* @p chSchGoSleepS() but, of course, less efficient.
|
||||
* - @a TIME_IMMEDIATE this value is accepted but
|
||||
* interpreted as a normal time specification not as an
|
||||
* immediate timeout specification.
|
||||
* .
|
||||
* @return The wakeup message.
|
||||
* @retval RDY_TIMEOUT if a timeout occurs.
|
||||
*/
|
||||
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
|
||||
|
||||
if (TIME_INFINITE != time) {
|
||||
VirtualTimer vt;
|
||||
|
||||
chVTSetI(&vt, time, wakeup, currp);
|
||||
chSchGoSleepS(newstate);
|
||||
if (chVTIsArmedI(&vt))
|
||||
chVTResetI(&vt);
|
||||
}
|
||||
else
|
||||
chSchGoSleepS(newstate);
|
||||
return currp->p_u.rdymsg;
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_GOSLEEPTIMEOUTS) */
|
||||
|
||||
/**
|
||||
* @brief Wakes up a thread.
|
||||
* @details The thread is inserted into the ready list or immediately made
|
||||
* running depending on its relative priority compared to the current
|
||||
* thread.
|
||||
* @note It is equivalent to a @p chSchReadyI() followed by a
|
||||
* @p chSchRescheduleS() but much more efficient.
|
||||
* @note The function assumes that the current thread has the highest
|
||||
* priority.
|
||||
*
|
||||
* @param[in] ntp the Thread to be made ready
|
||||
* @param[in] msg message to the awakened thread
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_WAKEUPS) || defined(__DOXYGEN__)
|
||||
void chSchWakeupS(Thread *ntp, msg_t msg) {
|
||||
|
||||
ntp->p_u.rdymsg = msg;
|
||||
/* If the waken thread has a not-greater priority than the current
|
||||
one then it is just inserted in the ready list else it made
|
||||
running immediately and the invoking thread goes in the ready
|
||||
list instead.*/
|
||||
if (ntp->p_prio <= currp->p_prio)
|
||||
chSchReadyI(ntp);
|
||||
else {
|
||||
Thread *otp = chSchReadyI(currp);
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
#endif
|
||||
setcurrp(ntp);
|
||||
ntp->p_state = THD_STATE_CURRENT;
|
||||
chDbgTrace(otp);
|
||||
chSysSwitchI(ntp, otp);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_WAKEUPS) */
|
||||
|
||||
/**
|
||||
* @brief Switches to the first thread on the runnable queue.
|
||||
* @note It is intended to be called if @p chSchRescRequiredI() evaluates
|
||||
* to @p TRUE.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_DORESCHEDULEI) || defined(__DOXYGEN__)
|
||||
void chSchDoRescheduleI(void) {
|
||||
Thread *otp;
|
||||
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
rlist.r_preempt = CH_TIME_QUANTUM;
|
||||
#endif
|
||||
otp = currp;
|
||||
/* Picks the first thread from the ready queue and makes it current.*/
|
||||
setcurrp(fifo_remove(&rlist.r_queue));
|
||||
currp->p_state = THD_STATE_CURRENT;
|
||||
chSchReadyI(otp);
|
||||
chDbgTrace(otp);
|
||||
chSysSwitchI(currp, otp);
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_DORESCHEDULEI) */
|
||||
|
||||
/**
|
||||
* @brief Performs a reschedule if a higher priority thread is runnable.
|
||||
* @details If a thread with a higher priority than the current thread is in
|
||||
* the ready list then make the higher priority thread running.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_RESCHEDULES) || defined(__DOXYGEN__)
|
||||
void chSchRescheduleS(void) {
|
||||
|
||||
if (chSchIsRescRequiredI())
|
||||
chSchDoRescheduleI();
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_RESCHEDULES) */
|
||||
|
||||
/**
|
||||
* @brief Evaluates if a reschedule is required.
|
||||
* @details The decision is taken by comparing the relative priorities and
|
||||
* depending on the state of the round robin timeout counter.
|
||||
* @note This function is meant to be used in the timer interrupt handler
|
||||
* where @p chVTDoTickI() is invoked.
|
||||
*
|
||||
* @retval TRUE if there is a thread that should go in running state.
|
||||
* @retval FALSE if a reschedule is not required.
|
||||
*/
|
||||
#if !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI) || defined(__DOXYGEN__)
|
||||
bool_t chSchIsRescRequiredExI(void) {
|
||||
tprio_t p1 = firstprio(&rlist.r_queue);
|
||||
tprio_t p2 = currp->p_prio;
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
/* If the running thread has not reached its time quantum, reschedule only
|
||||
if the first thread on the ready queue has a higher priority.
|
||||
Otherwise, if the running thread has used up its time quantum, reschedule
|
||||
if the first thread on the ready queue has equal or higher priority.*/
|
||||
return rlist.r_preempt ? p1 > p2 : p1 >= p2;
|
||||
#else
|
||||
/* If the round robin preemption feature is not enabled then performs a
|
||||
simpler comparison.*/
|
||||
return p1 > p2;
|
||||
#endif
|
||||
}
|
||||
#endif /* !defined(PORT_OPTIMIZED_ISRESCHREQUIREDEXI) */
|
||||
|
||||
/** @} */
|
||||
291
ChibiOS_2.0.8/os/kernel/src/chsem.c
Normal file
291
ChibiOS_2.0.8/os/kernel/src/chsem.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chsem.c
|
||||
* @brief Semaphores code.
|
||||
*
|
||||
* @addtogroup semaphores
|
||||
* @details Semaphores related APIs and services.
|
||||
*
|
||||
* <h2>Operation mode</h2>
|
||||
* Semaphores are a flexible synchronization primitive, ChibiOS/RT
|
||||
* implements semaphores in their "counting semaphores" variant as
|
||||
* defined by Edsger Dijkstra plus several enhancements like:
|
||||
* - Wait operation with timeout.
|
||||
* - Reset operation.
|
||||
* - Atomic wait+signal operation.
|
||||
* - Return message from the wait operation (OK, RESET, TIMEOUT).
|
||||
* .
|
||||
* The binary semaphores variant can be easily implemented using
|
||||
* counting semaphores.<br>
|
||||
* Operations defined for semaphores:
|
||||
* - <b>Signal</b>: The semaphore counter is increased and if the
|
||||
* result is non-positive then a waiting thread is removed from
|
||||
* the semaphore queue and made ready for execution.
|
||||
* - <b>Wait</b>: The semaphore counter is decreased and if the result
|
||||
* becomes negative the thread is queued in the semaphore and
|
||||
* suspended.
|
||||
* - <b>Reset</b>: The semaphore counter is reset to a non-negative
|
||||
* value and all the threads in the queue are released.
|
||||
* .
|
||||
* Semaphores can be used as guards for mutual exclusion zones
|
||||
* (note that mutexes are recommended for this kind of use) but
|
||||
* also have other uses, queues guards and counters as example.<br>
|
||||
* Semaphores usually use a FIFO queuing strategy but it is possible
|
||||
* to make them order threads by priority by enabling
|
||||
* @p CH_USE_SEMAPHORES_PRIORITY in @p chconf.h.<br>
|
||||
* In order to use the Semaphores APIs the @p CH_USE_SEMAPHORES
|
||||
* option must be enabled in @p chconf.h.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
#if CH_USE_SEMAPHORES
|
||||
|
||||
#if CH_USE_SEMAPHORES_PRIORITY
|
||||
#define sem_insert(tp, qp) prio_insert(tp, qp)
|
||||
#else
|
||||
#define sem_insert(tp, qp) queue_insert(tp, qp)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes a semaphore with the specified counter value.
|
||||
*
|
||||
* @param[out] sp pointer to a @p Semaphore structure
|
||||
* @param[in] n initial value of the semaphore counter. Must be
|
||||
* non-negative.
|
||||
*/
|
||||
void chSemInit(Semaphore *sp, cnt_t n) {
|
||||
|
||||
chDbgCheck((sp != NULL) && (n >= 0), "chSemInit");
|
||||
|
||||
queue_init(&sp->s_queue);
|
||||
sp->s_cnt = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a reset operation on the semaphore.
|
||||
* @note The released threads can recognize they were waked up by a reset
|
||||
* rather than a signal because the @p chSemWait() will return
|
||||
* @p RDY_RESET instead of @p RDY_OK.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @param[in] n the new value of the semaphore counter. The value must
|
||||
* be non-negative.
|
||||
*/
|
||||
void chSemReset(Semaphore *sp, cnt_t n) {
|
||||
|
||||
chSysLock();
|
||||
chSemResetI(sp, n);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a reset operation on the semaphore.
|
||||
* @note The released threads can recognize they were waked up by a reset
|
||||
* rather than a signal because the @p chSemWait() will return
|
||||
* @p RDY_RESET instead of @p RDY_OK.
|
||||
* @note This function does not reschedule.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @param[in] n the new value of the semaphore counter. The value must
|
||||
* be non-negative.
|
||||
*/
|
||||
void chSemResetI(Semaphore *sp, cnt_t n) {
|
||||
cnt_t cnt;
|
||||
|
||||
chDbgCheck((sp != NULL) && (n >= 0), "chSemResetI");
|
||||
|
||||
cnt = sp->s_cnt;
|
||||
sp->s_cnt = n;
|
||||
while (++cnt <= 0)
|
||||
chSchReadyI(lifo_remove(&sp->s_queue))->p_u.rdymsg = RDY_RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a wait operation on a semaphore.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @retval RDY_OK if the semaphore was signaled or not taken.
|
||||
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
|
||||
*/
|
||||
msg_t chSemWait(Semaphore *sp) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
msg = chSemWaitS(sp);
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a wait operation on a semaphore.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @retval RDY_OK if the semaphore was signaled or not taken.
|
||||
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
|
||||
*/
|
||||
msg_t chSemWaitS(Semaphore *sp) {
|
||||
|
||||
chDbgCheck(sp != NULL, "chSemWaitS");
|
||||
|
||||
if (--sp->s_cnt < 0) {
|
||||
currp->p_u.wtobjp = sp;
|
||||
sem_insert(currp, &sp->s_queue);
|
||||
chSchGoSleepS(THD_STATE_WTSEM);
|
||||
return currp->p_u.rdymsg;
|
||||
}
|
||||
return RDY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a wait operation on a semaphore with timeout specification.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @retval RDY_OK if the semaphore was signaled or not taken.
|
||||
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
|
||||
* @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the
|
||||
* specified timeout.
|
||||
*/
|
||||
msg_t chSemWaitTimeout(Semaphore *sp, systime_t time) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
msg = chSemWaitTimeoutS(sp, time);
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a wait operation on a semaphore with timeout specification.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
* @param[in] time the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_IMMEDIATE immediate timeout.
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @retval RDY_OK if the semaphore was signaled or not taken.
|
||||
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
|
||||
* @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the
|
||||
* specified timeout.
|
||||
*/
|
||||
msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) {
|
||||
|
||||
chDbgCheck(sp != NULL, "chSemWaitTimeoutS");
|
||||
|
||||
if (--sp->s_cnt < 0) {
|
||||
if (TIME_IMMEDIATE == time) {
|
||||
sp->s_cnt++;
|
||||
return RDY_TIMEOUT;
|
||||
}
|
||||
currp->p_u.wtobjp = sp;
|
||||
sem_insert(currp, &sp->s_queue);
|
||||
return chSchGoSleepTimeoutS(THD_STATE_WTSEM, time);
|
||||
}
|
||||
return RDY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a signal operation on a semaphore.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
*/
|
||||
void chSemSignal(Semaphore *sp) {
|
||||
|
||||
chDbgCheck(sp != NULL, "chSemSignal");
|
||||
|
||||
chSysLock();
|
||||
if (++sp->s_cnt <= 0)
|
||||
chSchWakeupS(fifo_remove(&sp->s_queue), RDY_OK);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a signal operation on a semaphore.
|
||||
* @note This function does not reschedule.
|
||||
*
|
||||
* @param[in] sp pointer to a @p Semaphore structure
|
||||
*/
|
||||
void chSemSignalI(Semaphore *sp) {
|
||||
|
||||
chDbgCheck(sp != NULL, "chSemSignalI");
|
||||
|
||||
if (++sp->s_cnt <= 0) {
|
||||
/* note, it is done this way in order to allow a tail call on
|
||||
chSchReadyI().*/
|
||||
Thread *tp = fifo_remove(&sp->s_queue);
|
||||
tp->p_u.rdymsg = RDY_OK;
|
||||
chSchReadyI(tp);
|
||||
}
|
||||
}
|
||||
|
||||
#if CH_USE_SEMSW
|
||||
/**
|
||||
* @brief Performs atomic signal and wait operations on two semaphores.
|
||||
* @note The function is available only if the @p CH_USE_SEMSW
|
||||
* option is enabled in @p chconf.h.
|
||||
*
|
||||
* @param[in] sps pointer to a @p Semaphore structure to be signaled
|
||||
* @param[in] spw pointer to a @p Semaphore structure to be wait on
|
||||
* @retval RDY_OK if the semaphore was signaled or not taken.
|
||||
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
|
||||
*/
|
||||
msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw) {
|
||||
msg_t msg;
|
||||
|
||||
chDbgCheck((sps != NULL) && (spw != NULL), "chSemSignalWait");
|
||||
|
||||
chSysLock();
|
||||
if (++sps->s_cnt <= 0)
|
||||
chSchReadyI(fifo_remove(&sps->s_queue))->p_u.rdymsg = RDY_OK;
|
||||
if (--spw->s_cnt < 0) {
|
||||
Thread *ctp = currp;
|
||||
sem_insert(ctp, &spw->s_queue);
|
||||
ctp->p_u.wtobjp = spw;
|
||||
chSchGoSleepS(THD_STATE_WTSEM);
|
||||
msg = ctp->p_u.rdymsg;
|
||||
}
|
||||
else {
|
||||
chSchRescheduleS();
|
||||
msg = RDY_OK;
|
||||
}
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
#endif /* CH_USE_SEMSW */
|
||||
|
||||
#endif /* CH_USE_SEMAPHORES */
|
||||
|
||||
/** @} */
|
||||
145
ChibiOS_2.0.8/os/kernel/src/chsys.c
Normal file
145
ChibiOS_2.0.8/os/kernel/src/chsys.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chsys.c
|
||||
* @brief System related code.
|
||||
*
|
||||
* @addtogroup system
|
||||
* @details System related APIs and services:
|
||||
* - Initialization.
|
||||
* - Locks.
|
||||
* - Interrupt Handling.
|
||||
* - Power Management.
|
||||
* - Abnormal Termination.
|
||||
* .
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
static WORKING_AREA(idle_thread_wa, IDLE_THREAD_STACK_SIZE);
|
||||
|
||||
/**
|
||||
* @brief This function implements the idle thread infinite loop.
|
||||
* @details The function puts the processor in the lowest power mode capable
|
||||
* to serve interrupts.<br>
|
||||
* The priority is internally set to the minimum system value so
|
||||
* that this thread is executed only if there are no other ready
|
||||
* threads in the system.
|
||||
*
|
||||
* @param[in] p the thread parameter, unused in this scenario
|
||||
*/
|
||||
static void idle_thread(void *p) {
|
||||
|
||||
(void)p;
|
||||
while (TRUE) {
|
||||
port_wait_for_interrupt();
|
||||
IDLE_LOOP_HOOK();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ChibiOS/RT initialization.
|
||||
* @details After executing this function the current instructions stream
|
||||
* becomes the main thread.
|
||||
* @note Interrupts should be still disabled when @p chSysInit() is invoked
|
||||
* and are internally enabled.
|
||||
* @note The main thread is created with priority @p NORMALPRIO.
|
||||
*/
|
||||
void chSysInit(void) {
|
||||
static Thread mainthread;
|
||||
|
||||
port_init();
|
||||
scheduler_init();
|
||||
vt_init();
|
||||
#if CH_USE_MEMCORE
|
||||
core_init();
|
||||
#endif
|
||||
#if CH_USE_HEAP
|
||||
heap_init();
|
||||
#endif
|
||||
#if CH_DBG_ENABLE_TRACE
|
||||
trace_init();
|
||||
#endif
|
||||
|
||||
/* Now this instructions flow becomes the main thread.*/
|
||||
setcurrp(init_thread(&mainthread, NORMALPRIO));
|
||||
currp->p_state = THD_STATE_CURRENT;
|
||||
chSysEnable();
|
||||
|
||||
/* This thread has the lowest priority in the system, its role is just to
|
||||
serve interrupts in its context while keeping the lowest energy saving
|
||||
mode compatible with the system status.*/
|
||||
chThdCreateStatic(idle_thread_wa, sizeof(idle_thread_wa), IDLEPRIO,
|
||||
(tfunc_t)idle_thread, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles time ticks for round robin preemption and timer increments.
|
||||
* @details Decrements the remaining time quantum of the running thread
|
||||
* and preempts it when the quantum is used up. Increments system
|
||||
* time and manages the timers.
|
||||
*
|
||||
* @note The frequency of the timer determines the system tick granularity
|
||||
* and, together with the @p CH_TIME_QUANTUM macro, the round robin
|
||||
* interval.
|
||||
*/
|
||||
void chSysTimerHandlerI(void) {
|
||||
|
||||
#if CH_TIME_QUANTUM > 0
|
||||
/* Running thread has not used up quantum yet? */
|
||||
if (rlist.r_preempt > 0)
|
||||
/* Decrement remaining quantum.*/
|
||||
rlist.r_preempt--;
|
||||
#endif
|
||||
#if CH_DBG_THREADS_PROFILING
|
||||
currp->p_time++;
|
||||
#endif
|
||||
chVTDoTickI();
|
||||
}
|
||||
|
||||
#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
|
||||
void chSysLock(void) {
|
||||
|
||||
chDbgAssert(currp->p_locks >= 0,
|
||||
"chSysLock(), #1",
|
||||
"negative nesting counter");
|
||||
if (currp->p_locks++ == 0)
|
||||
port_lock();
|
||||
}
|
||||
|
||||
void chSysUnlock(void) {
|
||||
|
||||
chDbgAssert(currp->p_locks > 0,
|
||||
"chSysUnlock(), #1",
|
||||
"non-positive nesting counter");
|
||||
if (--currp->p_locks == 0)
|
||||
port_unlock();
|
||||
}
|
||||
#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
|
||||
|
||||
/** @} */
|
||||
522
ChibiOS_2.0.8/os/kernel/src/chthreads.c
Normal file
522
ChibiOS_2.0.8/os/kernel/src/chthreads.c
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chthreads.c
|
||||
* @brief Threads code.
|
||||
*
|
||||
* @addtogroup threads
|
||||
* @details Threads related APIs and services.
|
||||
*
|
||||
* <h2>Operation mode</h2>
|
||||
* A thread is an abstraction of an independent instructions flow.
|
||||
* In ChibiOS/RT a thread is represented by a "C" function owning
|
||||
* a processor context, state informations and a dedicated stack
|
||||
* area. In this scenario static variables are shared among all
|
||||
* threads while automatic variables are local to the thread.<br>
|
||||
* Operations defined for threads:
|
||||
* - <b>Init</b>, a thread is prepared and put in the suspended
|
||||
* state.
|
||||
* - <b>Create</b>, a thread is started on the specified thread
|
||||
* function. This operation is available in multiple variants,
|
||||
* both static and dynamic.
|
||||
* - <b>Exit</b>, a thread terminates by returning from its top
|
||||
* level function or invoking a specific API, the thread can
|
||||
* return a value that can be retrieved by other threads.
|
||||
* - <b>Wait</b>, a thread waits for the termination of another
|
||||
* thread and retrieves its return value.
|
||||
* - <b>Resume</b>, a thread created in suspended state is started.
|
||||
* - <b>Sleep</b>, the execution of a thread is suspended for the
|
||||
* specified amount of time or the specified future absolute time
|
||||
* is reached.
|
||||
* - <b>SetPriority</b>, a thread changes its own priority level.
|
||||
* - <b>Yield</b>, a thread voluntarily renounces to its time slot.
|
||||
* .
|
||||
* The threads subsystem is implicitly included in kernel however
|
||||
* some of its part may be excluded by disabling them in @p chconf.h,
|
||||
* see the @p CH_USE_WAITEXIT and @p CH_USE_DYNAMIC configuration
|
||||
* options.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
/**
|
||||
* @brief Initializes a thread structure.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
* @param[in] prio the priority level for the new thread
|
||||
* @return The same thread pointer passed as parameter.
|
||||
*/
|
||||
Thread *init_thread(Thread *tp, tprio_t prio) {
|
||||
|
||||
tp->p_prio = prio;
|
||||
tp->p_state = THD_STATE_SUSPENDED;
|
||||
tp->p_flags = THD_MEM_MODE_STATIC;
|
||||
#if CH_USE_MUTEXES
|
||||
tp->p_realprio = prio;
|
||||
tp->p_mtxlist = NULL;
|
||||
#endif
|
||||
#if CH_USE_EVENTS
|
||||
tp->p_epending = 0;
|
||||
#endif
|
||||
#if CH_USE_NESTED_LOCKS
|
||||
tp->p_locks = 0;
|
||||
#endif
|
||||
#if CH_DBG_THREADS_PROFILING
|
||||
tp->p_time = 0;
|
||||
#endif
|
||||
#if CH_USE_DYNAMIC
|
||||
tp->p_refs = 1;
|
||||
#endif
|
||||
#if CH_USE_WAITEXIT
|
||||
list_init(&tp->p_waiting);
|
||||
#endif
|
||||
#if CH_USE_MESSAGES
|
||||
queue_init(&tp->p_msgqueue);
|
||||
#endif
|
||||
#if CH_USE_REGISTRY
|
||||
REG_INSERT(tp);
|
||||
#endif
|
||||
#if defined(THREAD_EXT_INIT)
|
||||
THREAD_EXT_INIT(tp);
|
||||
#endif
|
||||
return tp;
|
||||
}
|
||||
|
||||
#if CH_DBG_FILL_THREADS
|
||||
static void memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
|
||||
|
||||
while (startp < endp)
|
||||
*startp++ = v;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Creates a new thread into a static memory area.
|
||||
* @details The new thread is initialized but not inserted in the ready list,
|
||||
* the initial state is @p THD_STATE_SUSPENDED.
|
||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||
* returning from its main function.
|
||||
* @note Threads created using this function do not obey to the
|
||||
* @p CH_DBG_FILL_THREADS debug option because it would keep
|
||||
* the kernel locked for too much time.
|
||||
*
|
||||
* @param[out] wsp pointer to a working area dedicated to the thread stack
|
||||
* @param[in] size size of the working area
|
||||
* @param[in] prio the priority level for the new thread
|
||||
* @param[in] pf the thread function
|
||||
* @param[in] arg an argument passed to the thread function. It can be
|
||||
* @p NULL.
|
||||
* @return The pointer to the @p Thread structure allocated for
|
||||
* the thread into the working space area.
|
||||
*/
|
||||
Thread *chThdCreateI(void *wsp, size_t size,
|
||||
tprio_t prio, tfunc_t pf, void *arg) {
|
||||
/* Thread structure is layed out in the lower part of the thread workspace */
|
||||
Thread *tp = wsp;
|
||||
|
||||
chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) &&
|
||||
(prio <= HIGHPRIO) && (pf != NULL),
|
||||
"chThdCreateI");
|
||||
SETUP_CONTEXT(wsp, size, pf, arg);
|
||||
return init_thread(tp, prio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new thread into a static memory area.
|
||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||
* returning from its main function.
|
||||
*
|
||||
* @param[out] wsp pointer to a working area dedicated to the thread stack
|
||||
* @param[in] size size of the working area
|
||||
* @param[in] prio the priority level for the new thread
|
||||
* @param[in] pf the thread function
|
||||
* @param[in] arg an argument passed to the thread function. It can be
|
||||
* @p NULL.
|
||||
* @return The pointer to the @p Thread structure allocated for
|
||||
* the thread into the working space area.
|
||||
*/
|
||||
Thread *chThdCreateStatic(void *wsp, size_t size,
|
||||
tprio_t prio, tfunc_t pf, void *arg) {
|
||||
Thread *tp;
|
||||
|
||||
#if CH_DBG_FILL_THREADS
|
||||
memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE);
|
||||
memfill((uint8_t *)wsp + sizeof(Thread),
|
||||
(uint8_t *)wsp + size, STACK_FILL_VALUE);
|
||||
#endif
|
||||
chSysLock();
|
||||
chSchWakeupS(tp = chThdCreateI(wsp, size, prio, pf, arg), RDY_OK);
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
|
||||
#if CH_USE_DYNAMIC && CH_USE_HEAP
|
||||
/**
|
||||
* @brief Creates a new thread allocating the memory from the heap.
|
||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||
* returning from its main function.
|
||||
* @note The memory allocated for the thread is not released when the thread
|
||||
* terminates but when a @p chThdWait() is performed.
|
||||
* @note The function is available only if the @p CH_USE_DYNAMIC,
|
||||
* @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled
|
||||
* in @p chconf.h.
|
||||
*
|
||||
* @param[in] heapp heap from which allocate the memory or @p 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
|
||||
* @param[in] arg an argument passed to the thread function. It can be
|
||||
* @p NULL.
|
||||
* @return The pointer to the @p Thread structure allocated for
|
||||
* the thread into the working space area.
|
||||
* @retval NULL if the memory cannot be allocated.
|
||||
*/
|
||||
Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size,
|
||||
tprio_t prio, tfunc_t pf, void *arg) {
|
||||
void *wsp;
|
||||
Thread *tp;
|
||||
|
||||
wsp = chHeapAlloc(heapp, size);
|
||||
if (wsp == NULL)
|
||||
return NULL;
|
||||
|
||||
#if CH_DBG_FILL_THREADS
|
||||
memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE);
|
||||
memfill((uint8_t *)wsp + sizeof(Thread),
|
||||
(uint8_t *)wsp + size, STACK_FILL_VALUE);
|
||||
#endif
|
||||
|
||||
chSysLock();
|
||||
tp = chThdCreateI(wsp, size, prio, pf, arg);
|
||||
tp->p_flags = THD_MEM_MODE_HEAP;
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
#endif /* CH_USE_DYNAMIC && CH_USE_HEAP */
|
||||
|
||||
#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS
|
||||
/**
|
||||
* @brief Creates a new thread allocating the memory from the specified
|
||||
* memory pool.
|
||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||
* returning from its main function.
|
||||
* @note The memory allocated for the thread is not released when the thread
|
||||
* terminates but when a @p chThdWait() is performed.
|
||||
* @note The function is available only if the @p CH_USE_DYNAMIC,
|
||||
* @p CH_USE_MEMPOOLS and @p CH_USE_WAITEXIT options are enabled
|
||||
* in @p chconf.h.
|
||||
*
|
||||
* @param[in] mp pointer to the memory pool object
|
||||
* @param[in] prio the priority level for the new thread
|
||||
* @param[in] pf the thread function
|
||||
* @param[in] arg an argument passed to the thread function. It can be
|
||||
* @p NULL.
|
||||
* @return The pointer to the @p Thread structure allocated for
|
||||
* the thread into the working space area.
|
||||
* @retval NULL if the memory pool is empty.
|
||||
*/
|
||||
Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
|
||||
tfunc_t pf, void *arg) {
|
||||
void *wsp;
|
||||
Thread *tp;
|
||||
|
||||
chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool");
|
||||
|
||||
wsp = chPoolAlloc(mp);
|
||||
if (wsp == NULL)
|
||||
return NULL;
|
||||
|
||||
#if CH_DBG_FILL_THREADS
|
||||
memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE);
|
||||
memfill((uint8_t *)wsp + sizeof(Thread),
|
||||
(uint8_t *)wsp + mp->mp_object_size, STACK_FILL_VALUE);
|
||||
#endif
|
||||
|
||||
chSysLock();
|
||||
tp = chThdCreateI(wsp, mp->mp_object_size, prio, pf, arg);
|
||||
tp->p_flags = THD_MEM_MODE_MEMPOOL;
|
||||
tp->p_mpool = mp;
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
#endif /* CH_USE_DYNAMIC && CH_USE_MEMPOOLS */
|
||||
|
||||
/**
|
||||
* @brief Changes the running thread priority level then reschedules if
|
||||
* necessary.
|
||||
* @note The function returns the real thread priority regardless of the
|
||||
* current priority that could be higher than the real priority
|
||||
* because the priority inheritance mechanism.
|
||||
*
|
||||
* @param[in] newprio the new priority level of the running thread
|
||||
* @return The old priority level.
|
||||
*/
|
||||
tprio_t chThdSetPriority(tprio_t newprio) {
|
||||
tprio_t oldprio;
|
||||
|
||||
chDbgCheck((newprio >= LOWPRIO) && (newprio <= HIGHPRIO),
|
||||
"chThdSetPriority");
|
||||
|
||||
chSysLock();
|
||||
#if CH_USE_MUTEXES
|
||||
oldprio = currp->p_realprio;
|
||||
if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio))
|
||||
currp->p_prio = newprio;
|
||||
currp->p_realprio = newprio;
|
||||
#else
|
||||
oldprio = currp->p_prio;
|
||||
currp->p_prio = newprio;
|
||||
#endif
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
return oldprio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes a suspended thread.
|
||||
* @note Use this function to resume threads created with @p chThdInit().
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
* @return The pointer to the thread.
|
||||
*/
|
||||
Thread *chThdResume(Thread *tp) {
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(tp->p_state == THD_STATE_SUSPENDED,
|
||||
"chThdResume(), #1",
|
||||
"thread not in THD_STATE_SUSPENDED state");
|
||||
chSchWakeupS(tp, RDY_OK);
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Requests a thread termination.
|
||||
* @note The thread is not terminated but a termination request is added to
|
||||
* its @p p_flags field. The thread can read this status by
|
||||
* invoking @p chThdShouldTerminate() and then terminate cleanly.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
*/
|
||||
void chThdTerminate(Thread *tp) {
|
||||
|
||||
chSysLock();
|
||||
tp->p_flags |= THD_TERMINATE;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspends the invoking thread for the specified time.
|
||||
*
|
||||
* @param[in] time the delay in system ticks, the special values are
|
||||
* handled as follow:
|
||||
* - @a TIME_INFINITE the thread enters an infinite sleep
|
||||
* state.
|
||||
* - @a TIME_IMMEDIATE this value is accepted but
|
||||
* interpreted as a normal time specification not as an
|
||||
* immediate timeout specification.
|
||||
* .
|
||||
*/
|
||||
void chThdSleep(systime_t time) {
|
||||
|
||||
chDbgCheck(time != TIME_INFINITE, "chThdSleep");
|
||||
|
||||
chSysLock();
|
||||
chThdSleepS(time);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspends the invoking thread until the system time arrives to the
|
||||
* specified value.
|
||||
*
|
||||
* @param[in] time absolute system time
|
||||
*/
|
||||
void chThdSleepUntil(systime_t time) {
|
||||
|
||||
chSysLock();
|
||||
if ((time -= chTimeNow()) > 0)
|
||||
chThdSleepS(time);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Yields the time slot.
|
||||
* @details Yields the CPU control to the next thread in the ready list with
|
||||
* equal priority, if any.
|
||||
*/
|
||||
void chThdYield(void) {
|
||||
|
||||
chSysLock();
|
||||
chSchDoYieldS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminates the current thread by specifying an exit status code.
|
||||
*
|
||||
* @param[in] msg thread exit code. The code can be retrieved by using
|
||||
* @p chThdWait().
|
||||
*/
|
||||
void chThdExit(msg_t msg) {
|
||||
Thread *tp = currp;
|
||||
|
||||
chSysLock();
|
||||
tp->p_u.exitcode = msg;
|
||||
#if defined(THREAD_EXT_EXIT)
|
||||
THREAD_EXT_EXIT(tp);
|
||||
#endif
|
||||
#if CH_USE_WAITEXIT
|
||||
while (notempty(&tp->p_waiting))
|
||||
chSchReadyI(list_remove(&tp->p_waiting));
|
||||
#endif
|
||||
#if CH_USE_REGISTRY
|
||||
/* Static threads are immediately removed from the registry because
|
||||
there is no memory to recover.*/
|
||||
if ((tp->p_flags & THD_MEM_MODE_MASK) == THD_MEM_MODE_STATIC)
|
||||
REG_REMOVE(tp);
|
||||
#endif
|
||||
chSchGoSleepS(THD_STATE_FINAL);
|
||||
}
|
||||
|
||||
#if CH_USE_DYNAMIC || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Adds a reference to a thread object.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
* @return The same thread pointer passed as parameter
|
||||
* representing the new reference.
|
||||
*/
|
||||
Thread *chThdAddRef(Thread *tp) {
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(tp->p_refs < 255, "chThdAddRef(), #1", "too many references");
|
||||
tp->p_refs++;
|
||||
chSysUnlock();
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a reference to a thread object.
|
||||
* @details If the references counter reaches zero <b>and</b> the thread
|
||||
* is in the @p THD_STATE_FINAL state then the thread's memory is
|
||||
* returned to the proper allocator.
|
||||
* @note Static threads are not affected.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
*/
|
||||
void chThdRelease(Thread *tp) {
|
||||
trefs_t refs;
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(tp->p_refs > 0, "chThdRelease(), #1", "not referenced");
|
||||
refs = --tp->p_refs;
|
||||
chSysUnlock();
|
||||
|
||||
/* If the references counter reaches zero and the thread is in its
|
||||
terminated state then the memory can be returned to the proper
|
||||
allocator. Of course static threads are not affected.*/
|
||||
if ((refs == 0) && (tp->p_state == THD_STATE_FINAL)) {
|
||||
switch (tp->p_flags & THD_MEM_MODE_MASK) {
|
||||
#if CH_USE_HEAP
|
||||
case THD_MEM_MODE_HEAP:
|
||||
#if CH_USE_REGISTRY
|
||||
REG_REMOVE(tp);
|
||||
#endif
|
||||
chHeapFree(tp);
|
||||
break;
|
||||
#endif
|
||||
#if CH_USE_MEMPOOLS
|
||||
case THD_MEM_MODE_MEMPOOL:
|
||||
#if CH_USE_REGISTRY
|
||||
REG_REMOVE(tp);
|
||||
#endif
|
||||
chPoolFree(tp->p_mpool, tp);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CH_USE_DYNAMIC */
|
||||
|
||||
#if CH_USE_WAITEXIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Blocks the execution of the invoking thread until the specified
|
||||
* thread terminates then the exit code is returned.
|
||||
* @details This function waits for the specified thread to terminate then
|
||||
* decrements its reference counter, if the counter reaches zero then
|
||||
* the thread working area is returned to the proper allocator.<br>
|
||||
* The memory used by the exited thread is handled in different ways
|
||||
* depending on the API that spawned the thread:
|
||||
* - If the thread was spawned by @p chThdCreateStatic() or by
|
||||
* @p chThdInit() then nothing happens and the thread working area
|
||||
* is not released or modified in any way. This is the default,
|
||||
* totally static, behavior.
|
||||
* - If the thread was spawned by @p chThdCreateFromHeap() then
|
||||
* the working area is returned to the system heap.
|
||||
* - If the thread was spawned by @p chThdCreateFromMemoryPool()
|
||||
* then the working area is returned to the owning memory pool.
|
||||
* .
|
||||
* Please read the @ref article_lifecycle article for more details.
|
||||
* @note After invoking @p chThdWait() the thread pointer becomes invalid
|
||||
* and must not be used as parameter for further system calls.
|
||||
* @note The function is available only if the @p CH_USE_WAITEXIT
|
||||
* option is enabled in @p chconf.h.
|
||||
* @note If @p CH_USE_DYNAMIC is not specified this function just waits for
|
||||
* the thread termination, no memory allocators are involved.
|
||||
*
|
||||
* @param[in] tp pointer to the thread
|
||||
* @return The exit code from the terminated thread.
|
||||
*/
|
||||
msg_t chThdWait(Thread *tp) {
|
||||
msg_t msg;
|
||||
|
||||
chDbgCheck(tp != NULL, "chThdWait");
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(tp != currp, "chThdWait(), #1", "waiting self");
|
||||
#if CH_USE_DYNAMIC
|
||||
chDbgAssert(tp->p_refs > 0, "chThdWait(), #2", "not referenced");
|
||||
#endif
|
||||
if (tp->p_state != THD_STATE_FINAL) {
|
||||
list_insert(currp, &tp->p_waiting);
|
||||
chSchGoSleepS(THD_STATE_WTEXIT);
|
||||
}
|
||||
msg = tp->p_u.exitcode;
|
||||
chSysUnlock();
|
||||
#if CH_USE_DYNAMIC
|
||||
chThdRelease(tp);
|
||||
#endif
|
||||
return msg;
|
||||
}
|
||||
#endif /* CH_USE_WAITEXIT */
|
||||
|
||||
/** @} */
|
||||
129
ChibiOS_2.0.8/os/kernel/src/chvt.c
Normal file
129
ChibiOS_2.0.8/os/kernel/src/chvt.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chvt.c
|
||||
* @brief Time and Virtual Timers related code.
|
||||
*
|
||||
* @addtogroup time
|
||||
* @details Time and Virtual Timers related APIs and services.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
/**
|
||||
* @brief Virtual timers delta list header.
|
||||
*/
|
||||
VTList vtlist;
|
||||
|
||||
/**
|
||||
* @brief Virtual Timers initialization.
|
||||
* @note Internal use only.
|
||||
*/
|
||||
void vt_init(void) {
|
||||
|
||||
vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
|
||||
vtlist.vt_time = (systime_t)-1;
|
||||
vtlist.vt_systime = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a virtual timer.
|
||||
* @note The associated function is invoked by an interrupt handler within
|
||||
* the I-Locked state, see @ref system_states.
|
||||
*
|
||||
* @param[out] vtp the @p VirtualTimer structure pointer
|
||||
* @param[in] time the number of time ticks, the value @p TIME_INFINITE
|
||||
* is notallowed. The value @p TIME_IMMEDIATE is allowed
|
||||
* but interpreted as a normal time specification not as
|
||||
* an immediate timeout specification.
|
||||
* @param[in] vtfunc the timer callback function. After invoking the
|
||||
* callback the timer is disabled and the structure can
|
||||
* be disposed or reused.
|
||||
* @param[in] par a parameter that will be passed to the callback
|
||||
* function
|
||||
*/
|
||||
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
|
||||
VirtualTimer *p;
|
||||
|
||||
chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_INFINITE),
|
||||
"chVTSetI");
|
||||
|
||||
vtp->vt_par = par;
|
||||
vtp->vt_func = vtfunc;
|
||||
p = vtlist.vt_next;
|
||||
while (p->vt_time < time) {
|
||||
time -= p->vt_time;
|
||||
p = p->vt_next;
|
||||
}
|
||||
|
||||
vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
|
||||
vtp->vt_prev->vt_next = p->vt_prev = vtp;
|
||||
vtp->vt_time = time;
|
||||
if (p != (void *)&vtlist)
|
||||
p->vt_time -= time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables a Virtual Timer.
|
||||
* @note The timer MUST be active when this function is invoked.
|
||||
*
|
||||
* @param[in] vtp the @p VirtualTimer structure pointer
|
||||
*/
|
||||
void chVTResetI(VirtualTimer *vtp) {
|
||||
|
||||
chDbgCheck(vtp != NULL, "chVTResetI");
|
||||
chDbgAssert(vtp->vt_func != NULL,
|
||||
"chVTResetI(), #1",
|
||||
"timer not set or already triggered");
|
||||
|
||||
if (vtp->vt_next != (void *)&vtlist)
|
||||
vtp->vt_next->vt_time += vtp->vt_time;
|
||||
vtp->vt_prev->vt_next = vtp->vt_next;
|
||||
vtp->vt_next->vt_prev = vtp->vt_prev;
|
||||
vtp->vt_func = (vtfunc_t)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the current system time is within the specified time
|
||||
* window.
|
||||
* @note When start==end then the function returns always true because the
|
||||
* whole time range is specified.
|
||||
*
|
||||
* @param[in] start the start of the time window (inclusive)
|
||||
* @param[in] end the end of the time window (non inclusive)
|
||||
* @retval TRUE current time within the specified time window.
|
||||
* @retval FALSE current time not within the specified time window.
|
||||
*/
|
||||
bool_t chTimeIsWithin(systime_t start, systime_t end) {
|
||||
|
||||
systime_t time = chTimeNow();
|
||||
return end > start ? (time >= start) && (time < end) :
|
||||
(time >= start) || (time < end);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
494
ChibiOS_2.0.8/os/kernel/templates/chconf.h
Normal file
494
ChibiOS_2.0.8/os/kernel/templates/chconf.h
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/chconf.h
|
||||
* @brief Configuration file template.
|
||||
* @details A copy of this file must be placed in each project directory, it
|
||||
* contains the application specific kernel settings.
|
||||
*
|
||||
* @addtogroup config
|
||||
* @details Kernel related settings and hooks.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHCONF_H_
|
||||
#define _CHCONF_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Kernel parameters. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
/**
|
||||
* @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 preemption for threads with equal priority and the
|
||||
* round robin becomes cooperative. Note that higher priority
|
||||
* threads can still preempt, the kernel is always preemptive.
|
||||
*
|
||||
* @note Disabling the round robin preemption makes the kernel more compact
|
||||
* and generally faster.
|
||||
*/
|
||||
#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
|
||||
#define CH_TIME_QUANTUM 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 T he default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__)
|
||||
#define CH_USE_NESTED_LOCKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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_COREMEM.
|
||||
*/
|
||||
#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
|
||||
#define CH_MEMCORE_SIZE 0
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Performance options. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__)
|
||||
#define CH_OPTIMIZE_SPEED TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 only.
|
||||
*/
|
||||
#if defined(__DOXYGEN__)
|
||||
#define CH_CURRP_REGISTER_CACHE "reg"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Subsystem options. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Threads registry APIs.
|
||||
* @details If enabled then the registry APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_REGISTRY TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_WAITEXIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_SEMAPHORES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Atomic semaphore API.
|
||||
* @details If enabled then the semaphores the @p chSemSignalWait() API
|
||||
* is included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__)
|
||||
#define CH_USE_SEMSW TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_MUTEXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__)
|
||||
#define CH_USE_CONDVARS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define CH_USE_CONDVARS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_EVENTS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define CH_USE_EVENTS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_MESSAGES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define CH_USE_MESSAGES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__)
|
||||
#define CH_USE_QUEUES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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_MEMCORE) || 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__)
|
||||
#define CH_USE_HEAP TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_USE_MEMPOOLS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS.
|
||||
*/
|
||||
#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__)
|
||||
#define CH_USE_DYNAMIC TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Debug options. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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__)
|
||||
#define CH_DBG_ENABLE_TRACE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 or some ports.
|
||||
* @note The default failure mode is to halt the system with the global
|
||||
* @p panic_msg variable set to @p NULL.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
|
||||
#define CH_DBG_ENABLE_STACK_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
/**
|
||||
* @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
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Kernel hooks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @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 threads custom fields here.*/ \
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 threads initialization code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 threads finalization code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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() { \
|
||||
/* Idle loop code here.*/ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Port-specific settings (override port settings defaulted in chcore.h). */
|
||||
/*===========================================================================*/
|
||||
|
||||
#endif /* _CHCONF_H_ */
|
||||
|
||||
/** @} */
|
||||
140
ChibiOS_2.0.8/os/kernel/templates/chcore.c
Normal file
140
ChibiOS_2.0.8/os/kernel/templates/chcore.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/chcore.c
|
||||
* @brief Port related template code.
|
||||
* @details This file is a template of the system driver functions provided by
|
||||
* a port. Some of the following functions may be implemented as
|
||||
* macros in chcore.h if the implementer decides that there is an
|
||||
* advantage in doing so, as example because performance concerns.
|
||||
*
|
||||
* @addtogroup core
|
||||
* @details Non portable code templates.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
/**
|
||||
* @brief Port-related initialization code.
|
||||
* @note This function is usually empty.
|
||||
*/
|
||||
void port_init(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-lock action.
|
||||
* @details Usually this function just disables interrupts but may perform more
|
||||
* actions.
|
||||
*/
|
||||
void port_lock(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-unlock action.
|
||||
* @details Usually this function just disables interrupts but may perform more
|
||||
* actions.
|
||||
*/
|
||||
void port_unlock(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-lock action from an interrupt handler.
|
||||
* @details This function is invoked before invoking I-class APIs from
|
||||
* interrupt handlers. The implementation is architecture dependent,
|
||||
* in its simplest form it is void.
|
||||
*/
|
||||
void port_lock_from_isr(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-unlock action from an interrupt handler.
|
||||
* @details This function is invoked after invoking I-class APIs from interrupt
|
||||
* handlers. The implementation is architecture dependent, in its
|
||||
* simplest form it is void.
|
||||
*/
|
||||
void port_unlock_from_isr(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables all the interrupt sources.
|
||||
* @note Of course non maskable interrupt sources are not included.
|
||||
*/
|
||||
void port_disable(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the interrupt sources below kernel-level priority.
|
||||
* @note Interrupt sources above kernel level remains enabled.
|
||||
*/
|
||||
void port_suspend(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables all the interrupt sources.
|
||||
*/
|
||||
void port_enable(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters an architecture-dependent IRQ-waiting mode.
|
||||
* @details The function is meant to return when an interrupt becomes pending.
|
||||
* The simplest implementation is an empty function or macro but this
|
||||
* would not take advantage of architecture-specific power saving
|
||||
* modes.
|
||||
*/
|
||||
void port_wait_for_interrupt(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Halts the system.
|
||||
* @details This function is invoked by the operating system when an
|
||||
* unrecoverable error is detected (as example because a programming
|
||||
* error in the application code that triggers an assertion while in
|
||||
* debug mode).
|
||||
*/
|
||||
void port_halt(void) {
|
||||
|
||||
port_disable();
|
||||
while (TRUE) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a context switch between two threads.
|
||||
* @details This is the most critical code in any port, this function
|
||||
* is responsible for the context switch between 2 threads.
|
||||
* @note The implementation of this code affects <b>directly</b> the context
|
||||
* switch performance so optimize here as much as you can.
|
||||
*
|
||||
* @param[in] ntp the thread to be switched in
|
||||
* @param[in] otp the thread to be switched out
|
||||
*/
|
||||
void port_switch(Thread *ntp, Thread *otp) {
|
||||
}
|
||||
|
||||
/** @} */
|
||||
185
ChibiOS_2.0.8/os/kernel/templates/chcore.h
Normal file
185
ChibiOS_2.0.8/os/kernel/templates/chcore.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/chcore.h
|
||||
* @brief Port related template macros and structures.
|
||||
* @details This file is a template of the system driver macros provided by
|
||||
* a port.
|
||||
*
|
||||
* @addtogroup core
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHCORE_H_
|
||||
#define _CHCORE_H_
|
||||
|
||||
/**
|
||||
* @brief Unique macro for the implemented architecture.
|
||||
*/
|
||||
#define CH_ARCHITECTURE_XXX
|
||||
|
||||
/**
|
||||
* @brief Name of the implemented architecture.
|
||||
*/
|
||||
#define CH_ARCHITECTURE_NAME ""
|
||||
|
||||
/**
|
||||
* @brief Name of the architecture variant (optional).
|
||||
*/
|
||||
#define CH_ARCHITECTURE_VARIANT_NAME ""
|
||||
|
||||
/**
|
||||
* @brief Base type for stack and memory alignment.
|
||||
*/
|
||||
typedef uint8_t stkalign_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt saved context.
|
||||
* @details This structure represents the stack frame saved during a
|
||||
* preemption-capable interrupt handler.
|
||||
*/
|
||||
struct extctx {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief System saved context.
|
||||
* @details This structure represents the inner stack frame during a context
|
||||
* switching.
|
||||
*/
|
||||
struct intctx {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Platform dependent part of the @p Thread structure.
|
||||
* @details This structure usually contains just the saved stack pointer
|
||||
* defined as a pointer to a @p intctx structure.
|
||||
*/
|
||||
struct context {
|
||||
struct intctx *sp;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Platform dependent part of the @p chThdInit() API.
|
||||
* @details This code usually setup the context switching frame represented
|
||||
* by an @p intctx structure.
|
||||
*/
|
||||
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stack size for the system idle thread.
|
||||
* @details This size depends on the idle thread implementation, usually
|
||||
* the idle thread should take no more space than those reserved
|
||||
* by @p INT_REQUIRED_STACK.
|
||||
*/
|
||||
#ifndef IDLE_THREAD_STACK_SIZE
|
||||
#define IDLE_THREAD_STACK_SIZE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Per-thread stack overhead for interrupts servicing.
|
||||
* @details This constant is used in the calculation of the correct working
|
||||
* area size.
|
||||
* This value can be zero on those architecture where there is a
|
||||
* separate interrupt stack and the stack space between @p intctx and
|
||||
* @p extctx is known to be zero.
|
||||
*/
|
||||
#ifndef INT_REQUIRED_STACK
|
||||
#define INT_REQUIRED_STACK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enforces a correct alignment for a stack area size value.
|
||||
*/
|
||||
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
|
||||
|
||||
/**
|
||||
* @brief Computes the thread working area global size.
|
||||
*/
|
||||
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
|
||||
sizeof(struct intctx) + \
|
||||
sizeof(struct extctx) + \
|
||||
(n) + (INT_REQUIRED_STACK))
|
||||
|
||||
/**
|
||||
* @brief Static working area allocation.
|
||||
* @details This macro is used to allocate a static thread working area
|
||||
* aligned as both position and size.
|
||||
*/
|
||||
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)]
|
||||
|
||||
/**
|
||||
* @brief IRQ prologue code.
|
||||
* @details This macro must be inserted at the start of all IRQ handlers
|
||||
* enabled to invoke system APIs.
|
||||
*/
|
||||
#define PORT_IRQ_PROLOGUE()
|
||||
|
||||
/**
|
||||
* @brief IRQ epilogue code.
|
||||
* @details This macro must be inserted at the end of all IRQ handlers
|
||||
* enabled to invoke system APIs.
|
||||
*/
|
||||
#define PORT_IRQ_EPILOGUE()
|
||||
|
||||
/**
|
||||
* @brief IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define PORT_IRQ_HANDLER(id) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Fast IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
* @note Not all architectures support fast interrupts, in this case this
|
||||
* macro must be omitted.
|
||||
*/
|
||||
#define PORT_FAST_IRQ_HANDLER(id) void id(void)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void port_init(void);
|
||||
void port_lock(void);
|
||||
void port_unlock(void);
|
||||
void port_lock_from_isr(void);
|
||||
void port_unlock_from_isr(void);
|
||||
void port_disable(void);
|
||||
void port_suspend(void);
|
||||
void port_enable(void);
|
||||
void port_wait_for_interrupt(void);
|
||||
void port_halt(void);
|
||||
void port_switch(Thread *ntp, Thread *otp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CHCORE_H_ */
|
||||
|
||||
/** @} */
|
||||
136
ChibiOS_2.0.8/os/kernel/templates/chtypes.h
Normal file
136
ChibiOS_2.0.8/os/kernel/templates/chtypes.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/chtypes.h
|
||||
* @brief System types template.
|
||||
* @details The types defined in this file may change depending on the target
|
||||
* architecture. You may also try to optimize the size of the various
|
||||
* types in order to privilege size or performance, be careful in
|
||||
* doing so.
|
||||
*
|
||||
* @addtogroup types
|
||||
* @details System types and macros.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHTYPES_H_
|
||||
#define _CHTYPES_H_
|
||||
|
||||
#define __need_NULL
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined(_STDINT_H) && !defined(__STDINT_H_)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Boolean, recommended the fastest signed.
|
||||
*/
|
||||
typedef int32_t bool_t;
|
||||
|
||||
/**
|
||||
* @brief Thread mode flags, uint8_t is ok.
|
||||
*/
|
||||
typedef uint8_t tmode_t;
|
||||
|
||||
/**
|
||||
* @brief Thread state, uint8_t is ok.
|
||||
*/
|
||||
typedef uint8_t tstate_t;
|
||||
|
||||
/**
|
||||
* @brief Thread references counter, uint8_t is ok.
|
||||
*/
|
||||
typedef uint8_t trefs_t;
|
||||
|
||||
/**
|
||||
* @brief Priority, use the fastest unsigned type.
|
||||
*/
|
||||
typedef uint32_t tprio_t;
|
||||
|
||||
/**
|
||||
* @brief Message, use signed pointer equivalent.
|
||||
*/
|
||||
typedef int32_t msg_t;
|
||||
|
||||
/**
|
||||
* @brief Event Id, use fastest signed.
|
||||
*/
|
||||
typedef int32_t eventid_t;
|
||||
|
||||
/**
|
||||
* @brief Event Mask, recommended fastest unsigned.
|
||||
*/
|
||||
typedef uint32_t eventmask_t;
|
||||
|
||||
/**
|
||||
* @brief System Time, recommended fastest unsigned.
|
||||
*/
|
||||
typedef uint32_t systime_t;
|
||||
|
||||
/**
|
||||
* @brief Counter, recommended fastest signed.
|
||||
*/
|
||||
typedef int32_t cnt_t;
|
||||
|
||||
/**
|
||||
* @brief Inline function modifier.
|
||||
*/
|
||||
#define INLINE inline
|
||||
|
||||
/**
|
||||
* @brief ROM constant modifier.
|
||||
* @note This is required because some compilers require a custom keyword,
|
||||
* usually this macro is just set to "const" for the GCC compiler.
|
||||
* @note This macro is not used to place constants in different address
|
||||
* spaces (like AVR requires as example) because it is assumed that
|
||||
* a pointer to a ROMCONST constant is compatible with a pointer
|
||||
* to a normal variable. It is just like the "const" keyword but
|
||||
* requires that the constant is placed in ROM if the architecture
|
||||
* supports it.
|
||||
*/
|
||||
#define ROMCONST const
|
||||
|
||||
/**
|
||||
* @brief Packed structure modifier (within).
|
||||
*/
|
||||
#define PACK_STRUCT_STRUCT __attribute__((packed))
|
||||
|
||||
/**
|
||||
* @brief Packed structure modifier (before).
|
||||
*/
|
||||
#define PACK_STRUCT_BEGIN
|
||||
|
||||
/**
|
||||
* @brief Packed structure modifier (after).
|
||||
*/
|
||||
#define PACK_STRUCT_END
|
||||
|
||||
#endif /* _CHTYPES_H_ */
|
||||
|
||||
/** @} */
|
||||
Reference in New Issue
Block a user