git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@5859 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2013-06-16 12:21:30 +00:00
parent 9c9c52f753
commit 0d96f5c78e
32 changed files with 505 additions and 2524 deletions

View File

@ -164,7 +164,7 @@ static msg_t Thread1(void *arg) {
lis302dlWriteRegister(&SPID1, LIS302DL_CTRL_REG3, 0x00);
/* Reader thread loop.*/
time = chTimeNow();
time = chVTGetSystemTime();
while (TRUE) {
int32_t x, y;
unsigned i;

View File

@ -1,210 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 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/>.
*/
/**
* @file fs_fatfs_impl.cpp
* @brief FatFS file system wrapper.
*
* @addtogroup fs_fatfs_wrapper
* @{
*/
#include "ch.hpp"
#include "fs.hpp"
#include "fatfs_fsimpl.hpp"
#include "hal.h"
#define MSG_TERMINATE (msg_t)0
#define ERR_OK (msg_t)0
#define ERR_TERMINATING (msg_t)1
#define ERR_UNKNOWN_MSG (msg_t)2
using namespace chibios_rt;
using namespace chibios_fs;
/**
* @brief FatFS wrapper-related classes and interfaces.
*/
namespace chibios_fatfs {
typedef struct {
uint32_t msg_code;
union {
struct {
};
} op;
} wmsg_t;
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSFileWrapper *
*------------------------------------------------------------------------*/
FatFSFileWrapper::FatFSFileWrapper(void) : fs(NULL) {
}
FatFSFileWrapper::FatFSFileWrapper(FatFSWrapper *fsref) : fs(fsref) {
}
size_t FatFSFileWrapper::write(const uint8_t *bp, size_t n) {
return 0;
}
size_t FatFSFileWrapper::read(uint8_t *bp, size_t n) {
return 0;
}
msg_t FatFSFileWrapper::put(uint8_t b) {
return 0;
}
msg_t FatFSFileWrapper::get(void) {
return 0;
}
uint32_t FatFSFileWrapper::getAndClearLastError(void) {
return 0;
}
fileoffset_t FatFSFileWrapper::getSize(void) {
return 0;
}
fileoffset_t FatFSFileWrapper::getPosition(void) {
return 0;
}
uint32_t FatFSFileWrapper::setPosition(fileoffset_t offset) {
return 0;
}
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSFilesPool *
*------------------------------------------------------------------------*/
FatFSFilesPool::FatFSFilesPool(void) : ObjectsPool<FatFSFileWrapper,
FATFS_MAX_FILES>() {
}
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSServerThread *
*------------------------------------------------------------------------*/
FatFSServerThread::FatFSServerThread(void) :
BaseStaticThread<FATFS_THREAD_STACK_SIZE>() {
}
msg_t FatFSServerThread::main() {
msg_t sts;
setName("fatfs");
/* Synchronous messages processing loop.*/
while (true) {
ThreadReference tr = waitMessage();
msg_t msg = tr.getMessage();
switch (msg) {
case MSG_TERMINATE:
/* The server object is being destroyed, terminating.*/
tr.releaseMessage(ERR_TERMINATING);
return 0;
default:
sts = ERR_UNKNOWN_MSG;
}
tr.releaseMessage(sts);
}
}
void FatFSServerThread::stop(void) {
sendMessage(MSG_TERMINATE);
wait();
}
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSWrapper *
*------------------------------------------------------------------------*/
FatFSWrapper::FatFSWrapper(void) {
}
void FatFSWrapper::mount(void) {
server.start(FATFS_THREAD_PRIORITY);
}
void FatFSWrapper::unmount(void) {
server.stop();
}
uint32_t FatFSWrapper::getAndClearLastError(void) {
return 0;
}
void FatFSWrapper::synchronize(void) {
}
void FatFSWrapper::remove(const char *fname) {
(void)fname;
}
BaseFileStreamInterface *FatFSWrapper::open(const char *fname) {
(void)fname;
return NULL;
}
BaseFileStreamInterface *FatFSWrapper::openForRead(const char *fname) {
(void)fname;
return NULL;
}
BaseFileStreamInterface *FatFSWrapper::openForWrite(const char *fname) {
(void)fname;
return NULL;
}
BaseFileStreamInterface *FatFSWrapper::create(const char *fname) {
(void)fname;
return NULL;
}
void FatFSWrapper::close(BaseFileStreamInterface *file) {
(void)file;
}
}
/** @} */

View File

@ -1,154 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 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/>.
*/
/**
* @file fs_fatfs_impl.hpp
* @brief FatFS file system wrapper header.
*
* @addtogroup cpp_library
* @{
*/
#include "ch.hpp"
#include "fs.hpp"
#ifndef _FS_FATFS_IMPL_HPP_
#define _FS_FATFS_IMPL_HPP_
/**
* @brief Stack size for the internal server thread.
*/
#if !defined(FATFS_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
#define FATFS_THREAD_STACK_SIZE 1024
#endif
/**
* @brief Priority for the internal server thread.
*/
#if !defined(FATFS_THREAD_PRIORITY) || defined(__DOXYGEN__)
#define FATFS_THREAD_PRIORITY NORMALPRIO
#endif
/**
* @brief Maximum number of open files.
*/
#if !defined(FATFS_MAX_FILES) || defined(__DOXYGEN__)
#define FATFS_MAX_FILES 16
#endif
using namespace chibios_rt;
using namespace chibios_fs;
/**
* @brief FatFS wrapper-related classes and interfaces.
*/
namespace chibios_fatfs {
class FatFSWrapper;
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSFileWrapper *
*------------------------------------------------------------------------*/
class FatFSFileWrapper : public BaseFileStreamInterface {
friend class FatFSWrapper;
protected:
FatFSWrapper *fs;
public:
FatFSFileWrapper(void);
FatFSFileWrapper(FatFSWrapper *fsref);
virtual size_t write(const uint8_t *bp, size_t n);
virtual size_t read(uint8_t *bp, size_t n);
virtual msg_t put(uint8_t b);
virtual msg_t get(void);
virtual uint32_t getAndClearLastError(void);
virtual fileoffset_t getSize(void);
virtual fileoffset_t getPosition(void);
virtual uint32_t setPosition(fileoffset_t offset);
};
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSFilesPool *
*------------------------------------------------------------------------*/
/**
* @brief Class of memory pool of @p FatFSFileWrapper objects.
*/
class FatFSFilesPool : public ObjectsPool<FatFSFileWrapper,
FATFS_MAX_FILES> {
public:
FatFSFilesPool(void);
};
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSServerThread *
*------------------------------------------------------------------------*/
/**
* @brief Class of the internal server thread.
*/
class FatFSServerThread : public BaseStaticThread<FATFS_THREAD_STACK_SIZE> {
private:
FatFSFilesPool files;
protected:
virtual msg_t main(void);
public:
FatFSServerThread(void);
virtual void stop(void);
};
/*------------------------------------------------------------------------*
* chibios_fatfs::FatFSWrapper *
*------------------------------------------------------------------------*/
/**
* @brief Class of the FatFS wrapper.
*/
class FatFSWrapper : public chibios_fs::BaseFileSystemInterface {
friend class FatFSFileWrapper;
protected:
FatFSServerThread server;
public:
FatFSWrapper(void);
virtual uint32_t getAndClearLastError(void);
virtual void synchronize(void);
virtual void remove(const char *fname);
virtual BaseFileStreamInterface *open(const char *fname);
virtual BaseFileStreamInterface *openForRead(const char *fname);
virtual BaseFileStreamInterface *openForWrite(const char *fname);
virtual BaseFileStreamInterface *create(const char *fname);
virtual void close(BaseFileStreamInterface *file);
/**
* @brief Mounts the file system.
*/
void mount(void);
/**
* @brief Unmounts the file system.
*/
void unmount(void);
};
}
#endif /* _FS_FATFS_IMPL_HPP_ */
/** @} */

View File

@ -1,198 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 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/>.
*/
/**
* @file fs.hpp
* @brief File System interfaces header.
*
* @addtogroup fs_interface
* @{
*/
#ifndef _FS_HPP_
#define _FS_HPP_
#include "ch.hpp"
/**
* @name Error codes
* @{
*/
/**
* @brief No error return code.
*/
#define FILE_OK 0
/**
* @brief Error code from the file stream methods.
*/
#define FILE_ERROR 0xFFFFFFFFUL
/** @} */
/**
* @brief ChibiOS FS-related interfaces.
*/
namespace chibios_fs {
/**
* @brief File offset type.
*/
typedef uint32_t fileoffset_t;
/*------------------------------------------------------------------------*
* chibios_fs::BaseFileStreamInterface *
*------------------------------------------------------------------------*/
/**
* @brief Interface of an abstract file object.
*/
class BaseFileStreamInterface : public chibios_rt::BaseSequentialStreamInterface {
public:
/**
* @brief Returns an implementation dependent error code.
*
* @return An implementation-dependent error code.
*
* @api
*/
virtual uint32_t getAndClearLastError(void) = 0;
/**
* @brief Returns the current file size.
*
* @return The file size.
* @retval FILE_ERROR if the operation failed.
*
* @api
*/
virtual fileoffset_t getSize(void) = 0;
/**
* @brief Returns the current file pointer position.
*
* @return The current position inside the file.
* @retval FILE_ERROR if the operation failed.
*
* @api
*/
virtual fileoffset_t getPosition(void) = 0;
/**
* @brief sets the current file pointer position.
*
* @param[in] offset new absolute position
* @return The operation status.
* @retval FILE_OK if no error.
* @retval FILE_ERROR if the operation failed.
*
* @api
*/
virtual uint32_t setPosition(fileoffset_t offset) = 0;
};
/*------------------------------------------------------------------------*
* chibios_fs::BaseFileSystemInterface *
*------------------------------------------------------------------------*/
/**
* @brief Interface of an abstract file system object.
* @note The interface only exposes common features, the implementing
* classes can offer an extended interface.
*/
class BaseFileSystemInterface {
public:
/**
* @brief Returns an implementation dependent error code.
*
* @return An implementation-dependent error code.
*
* @api
*/
virtual uint32_t getAndClearLastError(void) = 0;
/**
* @brief Synchronizes caches with media device.
*/
virtual void synchronize(void) = 0;
/**
* @brief Removes a file.
*
* @param[in] fname file name
*
* @api
*/
virtual void remove(const char *fname) = 0;
/**
* @brief Opens a file for read and write.
*
* @param[in] fname file name
* @return An interface of a file object.
* @retval NULL if the operation failed.
*
* @api
*/
virtual BaseFileStreamInterface *open(const char *fname) = 0;
/**
* @brief Opens a file for read only.
*
* @param[in] fname file name
* @return An interface of a file object.
* @retval NULL if the operation failed.
*
* @api
*/
virtual BaseFileStreamInterface *openForRead(const char *fname) = 0;
/**
* @brief Opens a file for write only.
*
* @param[in] fname file name
* @return An interface of a file object.
* @retval NULL if the operation failed.
*
* @api
*/
virtual BaseFileStreamInterface *openForWrite(const char *fname) = 0;
/**
* @brief Creates a file and opens it for write only.
* @details If a file with the same name already exists then it is
* overwritten.
*
* @param[in] fname file name
* @return An interface of a file object.
* @retval NULL if the operation failed.
*
* @api
*/
virtual BaseFileStreamInterface *create(const char *fname) = 0;
/**
* @brief Closes a file.
*
* @api
*/
virtual void close(BaseFileStreamInterface *file) = 0;
};
}
#endif /* _FS_HPP_ */
/** @} */

View File

@ -102,6 +102,7 @@
#include "chconf.h"
#include "chtypes.h"
#include "chdebug.h"
#include "chlists.h"
#include "chcore.h"
#include "chsys.h"
@ -124,7 +125,6 @@
#include "chqueues.h"
#include "chstreams.h"
#include "chfiles.h"
#include "chdebug.h"
#if !defined(__DOXYGEN__)
extern WORKING_AREA(_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE);

View File

@ -20,7 +20,7 @@
/**
* @file chvt.h
* @brief Time macros and structures.
* @brief Time and Virtual Timers module macros and structures.
*
* @addtogroup time
* @{
@ -29,6 +29,63 @@
#ifndef _CHVT_H_
#define _CHVT_H_
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Virtual Timer callback function.
*/
typedef void (*vtfunc_t)(void *);
/**
* @brief Virtual Timer structure type.
*/
typedef struct VirtualTimer VirtualTimer;
/**
* @extends VTList
*
* @brief Virtual Timer descriptor structure.
*/
struct VirtualTimer {
VirtualTimer *vt_next; /**< @brief Next timer in the list. */
VirtualTimer *vt_prev; /**< @brief Previous timer in the list. */
systime_t vt_time; /**< @brief Absolute time. */
vtfunc_t vt_func; /**< @brief Timer callback function
pointer. */
void *vt_par; /**< @brief Timer callback function
parameter. */
};
/**
* @brief Virtual timers list header.
* @note The timers 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 list. */
VirtualTimer *vt_prev; /**< @brief Last timer in the list. */
volatile systime_t vt_time; /**< @brief Current system time. */
} VTList;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @name Time conversion utilities
* @{
@ -73,139 +130,9 @@
((systime_t)((((usec) * CH_FREQUENCY - 1L) / 1000000L) + 1L))
/** @} */
/**
* @brief Virtual Timer callback function.
*/
typedef void (*vtfunc_t)(void *);
/**
* @brief Virtual Timer structure type.
*/
typedef struct VirtualTimer VirtualTimer;
/**
* @extends VTList
*
* @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;
/**
* @name Macro Functions
* @{
*/
/**
* @brief Virtual timers ticker.
* @note The system lock is released before entering the callback and
* re-acquired immediately after. It is callback's responsibility
* to acquire the lock if needed. This is done in order to reduce
* interrupts jitter when many timers are in use.
*
* @iclass
*/
#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; \
chSysUnlockFromIsr(); \
fn(vtp->vt_par); \
chSysLockFromIsr(); \
} \
} \
}
/**
* @brief Returns @p TRUE if the specified timer is armed.
*
* @iclass
*/
#define chVTIsArmedI(vtp) ((vtp)->vt_func != NULL)
/**
* @brief Enables a virtual timer.
* @note The associated function is invoked from interrupt context.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] time the number of ticks before the operation timeouts, the
* special values are handled as follow:
* - @a TIME_INFINITE is allowed but interpreted as a
* normal time specification.
* - @a TIME_IMMEDIATE this value is not allowed.
* .
* @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
*
* @api
*/
#define chVTSet(vtp, time, vtfunc, par) { \
chSysLock(); \
chVTSetI(vtp, time, vtfunc, par); \
chSysUnlock(); \
}
/**
* @brief Disables a Virtual Timer.
* @note The timer is first checked and disabled only if armed.
*
* @param[in] vtp the @p VirtualTimer structure pointer
*
* @api
*/
#define chVTReset(vtp) { \
chSysLock(); \
if (chVTIsArmedI(vtp)) \
chVTResetI(vtp); \
chSysUnlock(); \
}
/**
* @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.
*
* @api
*/
#define chTimeNow() (vtlist.vt_systime)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern VTList vtlist;
@ -216,13 +143,188 @@ extern VTList vtlist;
extern "C" {
#endif
void _vt_init(void);
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par);
bool_t chVTIsSystemTimeWithin(systime_t start, systime_t end);
void chVTSetAbsoluteI(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
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @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.
*
* @return The system time in ticks.
*
* @iclass
*/
static inline systime_t chVTGetSystemTimeI(void) {
chDbgCheckClassI();
return vtlist.vt_time;
}
/**
* @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.
*
* @return The system time in ticks.
*
* @api
*/
static inline systime_t chVTGetSystemTime(void) {
systime_t systime;
chSysLock()
systime = chVTGetSystemTimeI();
chSysUnlock();
return systime;
}
/**
* @brief Initializes a @p VirtualTimer object.
* @note Initializing a timer object is not strictly required because
* the function @p chVTSetI() initializes the object too. This
* function is only useful if you need to perform a @p chVTIsArmed()
* check before calling @p chVTSetI().
*
* @param[out] vtp the @p VirtualTimer structure pointer
*
* @init
*/
static inline void chVTObjectInit(VirtualTimer *vtp) {
vtp->vt_func = NULL;
}
/**
* @brief Returns @p TRUE if the specified timer is armed.
* @pre The timer must have been initialized using @p chVTObjectInit()
* or @p chVTSetI() (or @p chVTSetI() variants).
*
* @param[in] vtp the @p VirtualTimer structure pointer
* @return true if the timer is armed.
*
* @iclass
*/
static inline bool_t chVTIsArmedI(VirtualTimer *vtp) {
chDbgCheckClassI();
return (bool_t)(vtp->vt_func != NULL);
}
/**
* @brief Enables a virtual timer.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] delay the number of ticks before the operation timeouts.
* @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
*
* @iclass
*/
static inline void chVTSetI(VirtualTimer *vtp, systime_t delay,
vtfunc_t vtfunc, void *par) {
chVTSetAbsoluteI(vtp, chVTGetSystemTimeI() + delay, vtfunc, par);
}
/**
* @brief Enables a virtual timer.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] delay the number of ticks before the operation timeouts.
* @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
*
* @api
*/
static inline void chVTSet(VirtualTimer *vtp, systime_t delay,
vtfunc_t vtfunc, void *par) {
chSysLock();
chVTSetI(vtp, delay, vtfunc, par);
chSysUnlock();
}
/**
* @brief Disables a Virtual Timer.
* @pre The timer must be in armed state before calling this function.
*
* @param[in] vtp the @p VirtualTimer structure pointer
*
* @iclass
*/
static inline void chVTDoResetI(VirtualTimer *vtp) {
chDbgCheckClassI();
chDbgCheck(vtp != NULL, "chVTDoResetI");
vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = (vtfunc_t)NULL;
}
/**
* @brief Disables a Virtual Timer.
* @note The timer is first checked and disabled only if armed.
*
* @param[in] vtp the @p VirtualTimer structure pointer
*
* @api
*/
static inline void chVTReset(VirtualTimer *vtp) {
chSysLock();
chVTResetI(vtp);
chSysUnlock();
}
/**
* @brief Virtual timers ticker.
* @note The system lock is released before entering the callback and
* re-acquired immediately after. It is callback's responsibility
* to acquire the lock if needed. This is done in order to reduce
* interrupts jitter when many timers are in use.
*
* @iclass
*/
static inline void chVTDoTickI(void) {
systime_t systime = ++vtlist.vt_time;
chDbgCheckClassI();
if (&vtlist != (VTList *)vtlist.vt_next) {
VirtualTimer *vtp;
while (((VirtualTimer *)&vtlist != (vtp = vtlist.vt_next)) &&
(vtp->vt_time == systime)) {
vtfunc_t fn = vtp->vt_func;
chVTDoResetI(vtp);
chSysUnlockFromIsr();
fn(vtp->vt_par);
chSysLockFromIsr();
}
}
}
#endif /* _CHVT_H_ */
/** @} */

View File

@ -189,7 +189,7 @@ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
chVTSetI(&vt, time, wakeup, currp);
chSchGoSleepS(newstate);
if (chVTIsArmedI(&vt))
chVTResetI(&vt);
chVTDoResetI(&vt);
}
else
chSchGoSleepS(newstate);

View File

@ -302,7 +302,7 @@ void chThdSleep(systime_t time) {
void chThdSleepUntil(systime_t time) {
chSysLock();
if ((time -= chTimeNow()) > 0)
if ((time -= chVTGetSystemTimeI()) > 0)
chThdSleepS(time);
chSysUnlock();
}

View File

@ -20,7 +20,7 @@
/**
* @file chvt.c
* @brief Time and Virtual Timers related code.
* @brief Time and Virtual Timers module code.
*
* @addtogroup time
* @details Time and Virtual Timers related APIs and services.
@ -29,11 +29,35 @@
#include "ch.h"
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/**
* @brief Virtual timers delta list header.
*/
VTList vtlist;
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Virtual Timers initialization.
* @note Internal use only.
@ -43,72 +67,7 @@ VTList vtlist;
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 from interrupt context.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] time the number of ticks before the operation timeouts, the
* special values are handled as follow:
* - @a TIME_INFINITE is allowed but interpreted as a
* normal time specification.
* - @a TIME_IMMEDIATE this value is not allowed.
* .
* @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
*
* @iclass
*/
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
VirtualTimer *p;
chDbgCheckClassI();
chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_IMMEDIATE),
"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
*
* @iclass
*/
void chVTResetI(VirtualTimer *vtp) {
chDbgCheckClassI();
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;
vtlist.vt_time = 0;
}
/**
@ -124,11 +83,74 @@ void chVTResetI(VirtualTimer *vtp) {
*
* @api
*/
bool_t chTimeIsWithin(systime_t start, systime_t end) {
bool_t chVTIsSystemTimeWithin(systime_t start, systime_t end) {
systime_t time = chTimeNow();
systime_t time = chVTGetSystemTime();
return end > start ? (time >= start) && (time < end) :
(time >= start) || (time < end);
}
/**
* @brief Enables a virtual timer.
* @details The timer is enabled and programmed to trigger at the absolute
* system time specified as parameter.
* @note The associated function is invoked from interrupt context.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] time absolute system time
* @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
*
* @iclass
*/
void chVTSetAbsoluteI(VirtualTimer *vtp, systime_t time,
vtfunc_t vtfunc, void *par) {
VirtualTimer *p;
systime_t systime = vtlist.vt_time;
chDbgCheckClassI();
chDbgCheck((vtp != NULL) && (vtfunc != NULL), "chVTSetI");
vtp->vt_par = par;
vtp->vt_func = vtfunc;
vtp->vt_time = time;
if (time <= systime) {
p = vtlist.vt_prev;
while ((p->vt_time <= systime) && (p->vt_time > time))
p = p->vt_prev;
vtp->vt_next = (vtp->vt_prev = p)->vt_next;
vtp->vt_next->vt_prev = p->vt_next = vtp;
}
else {
p = vtlist.vt_next;
while ((p->vt_time > systime) && (p->vt_time < time))
p = p->vt_next;
vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
vtp->vt_prev->vt_next = p->vt_prev = vtp;
}
}
/**
* @brief Disables a Virtual Timer.
* @note The timer is first checked and disabled only if armed.
*
* @param[in] vtp the @p VirtualTimer structure pointer
*
* @iclass
*/
void chVTResetI(VirtualTimer *vtp) {
chDbgCheckClassI();
chDbgCheck(vtp != NULL, "chVTResetI");
if (chVTIsArmedI(vtp)) {
vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = (vtfunc_t)NULL;
}
}
/** @} */

View File

@ -0,0 +1,81 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 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/>.
*/
/**
* @file chXxx.c
* @brief XXX module code.
*
* @addtogroup XXX
* @{
*/
#include "ch.h"
#if CH_USE_XXX || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief XXX Module initialization.
* @note This function is implicitly invoked on system initialization,
* there is no need to explicitly initialize the module.
*
* @notapi
*/
void _xxx_init(void) {
}
/**
* @brief Initializes a @p xxx_t object.
*
* @param[out] xxxp pointer to the @p xxx_t object
*
* @init
*/
void chXxxObjectInit(xxx_t *xxxp) {
}
#endif /* CH_USE_XXX */
/** @} */

View File

@ -0,0 +1,77 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013 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/>.
*/
/**
* @file chXxx.h
* @brief XXX Module macros and structures.
*
* @addtogroup XXX
* @{
*/
#ifndef _CHXXX_H_
#define _CHXXX_H_
#include "ch.h"
#if CH_USE_XXX || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void chXxxInit(void);
void chXxxObjectInit(xxx_t *xxxp);
#ifdef __cplusplus
}
#endif
#endif /* CH_USE_XXX */
#endif /* _CHXXX_H_ */
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/** @} */

View File

@ -92,7 +92,7 @@ namespace chibios_rt {
void Timer::resetI() {
if (chVTIsArmedI(&timer_ref))
chVTResetI(&timer_ref);
chVTDoResetI(&timer_ref);
}
bool Timer::isArmedI(void) {

View File

@ -1,7 +0,0 @@
# FATFS files.
FATFSSRC = ${CHIBIOS}/os/various/fatfs_bindings/fatfs_diskio.c \
${CHIBIOS}/os/various/fatfs_bindings/fatfs_syscall.c \
${CHIBIOS}/ext/fatfs/src/ff.c \
${CHIBIOS}/ext/fatfs/src/option/ccsbcs.c
FATFSINC = ${CHIBIOS}/ext/fatfs/src

View File

@ -1,254 +0,0 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "ch.h"
#include "hal.h"
#include "ffconf.h"
#include "diskio.h"
#if HAL_USE_MMC_SPI && HAL_USE_SDC
#error "cannot specify both MMC_SPI and SDC drivers"
#endif
#if HAL_USE_MMC_SPI
extern MMCDriver MMCD1;
#elif HAL_USE_SDC
extern SDCDriver SDCD1;
#else
#error "MMC_SPI or SDC driver must be specified"
#endif
#if HAL_USE_RTC
#include "chrtclib.h"
extern RTCDriver RTCD1;
#endif
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define MMC 0
#define SDC 0
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
return stat;
#else
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
return stat;
#endif
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
return stat;
#else
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
return stat;
#endif
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcStartSequentialRead(&MMCD1, sector))
return RES_ERROR;
while (count > 0) {
if (mmcSequentialRead(&MMCD1, buff))
return RES_ERROR;
buff += MMCSD_BLOCK_SIZE;
count--;
}
if (mmcStopSequentialRead(&MMCD1))
return RES_ERROR;
return RES_OK;
#else
case SDC:
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcRead(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcIsWriteProtected(&MMCD1))
return RES_WRPRT;
if (mmcStartSequentialWrite(&MMCD1, sector))
return RES_ERROR;
while (count > 0) {
if (mmcSequentialWrite(&MMCD1, buff))
return RES_ERROR;
buff += MMCSD_BLOCK_SIZE;
count--;
}
if (mmcStopSequentialWrite(&MMCD1))
return RES_ERROR;
return RES_OK;
#else
case SDC:
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcWrite(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (drv) {
#if HAL_USE_MMC_SPI
case MMC:
switch (ctrl) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MMCSD_BLOCK_SIZE;
return RES_OK;
#if _USE_ERASE
case CTRL_ERASE_SECTOR:
mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
return RES_OK;
#endif
default:
return RES_PARERR;
}
#else
case SDC:
switch (ctrl) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD *)buff) = mmcsdGetCardCapacity(&SDCD1);
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MMCSD_BLOCK_SIZE;
return RES_OK;
case GET_BLOCK_SIZE:
*((DWORD *)buff) = 256; /* 512b blocks in one erase block */
return RES_OK;
#if _USE_ERASE
case CTRL_ERASE_SECTOR:
sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
return RES_OK;
#endif
default:
return RES_PARERR;
}
#endif
}
return RES_PARERR;
}
DWORD get_fattime(void) {
#if HAL_USE_RTC
return rtcGetTimeFat(&RTCD1);
#else
return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
#endif
}

View File

@ -1,84 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs R0.08b */
/* (C)ChaN, 2011 */
/*------------------------------------------------------------------------*/
#include "ch.h"
#include "ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Static array of Synchronization Objects */
/*------------------------------------------------------------------------*/
static Semaphore ff_sem[_VOLUMES];
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
int ff_cre_syncobj(BYTE vol, _SYNC_t *sobj) {
*sobj = &ff_sem[vol];
chSemInit(*sobj, 1);
return TRUE;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
int ff_del_syncobj(_SYNC_t sobj) {
chSemReset(sobj, 0);
return TRUE;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
int ff_req_grant(_SYNC_t sobj) {
msg_t msg = chSemWaitTimeout(sobj, (systime_t)_FS_TIMEOUT);
return msg == RDY_OK;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
void ff_rel_grant(_SYNC_t sobj) {
chSemSignal(sobj);
}
#endif /* _FS_REENTRANT */
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void *ff_memalloc(UINT size) {
return chHeapAlloc(NULL, size);
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree(void *mblock) {
chHeapFree(mblock);
}
#endif /* _USE_LFN == 3 */

View File

@ -1,6 +0,0 @@
This directory contains the ChibiOS/RT "official" bindings with the FatFS
library by ChaN: http://elm-chan.org
In order to use FatFS within ChibiOS/RT project, unzip FatFS under
./ext/fatfs then include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk
in your makefile.

View File

@ -1,72 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __CC_H__
#define __CC_H__
#include <ch.h>
typedef uint8_t u8_t;
typedef int8_t s8_t;
typedef uint16_t u16_t;
typedef int16_t s16_t;
typedef uint32_t u32_t;
typedef int32_t s32_t;
typedef uint32_t mem_ptr_t;
#define LWIP_PLATFORM_DIAG(x)
#define LWIP_PLATFORM_ASSERT(x) { \
chSysHalt(); \
}
#define BYTE_ORDER LITTLE_ENDIAN
#define LWIP_PROVIDE_ERRNO
#endif /* __CC_H__ */

View File

@ -1,57 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PERF_H__
#define __PERF_H__
#define PERF_START
#define PERF_STOP(x)
#endif /* __PERF_H__ */

View File

@ -1,235 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
// see http://lwip.wikia.com/wiki/Porting_for_an_OS for instructions
#include "ch.h"
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "arch/cc.h"
#include "arch/sys_arch.h"
void sys_init(void) {
}
err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
*sem = chHeapAlloc(NULL, sizeof(Semaphore));
if (*sem == 0) {
SYS_STATS_INC(sem.err);
return ERR_MEM;
}
else {
chSemInit(*sem, (cnt_t)count);
SYS_STATS_INC_USED(sem);
return ERR_OK;
}
}
void sys_sem_free(sys_sem_t *sem) {
chHeapFree(*sem);
*sem = SYS_SEM_NULL;
SYS_STATS_DEC(sem.used);
}
void sys_sem_signal(sys_sem_t *sem) {
chSemSignal(*sem);
}
/* CHIBIOS FIX: specific variant of this call to be called from within
a lock.*/
void sys_sem_signal_S(sys_sem_t *sem) {
chSemSignalI(*sem);
chSchRescheduleS();
}
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
systime_t time, tmo;
chSysLock();
tmo = timeout > 0 ? (systime_t)timeout : TIME_INFINITE;
time = chTimeNow();
if (chSemWaitTimeoutS(*sem, tmo) != RDY_OK)
time = SYS_ARCH_TIMEOUT;
else
time = chTimeNow() - time;
chSysUnlock();
return time;
}
int sys_sem_valid(sys_sem_t *sem) {
return *sem != SYS_SEM_NULL;
}
// typically called within lwIP after freeing a semaphore
// to make sure the pointer is not left pointing to invalid data
void sys_sem_set_invalid(sys_sem_t *sem) {
*sem = SYS_SEM_NULL;
}
err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
*mbox = chHeapAlloc(NULL, sizeof(Mailbox) + sizeof(msg_t) * size);
if (*mbox == 0) {
SYS_STATS_INC(mbox.err);
return ERR_MEM;
}
else {
chMBInit(*mbox, (void *)(((uint8_t *)*mbox) + sizeof(Mailbox)), size);
SYS_STATS_INC(mbox.used);
return ERR_OK;
}
}
void sys_mbox_free(sys_mbox_t *mbox) {
if (chMBGetUsedCountI(*mbox) != 0) {
// If there are messages still present in the mailbox when the mailbox
// is deallocated, it is an indication of a programming error in lwIP
// and the developer should be notified.
SYS_STATS_INC(mbox.err);
chMBReset(*mbox);
}
chHeapFree(*mbox);
*mbox = SYS_MBOX_NULL;
SYS_STATS_DEC(mbox.used);
}
void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
chMBPost(*mbox, (msg_t)msg, TIME_INFINITE);
}
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
if (chMBPost(*mbox, (msg_t)msg, TIME_IMMEDIATE) == RDY_TIMEOUT) {
SYS_STATS_INC(mbox.err);
return ERR_MEM;
}
return ERR_OK;
}
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
systime_t time, tmo;
chSysLock();
tmo = timeout > 0 ? (systime_t)timeout : TIME_INFINITE;
time = chTimeNow();
if (chMBFetchS(*mbox, (msg_t *)msg, tmo) != RDY_OK)
time = SYS_ARCH_TIMEOUT;
else
time = chTimeNow() - time;
chSysUnlock();
return time;
}
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
if (chMBFetch(*mbox, (msg_t *)msg, TIME_IMMEDIATE) == RDY_TIMEOUT)
return SYS_MBOX_EMPTY;
return 0;
}
int sys_mbox_valid(sys_mbox_t *mbox) {
return *mbox != SYS_MBOX_NULL;
}
// typically called within lwIP after freeing an mbox
// to make sure the pointer is not left pointing to invalid data
void sys_mbox_set_invalid(sys_mbox_t *mbox) {
*mbox = SYS_MBOX_NULL;
}
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread,
void *arg, int stacksize, int prio) {
size_t wsz;
void *wsp;
(void)name;
wsz = THD_WA_SIZE(stacksize);
wsp = chCoreAlloc(wsz);
if (wsp == NULL)
return NULL;
return (sys_thread_t)chThdCreateStatic(wsp, wsz, prio, (tfunc_t)thread, arg);
}
sys_prot_t sys_arch_protect(void) {
chSysLock();
return 0;
}
void sys_arch_unprotect(sys_prot_t pval) {
(void)pval;
chSysUnlock();
}
u32_t sys_now(void) {
#if CH_FREQUENCY == 1000
return (u32_t)chTimeNow();
#elif (CH_FREQUENCY / 1000) >= 1 && (CH_FREQUENCY % 1000) == 0
return ((u32_t)chTimeNow() - 1) / (CH_FREQUENCY / 1000) + 1;
#elif (1000 / CH_FREQUENCY) >= 1 && (1000 % CH_FREQUENCY) == 0
return ((u32_t)chTimeNow() - 1) * (1000 / CH_FREQUENCY) + 1;
#else
return (u32_t)(((u64_t)(chTimeNow() - 1) * 1000) / CH_FREQUENCY) + 1;
#endif
}

View File

@ -1,68 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include <ch.h>
#ifndef __SYS_ARCH_H__
#define __SYS_ARCH_H__
typedef Semaphore * sys_sem_t;
typedef Mailbox * sys_mbox_t;
typedef Thread * sys_thread_t;
typedef int sys_prot_t;
#define SYS_MBOX_NULL (Mailbox *)0
#define SYS_THREAD_NULL (Thread *)0
#define SYS_SEM_NULL (Semaphore *)0
/* let sys.h use binary semaphores for mutexes */
#define LWIP_COMPAT_MUTEX 1
#endif /* __SYS_ARCH_H__ */

View File

@ -1,54 +0,0 @@
# List of the required lwIP files.
LWIP = ${CHIBIOS}/ext/lwip
LWBINDSRC = \
$(CHIBIOS)/os/various/lwip_bindings/lwipthread.c \
$(CHIBIOS)/os/various/lwip_bindings/arch/sys_arch.c
LWNETIFSRC = \
${LWIP}/src/netif/etharp.c
LWCORESRC = \
${LWIP}/src/core/dhcp.c \
${LWIP}/src/core/dns.c \
${LWIP}/src/core/init.c \
${LWIP}/src/core/mem.c \
${LWIP}/src/core/memp.c \
${LWIP}/src/core/netif.c \
${LWIP}/src/core/pbuf.c \
${LWIP}/src/core/raw.c \
${LWIP}/src/core/stats.c \
${LWIP}/src/core/sys.c \
${LWIP}/src/core/tcp.c \
${LWIP}/src/core/tcp_in.c \
${LWIP}/src/core/tcp_out.c \
${LWIP}/src/core/udp.c
LWIPV4SRC = \
${LWIP}/src/core/ipv4/autoip.c \
${LWIP}/src/core/ipv4/icmp.c \
${LWIP}/src/core/ipv4/igmp.c \
${LWIP}/src/core/ipv4/inet.c \
${LWIP}/src/core/ipv4/inet_chksum.c \
${LWIP}/src/core/ipv4/ip.c \
${LWIP}/src/core/ipv4/ip_addr.c \
${LWIP}/src/core/ipv4/ip_frag.c \
${LWIP}/src/core/def.c \
${LWIP}/src/core/timers.c
LWAPISRC = \
${LWIP}/src/api/api_lib.c \
${LWIP}/src/api/api_msg.c \
${LWIP}/src/api/err.c \
${LWIP}/src/api/netbuf.c \
${LWIP}/src/api/netdb.c \
${LWIP}/src/api/netifapi.c \
${LWIP}/src/api/sockets.c \
${LWIP}/src/api/tcpip.c
LWSRC = $(LWBINDSRC) $(LWNETIFSRC) $(LWCORESRC) $(LWIPV4SRC) $(LWAPISRC)
LWINC = \
$(CHIBIOS)/os/various/lwip_bindings \
${LWIP}/src/include \
${LWIP}/src/include/ipv4

View File

@ -1,303 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/**
* @file lwipthread.c
* @brief LWIP wrapper thread code.
* @addtogroup LWIP_THREAD
* @{
*/
#include "ch.h"
#include "hal.h"
#include "evtimer.h"
#include "lwipthread.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include <lwip/tcpip.h>
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
#define PERIODIC_TIMER_ID 1
#define FRAME_RECEIVED_ID 2
/**
* Stack area for the LWIP-MAC thread.
*/
WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE);
/*
* Initialization.
*/
static void low_level_init(struct netif *netif) {
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an Ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* Do whatever else is needed to initialize interface. */
}
/*
* Transmits a frame.
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
struct pbuf *q;
MACTransmitDescriptor td;
(void)netif;
if (macWaitTransmitDescriptor(&ETHD1, &td, MS2ST(LWIP_SEND_TIMEOUT)) != RDY_OK)
return ERR_TIMEOUT;
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* Iterates through the pbuf chain. */
for(q = p; q != NULL; q = q->next)
macWriteTransmitDescriptor(&td, (uint8_t *)q->payload, (size_t)q->len);
macReleaseTransmitDescriptor(&td);
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
/*
* Receives a frame.
*/
static struct pbuf *low_level_input(struct netif *netif) {
MACReceiveDescriptor rd;
struct pbuf *p, *q;
u16_t len;
(void)netif;
if (macWaitReceiveDescriptor(&ETHD1, &rd, TIME_IMMEDIATE) == RDY_OK) {
len = (u16_t)rd.size;
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* Iterates through the pbuf chain. */
for(q = p; q != NULL; q = q->next)
macReadReceiveDescriptor(&rd, (uint8_t *)q->payload, (size_t)q->len);
macReleaseReceiveDescriptor(&rd);
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
}
else {
macReleaseReceiveDescriptor(&rd);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
}
return NULL;
}
/*
* Initialization.
*/
static err_t ethernetif_init(struct netif *netif) {
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LWIP_LINK_SPEED);
netif->state = NULL;
netif->name[0] = LWIP_IFNAME0;
netif->name[1] = LWIP_IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
/**
* @brief LWIP handling thread.
*
* @param[in] p pointer to a @p lwipthread_opts structure or @p NULL
* @return The function does not return.
*/
msg_t lwip_thread(void *p) {
EvTimer evt;
EventListener el0, el1;
struct ip_addr ip, gateway, netmask;
static struct netif thisif;
static const MACConfig mac_config = {thisif.hwaddr};
chRegSetThreadName("lwipthread");
/* Initializes the thing.*/
tcpip_init(NULL, NULL);
/* TCP/IP parameters, runtime or compile time.*/
if (p) {
struct lwipthread_opts *opts = p;
unsigned i;
for (i = 0; i < 6; i++)
thisif.hwaddr[i] = opts->macaddress[i];
ip.addr = opts->address;
gateway.addr = opts->gateway;
netmask.addr = opts->netmask;
}
else {
thisif.hwaddr[0] = LWIP_ETHADDR_0;
thisif.hwaddr[1] = LWIP_ETHADDR_1;
thisif.hwaddr[2] = LWIP_ETHADDR_2;
thisif.hwaddr[3] = LWIP_ETHADDR_3;
thisif.hwaddr[4] = LWIP_ETHADDR_4;
thisif.hwaddr[5] = LWIP_ETHADDR_5;
LWIP_IPADDR(&ip);
LWIP_GATEWAY(&gateway);
LWIP_NETMASK(&netmask);
}
macStart(&ETHD1, &mac_config);
netif_add(&thisif, &ip, &netmask, &gateway, NULL, ethernetif_init, tcpip_input);
netif_set_default(&thisif);
netif_set_up(&thisif);
/* Setup event sources.*/
evtInit(&evt, LWIP_LINK_POLL_INTERVAL);
evtStart(&evt);
chEvtRegisterMask(&evt.et_es, &el0, PERIODIC_TIMER_ID);
chEvtRegisterMask(macGetReceiveEventSource(&ETHD1), &el1, FRAME_RECEIVED_ID);
chEvtAddEvents(PERIODIC_TIMER_ID | FRAME_RECEIVED_ID);
/* Goes to the final priority after initialization.*/
chThdSetPriority(LWIP_THREAD_PRIORITY);
while (TRUE) {
eventmask_t mask = chEvtWaitAny(ALL_EVENTS);
if (mask & PERIODIC_TIMER_ID) {
bool_t current_link_status = macPollLinkStatus(&ETHD1);
if (current_link_status != netif_is_link_up(&thisif)) {
if (current_link_status)
tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
&thisif, 0);
else
tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
&thisif, 0);
}
}
if (mask & FRAME_RECEIVED_ID) {
struct pbuf *p;
while ((p = low_level_input(&thisif)) != NULL) {
struct eth_hdr *ethhdr = p->payload;
switch (htons(ethhdr->type)) {
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (thisif.input(p, &thisif) == ERR_OK)
break;
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
default:
pbuf_free(p);
}
}
}
}
return 0;
}
/** @} */

View File

@ -1,131 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file lwipthread.h
* @brief LWIP wrapper thread macros and structures.
* @addtogroup LWIP_THREAD
* @{
*/
#ifndef _LWIPTHREAD_H_
#define _LWIPTHREAD_H_
#include <lwip/opt.h>
/** @brief MAC thread priority.*/
#ifndef LWIP_THREAD_PRIORITY
#define LWIP_THREAD_PRIORITY LOWPRIO
#endif
/** @brief MAC thread stack size. */
#if !defined(LWIP_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
#define LWIP_THREAD_STACK_SIZE 512
#endif
/** @brief Link poll interval. */
#if !defined(LWIP_LINK_POLL_INTERVAL) || defined(__DOXYGEN__)
#define LWIP_LINK_POLL_INTERVAL S2ST(5)
#endif
/** @brief IP Address. */
#if !defined(LWIP_IPADDR) || defined(__DOXYGEN__)
#define LWIP_IPADDR(p) IP4_ADDR(p, 192, 168, 1, 20)
#endif
/** @brief IP Gateway. */
#if !defined(LWIP_GATEWAY) || defined(__DOXYGEN__)
#define LWIP_GATEWAY(p) IP4_ADDR(p, 192, 168, 1, 1)
#endif
/** @brief IP netmask. */
#if !defined(LWIP_NETMASK) || defined(__DOXYGEN__)
#define LWIP_NETMASK(p) IP4_ADDR(p, 255, 255, 255, 0)
#endif
/** @brief Transmission timeout. */
#if !defined(LWIP_SEND_TIMEOUT) || defined(__DOXYGEN__)
#define LWIP_SEND_TIMEOUT 50
#endif
/** @brief Link speed. */
#if !defined(LWIP_LINK_SPEED) || defined(__DOXYGEN__)
#define LWIP_LINK_SPEED 100000000
#endif
/** @brief MAC Address byte 0. */
#if !defined(LWIP_ETHADDR_0) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_0 0xC2
#endif
/** @brief MAC Address byte 1. */
#if !defined(LWIP_ETHADDR_1) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_1 0xAF
#endif
/** @brief MAC Address byte 2. */
#if !defined(LWIP_ETHADDR_2) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_2 0x51
#endif
/** @brief MAC Address byte 3. */
#if !defined(LWIP_ETHADDR_3) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_3 0x03
#endif
/** @brief MAC Address byte 4. */
#if !defined(LWIP_ETHADDR_4) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_4 0xCF
#endif
/** @brief MAC Address byte 5. */
#if !defined(LWIP_ETHADDR_5) || defined(__DOXYGEN__)
#define LWIP_ETHADDR_5 0x46
#endif
/** @brief Interface name byte 0. */
#if !defined(LWIP_IFNAME0) || defined(__DOXYGEN__)
#define LWIP_IFNAME0 'm'
#endif
/** @brief Interface name byte 1. */
#if !defined(LWIP_IFNAME1) || defined(__DOXYGEN__)
#define LWIP_IFNAME1 's'
#endif
/**
* @brief Runtime TCP/IP settings.
*/
struct lwipthread_opts {
uint8_t *macaddress;
uint32_t address;
uint32_t netmask;
uint32_t gateway;
};
extern WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE);
#ifdef __cplusplus
extern "C" {
#endif
msg_t lwip_thread(void *p);
#ifdef __cplusplus
}
#endif
#endif /* _LWIPTHREAD_H_ */
/** @} */

View File

@ -1,6 +0,0 @@
This directory contains the ChibiOS/RT "official" bindings with the lwIP
TCP/IP stack: http://savannah.nongnu.org/projects/lwip
In order to use FatFS within ChibiOS/RT project, unzip FatFS under
./ext/lwip-1.4.0 then include $(CHIBIOS)/os/various/lwip_bindings/lwip.mk
in your makefile.

View File

@ -103,7 +103,7 @@ static void cmd_systime(BaseSequentialStream *chp, int argc, char *argv[]) {
usage(chp, "systime");
return;
}
chprintf(chp, "%lu\r\n", (unsigned long)chTimeNow());
chprintf(chp, "%lu\r\n", (unsigned long)chVTGetSystemTime());
}
/**

View File

@ -1,299 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-*
* @file usb_msc.c
* @brief USB Mass Storage Class code.
*
* @addtogroup USB_MSC
* @{
*/
#include "ch.h"
#include "hal.h"
#include "usb_msc.h"
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
/**
* @brief Zero-filled constant buffer.
*/
static const uint8_t zerobuf[4] = {0, 0, 0, 0};
/**
* @brief Answer to the INQUIRY command.
*/
static const uint8_t scsi_inquiry_data[] = {
0x00, /* Direct Access Device. */
0x80, /* RMB = 1: Removable Medium. */
0x02, /* ISO, ECMA, ANSI = 2. */
0x00, /* UFI response format. */
36 - 4, /* Additional Length. */
0x00,
0x00,
0x00,
/* Vendor Identification */
'C', 'h', 'i', 'b', 'i', 'O', 'S', ' ',
/* Product Identification */
'S', 'D', ' ', 'F', 'l', 'a', 's', 'h',
' ', 'D', 'i', 's', 'k', ' ', ' ', ' ',
/* Product Revision Level */
'1', '.', '0', ' '
};
/**
* @brief Generic buffer.
*/
uint8_t buf[16];
/*===========================================================================*/
/* MMC interface code. */
/*===========================================================================*/
/*===========================================================================*/
/* SCSI emulation code. */
/*===========================================================================*/
static uint8_t scsi_read_format_capacities(uint32_t *nblocks,
uint32_t *secsize) {
*nblocks = 1024;
*secsize = 512;
return 3; /* No Media.*/
}
/*===========================================================================*/
/* Mass Storage Class related code. */
/*===========================================================================*/
/**
* @brief MSC state machine current state.
*/
static mscstate_t msc_state;
/**
* @brief Received CBW.
*/
static msccbw_t CBW;
/**
* @brief CSW to be transmitted.
*/
static msccsw_t CSW;
/**
* @brief MSC state machine initialization.
*
* @param[in] usbp pointer to the @p USBDriver object
*/
static void msc_reset(USBDriver *usbp) {
msc_state = MSC_IDLE;
chSysLockFromIsr();
usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
chSysUnlockFromIsr();
}
static void msc_transmit(USBDriver *usbp, const uint8_t *p, size_t n) {
if (n > CBW.dCBWDataTransferLength)
n = CBW.dCBWDataTransferLength;
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength - (uint32_t)n;
chSysLockFromIsr();
usbStartTransmitI(usbp, MSC_DATA_IN_EP, p, n);
chSysUnlockFromIsr();
}
static void msc_sendstatus(USBDriver *usbp) {
msc_state = MSC_SENDING_CSW;
chSysLockFromIsr();
usbStartTransmitI(usbp, MSC_DATA_IN_EP, (uint8_t *)&CSW, sizeof CSW);
chSysUnlockFromIsr();
}
static bool_t msc_decode(USBDriver *usbp) {
uint32_t nblocks, secsize;
switch (CBW.CBWCB[0]) {
case SCSI_REQUEST_SENSE:
break;
case SCSI_INQUIRY:
msc_transmit(usbp, (uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data);
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
break;
case SCSI_READ_FORMAT_CAPACITIES:
buf[8] = scsi_read_format_capacities(&nblocks, &secsize);
buf[0] = buf[1] = buf[2] = 0;
buf[3] = 8;
buf[4] = (uint8_t)(nblocks >> 24);
buf[5] = (uint8_t)(nblocks >> 16);
buf[6] = (uint8_t)(nblocks >> 8);
buf[7] = (uint8_t)(nblocks >> 0);
buf[9] = (uint8_t)(secsize >> 16);
buf[10] = (uint8_t)(secsize >> 8);
buf[11] = (uint8_t)(secsize >> 0);
msc_transmit(usbp, buf, 12);
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
break;
default:
return TRUE;
}
return FALSE;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Default requests hook.
* @details The application must use this function as callback for the
* messages hook.
* The following requests are emulated:
* - MSC_GET_MAX_LUN_COMMAND.
* - MSC_MASS_STORAGE_RESET_COMMAND.
* .
*
* @param[in] usbp pointer to the @p USBDriver object
* @return The hook status.
* @retval TRUE Message handled internally.
* @retval FALSE Message not handled.
*/
bool_t mscRequestsHook(USBDriver *usbp) {
if ((usbp->setup[0] & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) ==
(USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) {
switch (usbp->setup[1]) {
case MSC_GET_MAX_LUN_COMMAND:
usbSetupTransfer(usbp, (uint8_t *)zerobuf, 1, NULL);
return TRUE;
case MSC_MASS_STORAGE_RESET_COMMAND:
msc_reset(usbp);
usbSetupTransfer(usbp, NULL, 0, NULL);
return TRUE;
default:
return FALSE;
}
}
return FALSE;
}
/**
* @brief Default data transmitted callback.
* @details The application must use this function as callback for the IN
* data endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*/
void mscDataTransmitted(USBDriver *usbp, usbep_t ep) {
switch (msc_state) {
case MSC_DATA_IN:
CSW.dCSWSignature = MSC_CSW_SIGNATURE;
CSW.dCSWTag = CBW.dCBWTag;
chSysLockFromIsr();
usbStartTransmitI(usbp, ep, (uint8_t *)&CSW, sizeof CSW);
chSysUnlockFromIsr();
msc_state = MSC_SENDING_CSW;
break;
case MSC_SENDING_CSW:
chSysLockFromIsr();
usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
chSysUnlockFromIsr();
msc_state = MSC_IDLE;
break;
default:
;
}
}
/**
* @brief Default data received callback.
* @details The application must use this function as callback for the OUT
* data endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*/
void mscDataReceived(USBDriver *usbp, usbep_t ep) {
size_t n;
n = usbGetReceiveTransactionSizeI(usbp, ep);
switch (msc_state) {
case MSC_IDLE:
if ((n != sizeof(msccbw_t)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
goto stall_out; /* 6.6.1 */
/* Decoding SCSI command.*/
if (msc_decode(usbp)) {
if (CBW.dCBWDataTransferLength == 0) {
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0;
msc_sendstatus(usbp);
return;
}
goto stall_both;
}
/* Commands with zero transfer length, 5.1.*/
if (CBW.dCBWDataTransferLength == 0) {
msc_sendstatus(usbp);
return;
}
/* Transfer direction.*/
if (CBW.bmCBWFlags & 0x80) {
/* IN, Device to Host.*/
msc_state = MSC_DATA_IN;
}
else {
/* OUT, Host to Device.*/
msc_state = MSC_DATA_OUT;
}
break;
case MSC_DATA_OUT:
break;
default:
;
}
return;
stall_out:
msc_state = MSC_ERROR;
chSysLockFromIsr();
usbStallReceiveI(usbp, ep);
chSysUnlockFromIsr();
return;
stall_both:
msc_state = MSC_ERROR;
chSysLockFromIsr();
usbStallTransmitI(usbp, ep);
usbStallReceiveI(usbp, ep);
chSysUnlockFromIsr();
return;
}
/** @} */

View File

@ -1,163 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-*
* @file usb_msc.h
* @brief USB Mass Storage Class header.
*
* @addtogroup USB_MSC
* @{
*/
#ifndef _USB_MSC_H_
#define _USB_MSC_H_
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define MSC_CBW_SIGNATURE 0x43425355
#define MSC_CSW_SIGNATURE 0x53425355
#define MSC_GET_MAX_LUN_COMMAND 0xFE
#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
#define MSC_CSW_STATUS_PASSED 0
#define MSC_CSW_STATUS_FAILED 1
#define MSC_CSW_STATUS_PHASE_ERROR 2
#define SCSI_FORMAT_UNIT 0x04
#define SCSI_INQUIRY 0x12
#define SCSI_MODE_SELECT6 0x15
#define SCSI_MODE_SELECT10 0x55
#define SCSI_MODE_SENSE6 0x1A
#define SCSI_MODE_SENSE10 0x5A
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_READ6 0x08
#define SCSI_READ10 0x28
#define SCSI_READ12 0xA8
#define SCSI_READ16 0x88
#define SCSI_READ_CAPACITY10 0x25
#define SCSI_READ_CAPACITY16 0x9E
#define SCSI_REQUEST_SENSE 0x03
#define SCSI_START_STOP_UNIT 0x1B
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_WRITE6 0x0A
#define SCSI_WRITE10 0x2A
#define SCSI_WRITE12 0xAA
#define SCSI_WRITE16 0x8A
#define SCSI_VERIFY10 0x2F
#define SCSI_VERIFY12 0xAF
#define SCSI_VERIFY16 0x8F
#define SCSI_SEND_DIAGNOSTIC 0x1D
#define SCSI_READ_FORMAT_CAPACITIES 0x23
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Endpoint number for bulk IN.
*/
#if !defined(MSC_DATA_IN_EP) || defined(__DOXYGEN__)
#define MSC_DATA_IN_EP 1
#endif
/**
* @brief Endpoint number for bulk OUT.
*/
#if !defined(MSC_DATA_OUT_EP) || defined(__DOXYGEN__)
#define MSC_DATA_OUT_EP 2
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of the MSC possible states.
*/
typedef enum {
MSC_IDLE = 0,
MSC_DATA_OUT,
MSC_DATA_IN,
MSC_SENDING_CSW,
MSC_ERROR
} mscstate_t;
/**
* @brief CBW structure.
*/
struct CBW {
uint32_t dCBWSignature;
uint32_t dCBWTag;
uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags;
uint8_t bCBWLUN;
uint8_t bCBWCBLength;
uint8_t CBWCB[16];
};
/**
* @brief CSW structure.
*/
struct CSW {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
};
/**
* @brief Type of a CBW structure.
*/
typedef struct CBW msccbw_t;
/**
* @brief Type of a CSW structure.
*/
typedef struct CSW msccsw_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
bool_t mscRequestsHook(USBDriver *usbp);
void mscDataTransmitted(USBDriver *usbp, usbep_t ep);
void mscDataReceived(USBDriver *usbp, usbep_t ep);
#ifdef __cplusplus
}
#endif
#endif /* _USB_MSC_H_ */
/** @} */

View File

@ -183,7 +183,7 @@ bool_t _test_assert_sequence(unsigned point, char *expected) {
bool_t _test_assert_time_window(unsigned point, systime_t start, systime_t end) {
return _test_assert(point, chTimeIsWithin(start, end));
return _test_assert(point, chVTIsSystemTimeWithin(start, end));
}
/*
@ -245,7 +245,7 @@ void test_cpu_pulse(unsigned duration) {
systime_t test_wait_tick(void) {
chThdSleep(1);
return chTimeNow();
return chVTGetSystemTime();
}
/*

View File

@ -166,7 +166,7 @@ static void evt2_execute(void) {
* Test on chEvtWaitOne() with wait.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
target_time = chVTGetSystemTime() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread1, chThdSelf());
m = chEvtWaitOne(ALL_EVENTS);
@ -189,7 +189,7 @@ static void evt2_execute(void) {
* Test on chEvtWaitAny() with wait.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
target_time = chVTGetSystemTime() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread1, chThdSelf());
m = chEvtWaitAny(ALL_EVENTS);
@ -207,7 +207,7 @@ static void evt2_execute(void) {
chEvtRegisterMask(&es1, &el1, 1);
chEvtRegisterMask(&es2, &el2, 4);
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
target_time = chVTGetSystemTime() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread2, "A");
m = chEvtWaitAll(5);

View File

@ -191,7 +191,7 @@ static void mtx2_execute(void) {
systime_t time;
test_wait_tick();
time = chTimeNow();
time = chVTGetSystemTime();
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread2H, 0);
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-2, thread2M, 0);
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread2L, 0);
@ -309,7 +309,7 @@ static void mtx3_execute(void) {
systime_t time;
test_wait_tick();
time = chTimeNow();
time = chVTGetSystemTime();
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread3LL, 0);
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread3L, 0);
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread3M, 0);

View File

@ -169,7 +169,7 @@ static void sem2_execute(void) {
* Testing timeout condition.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(5 * 500);
target_time = chVTGetSystemTime() + MS2ST(5 * 500);
for (i = 0; i < 5; i++) {
test_emit_token('A' + i);
msg = chSemWaitTimeout(&sem1, MS2ST(500));

View File

@ -192,22 +192,22 @@ static void thd4_execute(void) {
test_wait_tick();
/* Timeouts in microseconds.*/
time = chTimeNow();
time = chVTGetSystemTime();
chThdSleepMicroseconds(100000);
test_assert_time_window(1, time + US2ST(100000), time + US2ST(100000) + 1);
/* Timeouts in milliseconds.*/
time = chTimeNow();
time = chVTGetSystemTime();
chThdSleepMilliseconds(100);
test_assert_time_window(2, time + MS2ST(100), time + MS2ST(100) + 1);
/* Timeouts in seconds.*/
time = chTimeNow();
time = chVTGetSystemTime();
chThdSleepSeconds(1);
test_assert_time_window(3, time + S2ST(1), time + S2ST(1) + 1);
/* Absolute timelines.*/
time = chTimeNow() + MS2ST(100);
time = chVTGetSystemTime() + MS2ST(100);
chThdSleepUntil(time);
test_assert_time_window(4, time, time + 1);
}