Add software
This commit is contained in:
308
Software/portapack-mayhem/firmware/chibios/os/various/chprintf.c
Normal file
308
Software/portapack-mayhem/firmware/chibios/os/various/chprintf.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Fabio Utzig,
|
||||
chvprintf() added by Brent Roman.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chprintf.c
|
||||
* @brief Mini printf-like functionality.
|
||||
*
|
||||
* @addtogroup chprintf
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "chprintf.h"
|
||||
#include "memstreams.h"
|
||||
|
||||
#define MAX_FILLER 11
|
||||
#define FLOAT_PRECISION 100000
|
||||
|
||||
static char *long_to_string_with_divisor(char *p,
|
||||
long num,
|
||||
unsigned radix,
|
||||
long divisor) {
|
||||
int i;
|
||||
char *q;
|
||||
long l, ll;
|
||||
|
||||
l = num;
|
||||
if (divisor == 0) {
|
||||
ll = num;
|
||||
} else {
|
||||
ll = divisor;
|
||||
}
|
||||
|
||||
q = p + MAX_FILLER;
|
||||
do {
|
||||
i = (int)(l % radix);
|
||||
i += '0';
|
||||
if (i > '9')
|
||||
i += 'A' - '0' - 10;
|
||||
*--q = i;
|
||||
l /= radix;
|
||||
} while ((ll /= radix) != 0);
|
||||
|
||||
i = (int)(p + MAX_FILLER - q);
|
||||
do
|
||||
*p++ = *q++;
|
||||
while (--i);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *ltoa(char *p, long num, unsigned radix) {
|
||||
|
||||
return long_to_string_with_divisor(p, num, radix, 0);
|
||||
}
|
||||
|
||||
#if CHPRINTF_USE_FLOAT
|
||||
static char *ftoa(char *p, double num) {
|
||||
long l;
|
||||
unsigned long precision = FLOAT_PRECISION;
|
||||
|
||||
l = (long)num;
|
||||
p = long_to_string_with_divisor(p, l, 10, 0);
|
||||
*p++ = '.';
|
||||
l = (long)((num - l) * precision);
|
||||
return long_to_string_with_divisor(p, l, 10, precision / 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System formatted output function.
|
||||
* @details This function implements a minimal @p vprintf()-like functionality
|
||||
* with output on a @p BaseSequentialStream.
|
||||
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
|
||||
* The following parameter types (p) are supported:
|
||||
* - <b>x</b> hexadecimal integer.
|
||||
* - <b>X</b> hexadecimal long.
|
||||
* - <b>o</b> octal integer.
|
||||
* - <b>O</b> octal long.
|
||||
* - <b>d</b> decimal signed integer.
|
||||
* - <b>D</b> decimal signed long.
|
||||
* - <b>u</b> decimal unsigned integer.
|
||||
* - <b>U</b> decimal unsigned long.
|
||||
* - <b>c</b> character.
|
||||
* - <b>s</b> string.
|
||||
* .
|
||||
*
|
||||
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
|
||||
* @param[in] fmt formatting string
|
||||
* @param[in] ap list of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
|
||||
char *p, *s, c, filler;
|
||||
int i, precision, width;
|
||||
bool_t is_long, left_align;
|
||||
long l;
|
||||
#if CHPRINTF_USE_FLOAT
|
||||
float f;
|
||||
char tmpbuf[2*MAX_FILLER + 1];
|
||||
#else
|
||||
char tmpbuf[MAX_FILLER + 1];
|
||||
#endif
|
||||
|
||||
while (TRUE) {
|
||||
c = *fmt++;
|
||||
if (c == 0)
|
||||
return;
|
||||
if (c != '%') {
|
||||
chSequentialStreamPut(chp, (uint8_t)c);
|
||||
continue;
|
||||
}
|
||||
p = tmpbuf;
|
||||
s = tmpbuf;
|
||||
left_align = FALSE;
|
||||
if (*fmt == '-') {
|
||||
fmt++;
|
||||
left_align = TRUE;
|
||||
}
|
||||
filler = ' ';
|
||||
if ((*fmt == '.') || (*fmt == '0')) {
|
||||
fmt++;
|
||||
filler = '0';
|
||||
}
|
||||
width = 0;
|
||||
while (TRUE) {
|
||||
c = *fmt++;
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c == '*')
|
||||
c = va_arg(ap, int);
|
||||
else
|
||||
break;
|
||||
width = width * 10 + c;
|
||||
}
|
||||
precision = 0;
|
||||
if (c == '.') {
|
||||
while (TRUE) {
|
||||
c = *fmt++;
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c == '*')
|
||||
c = va_arg(ap, int);
|
||||
else
|
||||
break;
|
||||
precision *= 10;
|
||||
precision += c;
|
||||
}
|
||||
}
|
||||
/* Long modifier.*/
|
||||
if (c == 'l' || c == 'L') {
|
||||
is_long = TRUE;
|
||||
if (*fmt)
|
||||
c = *fmt++;
|
||||
}
|
||||
else
|
||||
is_long = (c >= 'A') && (c <= 'Z');
|
||||
|
||||
/* Command decoding.*/
|
||||
switch (c) {
|
||||
case 'c':
|
||||
filler = ' ';
|
||||
*p++ = va_arg(ap, int);
|
||||
break;
|
||||
case 's':
|
||||
filler = ' ';
|
||||
if ((s = va_arg(ap, char *)) == 0)
|
||||
s = "(null)";
|
||||
if (precision == 0)
|
||||
precision = 32767;
|
||||
for (p = s; *p && (--precision >= 0); p++)
|
||||
;
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
case 'I':
|
||||
case 'i':
|
||||
if (is_long)
|
||||
l = va_arg(ap, long);
|
||||
else
|
||||
l = va_arg(ap, int);
|
||||
if (l < 0) {
|
||||
*p++ = '-';
|
||||
l = -l;
|
||||
}
|
||||
p = ltoa(p, l, 10);
|
||||
break;
|
||||
#if CHPRINTF_USE_FLOAT
|
||||
case 'f':
|
||||
f = (float) va_arg(ap, double);
|
||||
if (f < 0) {
|
||||
*p++ = '-';
|
||||
f = -f;
|
||||
}
|
||||
p = ftoa(p, f);
|
||||
break;
|
||||
#endif
|
||||
case 'X':
|
||||
case 'x':
|
||||
c = 16;
|
||||
goto unsigned_common;
|
||||
case 'U':
|
||||
case 'u':
|
||||
c = 10;
|
||||
goto unsigned_common;
|
||||
case 'O':
|
||||
case 'o':
|
||||
c = 8;
|
||||
unsigned_common:
|
||||
if (is_long)
|
||||
l = va_arg(ap, unsigned long);
|
||||
else
|
||||
l = va_arg(ap, unsigned int);
|
||||
p = ltoa(p, l, c);
|
||||
break;
|
||||
default:
|
||||
*p++ = c;
|
||||
break;
|
||||
}
|
||||
i = (int)(p - s);
|
||||
if ((width -= i) < 0)
|
||||
width = 0;
|
||||
if (left_align == FALSE)
|
||||
width = -width;
|
||||
if (width < 0) {
|
||||
if (*s == '-' && filler == '0') {
|
||||
chSequentialStreamPut(chp, (uint8_t)*s++);
|
||||
i--;
|
||||
}
|
||||
do {
|
||||
chSequentialStreamPut(chp, (uint8_t)filler);
|
||||
} while (++width != 0);
|
||||
}
|
||||
while (--i >= 0)
|
||||
chSequentialStreamPut(chp, (uint8_t)*s++);
|
||||
|
||||
while (width) {
|
||||
chSequentialStreamPut(chp, (uint8_t)filler);
|
||||
width--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System formatted output function.
|
||||
* @details This function implements a minimal @p vprintf()-like functionality
|
||||
* with output on a @p BaseSequentialStream.
|
||||
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
|
||||
* The following parameter types (p) are supported:
|
||||
* - <b>x</b> hexadecimal integer.
|
||||
* - <b>X</b> hexadecimal long.
|
||||
* - <b>o</b> octal integer.
|
||||
* - <b>O</b> octal long.
|
||||
* - <b>d</b> decimal signed integer.
|
||||
* - <b>D</b> decimal signed long.
|
||||
* - <b>u</b> decimal unsigned integer.
|
||||
* - <b>U</b> decimal unsigned long.
|
||||
* - <b>c</b> character.
|
||||
* - <b>s</b> string.
|
||||
* .
|
||||
*
|
||||
* @param[in] str pointer to a buffer
|
||||
* @param[in] size maximum size of the buffer
|
||||
* @param[in] fmt formatting string
|
||||
* @return The size of the generated string.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
int chsnprintf(char *str, size_t size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
MemoryStream ms;
|
||||
BaseSequentialStream *chp;
|
||||
|
||||
/* Memory stream object to be used as a string writer, reserving one
|
||||
byte for the final zero.*/
|
||||
msObjectInit(&ms, (uint8_t *)str, size - 1, 0);
|
||||
|
||||
/* Performing the print operation using the common code.*/
|
||||
chp = (BaseSequentialStream *)&ms;
|
||||
va_start(ap, fmt);
|
||||
chvprintf(chp, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Final zero and size return.*/
|
||||
str[ms.eos] = 0;
|
||||
return ms.eos;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
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 chprintf.h
|
||||
* @brief Mini printf-like functionality.
|
||||
*
|
||||
* @addtogroup chprintf
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CHPRINTF_H_
|
||||
#define _CHPRINTF_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* @brief Float type support.
|
||||
*/
|
||||
#if !defined(CHPRINTF_USE_FLOAT) || defined(__DOXYGEN__)
|
||||
#define CHPRINTF_USE_FLOAT FALSE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap);
|
||||
int chsnprintf(char *str, size_t size, const char *fmt, ...);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System formatted output function.
|
||||
* @details This function implements a minimal @p printf() like functionality
|
||||
* with output on a @p BaseSequentialStream.
|
||||
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
|
||||
* The following parameter types (p) are supported:
|
||||
* - <b>x</b> hexadecimal integer.
|
||||
* - <b>X</b> hexadecimal long.
|
||||
* - <b>o</b> octal integer.
|
||||
* - <b>O</b> octal long.
|
||||
* - <b>d</b> decimal signed integer.
|
||||
* - <b>D</b> decimal signed long.
|
||||
* - <b>u</b> decimal unsigned integer.
|
||||
* - <b>U</b> decimal unsigned long.
|
||||
* - <b>c</b> character.
|
||||
* - <b>s</b> string.
|
||||
* .
|
||||
*
|
||||
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
|
||||
* @param[in] fmt formatting string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
static INLINE void chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
chvprintf(chp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#endif /* _CHPRINTF_H_ */
|
||||
|
||||
/** @} */
|
364
Software/portapack-mayhem/firmware/chibios/os/various/chrtclib.c
Normal file
364
Software/portapack-mayhem/firmware/chibios/os/various/chrtclib.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chrtclib.c
|
||||
* @brief RTC time conversion utilities code.
|
||||
*
|
||||
* @addtogroup chrtclib
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "chrtclib.h"
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
#if (defined(STM32F4XX) || defined(STM32F2XX) || defined(STM32L1XX) || \
|
||||
defined(STM32F30X) || defined(STM32F37X) || \
|
||||
defined(STM32F1XX) || defined(STM32F10X_MD) || defined(STM32F10X_LD) || \
|
||||
defined(STM32F10X_HD) || defined(STM32F10X_CL) || defined(STM32F0XX) || \
|
||||
defined(LPC122X) || defined(__DOXYGEN__))
|
||||
#if STM32_RTC_IS_CALENDAR
|
||||
/**
|
||||
* @brief Converts from STM32 BCD to canonicalized time format.
|
||||
*
|
||||
* @param[out] timp pointer to a @p tm structure as defined in time.h
|
||||
* @param[in] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static void stm32_rtc_bcd2tm(struct tm *timp, RTCTime *timespec) {
|
||||
uint32_t tv_time = timespec->tv_time;
|
||||
uint32_t tv_date = timespec->tv_date;
|
||||
|
||||
#if CH_DBG_ENABLE_CHECKS
|
||||
timp->tm_isdst = 0;
|
||||
timp->tm_wday = 0;
|
||||
timp->tm_mday = 0;
|
||||
timp->tm_yday = 0;
|
||||
timp->tm_mon = 0;
|
||||
timp->tm_year = 0;
|
||||
timp->tm_sec = 0;
|
||||
timp->tm_min = 0;
|
||||
timp->tm_hour = 0;
|
||||
#endif
|
||||
|
||||
timp->tm_isdst = -1;
|
||||
|
||||
timp->tm_wday = (tv_date & RTC_DR_WDU) >> RTC_DR_WDU_OFFSET;
|
||||
if (timp->tm_wday == 7)
|
||||
timp->tm_wday = 0;
|
||||
|
||||
timp->tm_mday = (tv_date & RTC_DR_DU) >> RTC_DR_DU_OFFSET;
|
||||
timp->tm_mday += ((tv_date & RTC_DR_DT) >> RTC_DR_DT_OFFSET) * 10;
|
||||
|
||||
timp->tm_mon = (tv_date & RTC_DR_MU) >> RTC_DR_MU_OFFSET;
|
||||
timp->tm_mon += ((tv_date & RTC_DR_MT) >> RTC_DR_MT_OFFSET) * 10;
|
||||
timp->tm_mon -= 1;
|
||||
|
||||
timp->tm_year = (tv_date & RTC_DR_YU) >> RTC_DR_YU_OFFSET;
|
||||
timp->tm_year += ((tv_date & RTC_DR_YT) >> RTC_DR_YT_OFFSET) * 10;
|
||||
timp->tm_year += 2000 - 1900;
|
||||
|
||||
timp->tm_sec = (tv_time & RTC_TR_SU) >> RTC_TR_SU_OFFSET;
|
||||
timp->tm_sec += ((tv_time & RTC_TR_ST) >> RTC_TR_ST_OFFSET) * 10;
|
||||
|
||||
timp->tm_min = (tv_time & RTC_TR_MNU) >> RTC_TR_MNU_OFFSET;
|
||||
timp->tm_min += ((tv_time & RTC_TR_MNT) >> RTC_TR_MNT_OFFSET) * 10;
|
||||
|
||||
timp->tm_hour = (tv_time & RTC_TR_HU) >> RTC_TR_HU_OFFSET;
|
||||
timp->tm_hour += ((tv_time & RTC_TR_HT) >> RTC_TR_HT_OFFSET) * 10;
|
||||
timp->tm_hour += 12 * ((tv_time & RTC_TR_PM) >> RTC_TR_PM_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts from canonicalized to STM32 BCD time format.
|
||||
*
|
||||
* @param[in] timp pointer to a @p tm structure as defined in time.h
|
||||
* @param[out] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static void stm32_rtc_tm2bcd(struct tm *timp, RTCTime *timespec) {
|
||||
uint32_t v = 0;
|
||||
|
||||
timespec->tv_date = 0;
|
||||
timespec->tv_time = 0;
|
||||
|
||||
v = timp->tm_year - 100;
|
||||
timespec->tv_date |= ((v / 10) << RTC_DR_YT_OFFSET) & RTC_DR_YT;
|
||||
timespec->tv_date |= (v % 10) << RTC_DR_YU_OFFSET;
|
||||
|
||||
if (timp->tm_wday == 0)
|
||||
v = 7;
|
||||
else
|
||||
v = timp->tm_wday;
|
||||
timespec->tv_date |= (v << RTC_DR_WDU_OFFSET) & RTC_DR_WDU;
|
||||
|
||||
v = timp->tm_mon + 1;
|
||||
timespec->tv_date |= ((v / 10) << RTC_DR_MT_OFFSET) & RTC_DR_MT;
|
||||
timespec->tv_date |= (v % 10) << RTC_DR_MU_OFFSET;
|
||||
|
||||
v = timp->tm_mday;
|
||||
timespec->tv_date |= ((v / 10) << RTC_DR_DT_OFFSET) & RTC_DR_DT;
|
||||
timespec->tv_date |= (v % 10) << RTC_DR_DU_OFFSET;
|
||||
|
||||
v = timp->tm_hour;
|
||||
timespec->tv_time |= ((v / 10) << RTC_TR_HT_OFFSET) & RTC_TR_HT;
|
||||
timespec->tv_time |= (v % 10) << RTC_TR_HU_OFFSET;
|
||||
|
||||
v = timp->tm_min;
|
||||
timespec->tv_time |= ((v / 10) << RTC_TR_MNT_OFFSET) & RTC_TR_MNT;
|
||||
timespec->tv_time |= (v % 10) << RTC_TR_MNU_OFFSET;
|
||||
|
||||
v = timp->tm_sec;
|
||||
timespec->tv_time |= ((v / 10) << RTC_TR_ST_OFFSET) & RTC_TR_ST;
|
||||
timespec->tv_time |= (v % 10) << RTC_TR_SU_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to canonicalized format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timp pointer to a @p tm structure as defined in time.h
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
RTCTime timespec = {0,0,FALSE,0};
|
||||
#else
|
||||
RTCTime timespec = {0,0,FALSE};
|
||||
#endif
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
stm32_rtc_bcd2tm(timp, ×pec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets RTC time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timp pointer to a @p tm structure as defined in time.h
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
RTCTime timespec = {0,0,FALSE,0};
|
||||
#else
|
||||
RTCTime timespec = {0,0,FALSE};
|
||||
#endif
|
||||
|
||||
stm32_rtc_tm2bcd(timp, ×pec);
|
||||
rtcSetTime(rtcp, ×pec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to unix format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return Unix time value in seconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
time_t rtcGetTimeUnixSec(RTCDriver *rtcp) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
RTCTime timespec = {0,0,FALSE,0};
|
||||
#else
|
||||
RTCTime timespec = {0,0,FALSE};
|
||||
#endif
|
||||
struct tm timp;
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
stm32_rtc_bcd2tm(&timp, ×pec);
|
||||
|
||||
return mktime(&timp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets RTC time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] tv_sec time specification
|
||||
* @return Unix time value in seconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
RTCTime timespec = {0,0,FALSE,0};
|
||||
#else
|
||||
RTCTime timespec = {0,0,FALSE};
|
||||
#endif
|
||||
struct tm timp;
|
||||
|
||||
localtime_r(&tv_sec, &timp);
|
||||
stm32_rtc_tm2bcd(&timp, ×pec);
|
||||
rtcSetTime(rtcp, ×pec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to unix format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return Unix time value in microseconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
uint64_t result = 0;
|
||||
RTCTime timespec = {0,0,FALSE,0};
|
||||
struct tm timp;
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
stm32_rtc_bcd2tm(&timp, ×pec);
|
||||
|
||||
result = (uint64_t)mktime(&timp) * 1000000;
|
||||
return result + timespec.tv_msec * 1000;
|
||||
#else
|
||||
return (uint64_t)rtcGetTimeUnixSec(rtcp) * 1000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* STM32_RTC_IS_CALENDAR */
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to canonicalized format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timp pointer to a @p tm structure as defined in time.h
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp) {
|
||||
RTCTime timespec = {0};
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
localtime_r((time_t *)&(timespec.tv_sec), timp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets RTC time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timp pointer to a @p tm structure as defined in time.h
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp) {
|
||||
RTCTime timespec = {0};
|
||||
|
||||
timespec.tv_sec = mktime(timp);
|
||||
#if !defined(LPC122X)
|
||||
timespec.tv_msec = 0;
|
||||
#endif
|
||||
rtcSetTime(rtcp, ×pec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to unix format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return Unix time value in seconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
time_t rtcGetTimeUnixSec(RTCDriver *rtcp) {
|
||||
RTCTime timespec = {0};
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
return timespec.tv_sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets RTC time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] tv_sec time specification
|
||||
* @return Unix time value in seconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec) {
|
||||
RTCTime timespec = {0};
|
||||
|
||||
timespec.tv_sec = tv_sec;
|
||||
#if !defined(LPC122X)
|
||||
timespec.tv_msec = 0;
|
||||
#endif
|
||||
rtcSetTime(rtcp, ×pec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets raw time from RTC and converts it to unix format.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return Unix time value in microseconds.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp) {
|
||||
#if STM32_RTC_HAS_SUBSECONDS
|
||||
uint64_t result = 0;
|
||||
RTCTime timespec = {0,0};
|
||||
|
||||
rtcGetTime(rtcp, ×pec);
|
||||
result = (uint64_t)timespec.tv_sec * 1000000;
|
||||
return result + timespec.tv_msec * 1000;
|
||||
#else
|
||||
return (uint64_t)rtcGetTimeUnixSec(rtcp) * 1000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current time in format suitable for usage in FatFS.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return FAT time value.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
uint32_t rtcGetTimeFatFromCounter(RTCDriver *rtcp) {
|
||||
uint32_t fattime;
|
||||
struct tm timp;
|
||||
|
||||
rtcGetTimeTm(rtcp, &timp);
|
||||
|
||||
fattime = (timp.tm_sec) >> 1;
|
||||
fattime |= (timp.tm_min) << 5;
|
||||
fattime |= (timp.tm_hour) << 11;
|
||||
fattime |= (timp.tm_mday) << 16;
|
||||
fattime |= (timp.tm_mon + 1) << 21;
|
||||
fattime |= (timp.tm_year - 80) << 25;
|
||||
|
||||
return fattime;
|
||||
}
|
||||
#endif /* STM32_RTC_IS_CALENDAR */
|
||||
#endif /* (defined(STM32F4XX) || defined(STM32F2XX) || defined(STM32L1XX) || defined(STM32F1XX)) */
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chrtclib.h
|
||||
* @brief RTC time conversion utilities header.
|
||||
*
|
||||
* @addtogroup chrtclib
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHRTCLIB_H_
|
||||
#define CHRTCLIB_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if !STM32_RTC_IS_CALENDAR
|
||||
uint32_t rtcGetTimeFat(RTCDriver *rtcp);
|
||||
#endif
|
||||
void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp);
|
||||
void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp);
|
||||
time_t rtcGetTimeUnixSec(RTCDriver *rtcp);
|
||||
uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp);
|
||||
void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
#endif /* CHRTCLIB_H_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,866 @@
|
||||
/*
|
||||
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 ch.cpp
|
||||
* @brief C++ wrapper code.
|
||||
*
|
||||
* @addtogroup cpp_library
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.hpp"
|
||||
|
||||
namespace chibios_rt {
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::System *
|
||||
*------------------------------------------------------------------------*/
|
||||
void System::init(void) {
|
||||
|
||||
chSysInit();
|
||||
}
|
||||
|
||||
void System::lock(void) {
|
||||
|
||||
chSysLock();
|
||||
}
|
||||
|
||||
void System::unlock(void) {
|
||||
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
void System::lockFromIsr(void) {
|
||||
|
||||
chSysLockFromIsr();
|
||||
}
|
||||
|
||||
void System::unlockFromIsr(void) {
|
||||
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
systime_t System::getTime(void) {
|
||||
|
||||
return chTimeNow();
|
||||
}
|
||||
|
||||
bool System::isTimeWithin(systime_t start, systime_t end) {
|
||||
|
||||
return (bool)chTimeIsWithin(start, end);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::Core *
|
||||
*------------------------------------------------------------------------*/
|
||||
void *Core::alloc(size_t size) {
|
||||
|
||||
return chCoreAlloc(size);
|
||||
}
|
||||
|
||||
void *Core::allocI(size_t size) {
|
||||
|
||||
return chCoreAllocI(size);
|
||||
}
|
||||
|
||||
size_t Core::getStatus(void) {
|
||||
|
||||
return chCoreStatus();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::Timer *
|
||||
*------------------------------------------------------------------------*/
|
||||
void Timer::setI(systime_t time, vtfunc_t vtfunc, void *par) {
|
||||
|
||||
chVTSetI(&timer_ref, time, vtfunc, par);
|
||||
}
|
||||
|
||||
void Timer::resetI() {
|
||||
|
||||
if (chVTIsArmedI(&timer_ref))
|
||||
chVTResetI(&timer_ref);
|
||||
}
|
||||
|
||||
bool Timer::isArmedI(void) {
|
||||
|
||||
return (bool)chVTIsArmedI(&timer_ref);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::ThreadReference *
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
void ThreadReference::stop(void) {
|
||||
|
||||
chDbgPanic("invoked unimplemented method stop()");
|
||||
}
|
||||
|
||||
msg_t ThreadReference::suspend(void) {
|
||||
msg_t msg;
|
||||
|
||||
chSysLock();
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #1",
|
||||
"already referenced");
|
||||
|
||||
thread_ref = chThdSelf();
|
||||
chSchGoSleepS(THD_STATE_SUSPENDED);
|
||||
msg = thread_ref->p_u.rdymsg;
|
||||
|
||||
chSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
msg_t ThreadReference::suspendS(void) {
|
||||
|
||||
chDbgAssert(thread_ref == NULL,
|
||||
"ThreadReference, #2",
|
||||
"already referenced");
|
||||
|
||||
thread_ref = chThdSelf();
|
||||
chSchGoSleepS(THD_STATE_SUSPENDED);
|
||||
return thread_ref->p_u.rdymsg;
|
||||
}
|
||||
|
||||
void ThreadReference::resume(msg_t msg) {
|
||||
|
||||
chSysLock()
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #3",
|
||||
"not referenced");
|
||||
|
||||
if (thread_ref) {
|
||||
Thread *tp = thread_ref;
|
||||
thread_ref = NULL;
|
||||
chSchWakeupS(tp, msg);
|
||||
}
|
||||
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
void ThreadReference::resumeI(msg_t msg) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #4",
|
||||
"not referenced");
|
||||
|
||||
if (thread_ref) {
|
||||
Thread *tp = thread_ref;
|
||||
thread_ref = NULL;
|
||||
tp->p_msg = msg;
|
||||
chSchReadyI(tp);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadReference::requestTerminate(void) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #5",
|
||||
"not referenced");
|
||||
|
||||
chThdTerminate(thread_ref);
|
||||
}
|
||||
|
||||
#if CH_USE_WAITEXIT
|
||||
msg_t ThreadReference::wait(void) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #6",
|
||||
"not referenced");
|
||||
|
||||
msg_t msg = chThdWait(thread_ref);
|
||||
thread_ref = NULL;
|
||||
return msg;
|
||||
}
|
||||
#endif /* CH_USE_WAITEXIT */
|
||||
|
||||
#if CH_USE_MESSAGES
|
||||
msg_t ThreadReference::sendMessage(msg_t msg) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #7",
|
||||
"not referenced");
|
||||
|
||||
return chMsgSend(thread_ref, msg);
|
||||
}
|
||||
|
||||
bool ThreadReference::isPendingMessage(void) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #7",
|
||||
"not referenced");
|
||||
|
||||
return (bool)chMsgIsPendingI(thread_ref);
|
||||
}
|
||||
|
||||
msg_t ThreadReference::getMessage(void) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #8",
|
||||
"not referenced");
|
||||
|
||||
return chMsgGet(thread_ref);
|
||||
}
|
||||
|
||||
void ThreadReference::releaseMessage(msg_t msg) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #9",
|
||||
"not referenced");
|
||||
|
||||
chMsgRelease(thread_ref, msg);
|
||||
}
|
||||
#endif /* CH_USE_MESSAGES */
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
void ThreadReference::signalEvents(eventmask_t mask) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #10",
|
||||
"not referenced");
|
||||
|
||||
chEvtSignal(thread_ref, mask);
|
||||
}
|
||||
|
||||
void ThreadReference::signalEventsI(eventmask_t mask) {
|
||||
|
||||
chDbgAssert(thread_ref != NULL,
|
||||
"ThreadReference, #11",
|
||||
"not referenced");
|
||||
|
||||
chEvtSignalI(thread_ref, mask);
|
||||
}
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
#if CH_USE_DYNAMIC
|
||||
#endif /* CH_USE_DYNAMIC */
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::BaseThread *
|
||||
*------------------------------------------------------------------------*/
|
||||
BaseThread::BaseThread() : ThreadReference(NULL) {
|
||||
|
||||
}
|
||||
|
||||
msg_t BaseThread::main(void) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadReference BaseThread::start(tprio_t prio) {
|
||||
|
||||
(void)prio;
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
msg_t _thd_start(void *arg) {
|
||||
|
||||
return ((BaseThread *)arg)->main();
|
||||
}
|
||||
|
||||
void BaseThread::setName(const char *tname) {
|
||||
|
||||
chRegSetThreadName(tname);
|
||||
}
|
||||
|
||||
tprio_t BaseThread::setPriority(tprio_t newprio) {
|
||||
|
||||
return chThdSetPriority(newprio);
|
||||
}
|
||||
|
||||
void BaseThread::exit(msg_t msg) {
|
||||
|
||||
chThdExit(msg);
|
||||
}
|
||||
|
||||
void BaseThread::exitS(msg_t msg) {
|
||||
|
||||
chThdExitS(msg);
|
||||
}
|
||||
|
||||
bool BaseThread::shouldTerminate(void) {
|
||||
|
||||
return (bool)chThdShouldTerminate();
|
||||
}
|
||||
|
||||
void BaseThread::sleep(systime_t interval){
|
||||
|
||||
chThdSleep(interval);
|
||||
}
|
||||
|
||||
void BaseThread::sleepUntil(systime_t time) {
|
||||
|
||||
chThdSleepUntil(time);
|
||||
}
|
||||
|
||||
void BaseThread::yield(void) {
|
||||
|
||||
chThdYield();
|
||||
}
|
||||
|
||||
#if CH_USE_MESSAGES
|
||||
ThreadReference BaseThread::waitMessage(void) {
|
||||
|
||||
ThreadReference tr(chMsgWait());
|
||||
return tr;
|
||||
}
|
||||
#endif /* CH_USE_MESSAGES */
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
eventmask_t BaseThread::getAndClearEvents(eventmask_t mask) {
|
||||
|
||||
return chEvtGetAndClearEvents(mask);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::addEvents(eventmask_t mask) {
|
||||
|
||||
return chEvtAddEvents(mask);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::waitOneEvent(eventmask_t ewmask) {
|
||||
|
||||
return chEvtWaitOne(ewmask);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::waitAnyEvent(eventmask_t ewmask) {
|
||||
|
||||
return chEvtWaitAny(ewmask);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::waitAllEvents(eventmask_t ewmask) {
|
||||
|
||||
return chEvtWaitAll(ewmask);
|
||||
}
|
||||
|
||||
#if CH_USE_EVENTS_TIMEOUT
|
||||
eventmask_t BaseThread::waitOneEventTimeout(eventmask_t ewmask,
|
||||
systime_t time) {
|
||||
|
||||
return chEvtWaitOneTimeout(ewmask, time);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::waitAnyEventTimeout(eventmask_t ewmask,
|
||||
systime_t time) {
|
||||
|
||||
return chEvtWaitAnyTimeout(ewmask, time);
|
||||
}
|
||||
|
||||
eventmask_t BaseThread::waitAllEventsTimeout(eventmask_t ewmask,
|
||||
systime_t time) {
|
||||
|
||||
return chEvtWaitAllTimeout(ewmask, time);
|
||||
}
|
||||
#endif /* CH_USE_EVENTS_TIMEOUT */
|
||||
|
||||
void BaseThread::dispatchEvents(const evhandler_t handlers[],
|
||||
eventmask_t mask) {
|
||||
|
||||
chEvtDispatch(handlers, mask);
|
||||
}
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
void BaseThread::unlockMutex(void) {
|
||||
|
||||
chMtxUnlock();
|
||||
}
|
||||
|
||||
void BaseThread::unlockMutexS(void) {
|
||||
|
||||
chMtxUnlockS();
|
||||
}
|
||||
|
||||
void BaseThread::unlockAllMutexes(void) {
|
||||
|
||||
chMtxUnlockAll();
|
||||
}
|
||||
#endif /* CH_USE_MUTEXES */
|
||||
|
||||
#if CH_USE_SEMAPHORES
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::CounterSemaphore *
|
||||
*------------------------------------------------------------------------*/
|
||||
CounterSemaphore::CounterSemaphore(cnt_t n) {
|
||||
|
||||
chSemInit(&sem, n);
|
||||
}
|
||||
|
||||
void CounterSemaphore::reset(cnt_t n) {
|
||||
|
||||
chSemReset(&sem, n);
|
||||
}
|
||||
|
||||
void CounterSemaphore::resetI(cnt_t n) {
|
||||
|
||||
chSemResetI(&sem, n);
|
||||
}
|
||||
|
||||
msg_t CounterSemaphore::wait(void) {
|
||||
|
||||
return chSemWait(&sem);
|
||||
}
|
||||
|
||||
msg_t CounterSemaphore::waitS(void) {
|
||||
|
||||
return chSemWaitS(&sem);
|
||||
}
|
||||
|
||||
msg_t CounterSemaphore::waitTimeout(systime_t time) {
|
||||
|
||||
return chSemWaitTimeout(&sem, time);
|
||||
}
|
||||
|
||||
msg_t CounterSemaphore::waitTimeoutS(systime_t time) {
|
||||
|
||||
return chSemWaitTimeoutS(&sem, time);
|
||||
}
|
||||
|
||||
void CounterSemaphore::signal(void) {
|
||||
|
||||
chSemSignal(&sem);
|
||||
}
|
||||
|
||||
void CounterSemaphore::signalI(void) {
|
||||
|
||||
chSemSignalI(&sem);
|
||||
}
|
||||
|
||||
void CounterSemaphore::addCounterI(cnt_t n) {
|
||||
|
||||
chSemAddCounterI(&sem, n);
|
||||
}
|
||||
|
||||
cnt_t CounterSemaphore::getCounterI(void) {
|
||||
|
||||
return chSemGetCounterI(&sem);
|
||||
}
|
||||
|
||||
#if CH_USE_SEMSW
|
||||
msg_t CounterSemaphore::signalWait(CounterSemaphore *ssem,
|
||||
CounterSemaphore *wsem) {
|
||||
|
||||
return chSemSignalWait(&ssem->sem, &wsem->sem);
|
||||
}
|
||||
#endif /* CH_USE_SEMSW */
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::BinarySemaphore *
|
||||
*------------------------------------------------------------------------*/
|
||||
BinarySemaphore::BinarySemaphore(bool taken) {
|
||||
|
||||
chBSemInit(&bsem, (bool_t)taken);
|
||||
}
|
||||
|
||||
msg_t BinarySemaphore::wait(void) {
|
||||
|
||||
return chBSemWait(&bsem);
|
||||
}
|
||||
|
||||
msg_t BinarySemaphore::waitS(void) {
|
||||
|
||||
return chBSemWaitS(&bsem);
|
||||
}
|
||||
|
||||
msg_t BinarySemaphore::waitTimeout(systime_t time) {
|
||||
|
||||
return chBSemWaitTimeout(&bsem, time);
|
||||
}
|
||||
|
||||
msg_t BinarySemaphore::waitTimeoutS(systime_t time) {
|
||||
|
||||
return chBSemWaitTimeoutS(&bsem, time);
|
||||
}
|
||||
|
||||
void BinarySemaphore::reset(bool taken) {
|
||||
|
||||
chBSemReset(&bsem, (bool_t)taken);
|
||||
}
|
||||
|
||||
void BinarySemaphore::resetI(bool taken) {
|
||||
|
||||
chBSemResetI(&bsem, (bool_t)taken);
|
||||
}
|
||||
|
||||
void BinarySemaphore::signal(void) {
|
||||
|
||||
chBSemSignal(&bsem);
|
||||
}
|
||||
|
||||
void BinarySemaphore::signalI(void) {
|
||||
|
||||
chBSemSignalI(&bsem);
|
||||
}
|
||||
|
||||
bool BinarySemaphore::getStateI(void) {
|
||||
|
||||
return (bool)chBSemGetStateI(&bsem);
|
||||
}
|
||||
#endif /* CH_USE_SEMAPHORES */
|
||||
|
||||
#if CH_USE_MUTEXES
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::Mutex *
|
||||
*------------------------------------------------------------------------*/
|
||||
Mutex::Mutex(void) {
|
||||
|
||||
chMtxInit(&mutex);
|
||||
}
|
||||
|
||||
bool Mutex::tryLock(void) {
|
||||
|
||||
return chMtxTryLock(&mutex);
|
||||
}
|
||||
|
||||
bool Mutex::tryLockS(void) {
|
||||
|
||||
return chMtxTryLockS(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::lock(void) {
|
||||
|
||||
chMtxLock(&mutex);
|
||||
}
|
||||
|
||||
void Mutex::lockS(void) {
|
||||
|
||||
chMtxLockS(&mutex);
|
||||
}
|
||||
|
||||
#if CH_USE_CONDVARS
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::CondVar *
|
||||
*------------------------------------------------------------------------*/
|
||||
CondVar::CondVar(void) {
|
||||
|
||||
chCondInit(&condvar);
|
||||
}
|
||||
|
||||
void CondVar::signal(void) {
|
||||
|
||||
chCondSignal(&condvar);
|
||||
}
|
||||
|
||||
void CondVar::signalI(void) {
|
||||
|
||||
chCondSignalI(&condvar);
|
||||
}
|
||||
|
||||
void CondVar::broadcast(void) {
|
||||
|
||||
chCondBroadcast(&condvar);
|
||||
}
|
||||
|
||||
void CondVar::broadcastI(void) {
|
||||
|
||||
chCondBroadcastI(&condvar);
|
||||
}
|
||||
|
||||
msg_t CondVar::wait(void) {
|
||||
|
||||
return chCondWait(&condvar);
|
||||
}
|
||||
|
||||
msg_t CondVar::waitS(void) {
|
||||
|
||||
return chCondWaitS(&condvar);
|
||||
}
|
||||
|
||||
#if CH_USE_CONDVARS_TIMEOUT
|
||||
msg_t CondVar::waitTimeout(systime_t time) {
|
||||
|
||||
return chCondWaitTimeout(&condvar, time);
|
||||
}
|
||||
#endif /* CH_USE_CONDVARS_TIMEOUT */
|
||||
#endif /* CH_USE_CONDVARS */
|
||||
#endif /* CH_USE_MUTEXES */
|
||||
|
||||
#if CH_USE_EVENTS
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::EvtListener *
|
||||
*------------------------------------------------------------------------*/
|
||||
flagsmask_t EvtListener::getAndClearFlags(void) {
|
||||
|
||||
return chEvtGetAndClearFlags(&ev_listener);
|
||||
}
|
||||
|
||||
flagsmask_t EvtListener::getAndClearFlagsI(void) {
|
||||
|
||||
return chEvtGetAndClearFlagsI(&ev_listener);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::EvtSource *
|
||||
*------------------------------------------------------------------------*/
|
||||
EvtSource::EvtSource(void) {
|
||||
|
||||
chEvtInit(&ev_source);
|
||||
}
|
||||
|
||||
void EvtSource::registerOne(chibios_rt::EvtListener *elp,
|
||||
eventid_t eid) {
|
||||
|
||||
chEvtRegister(&ev_source, &elp->ev_listener, eid);
|
||||
}
|
||||
|
||||
void EvtSource::registerMask(chibios_rt::EvtListener *elp,
|
||||
eventmask_t emask) {
|
||||
|
||||
chEvtRegisterMask(&ev_source, &elp->ev_listener, emask);
|
||||
}
|
||||
|
||||
void EvtSource::unregister(chibios_rt::EvtListener *elp) {
|
||||
|
||||
chEvtUnregister(&ev_source, &elp->ev_listener);
|
||||
}
|
||||
|
||||
void EvtSource::broadcastFlags(flagsmask_t flags) {
|
||||
|
||||
chEvtBroadcastFlags(&ev_source, flags);
|
||||
}
|
||||
|
||||
void EvtSource::broadcastFlagsI(flagsmask_t flags) {
|
||||
|
||||
chEvtBroadcastFlagsI(&ev_source, flags);
|
||||
}
|
||||
#endif /* CH_USE_EVENTS */
|
||||
|
||||
#if CH_USE_QUEUES
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::InQueue *
|
||||
*------------------------------------------------------------------------*/
|
||||
InQueue::InQueue(uint8_t *bp, size_t size, qnotify_t infy, void *link) {
|
||||
|
||||
chIQInit(&iq, bp, size, infy, link);
|
||||
}
|
||||
|
||||
size_t InQueue::getFullI(void) {
|
||||
|
||||
return chIQGetFullI(&iq);
|
||||
}
|
||||
|
||||
size_t InQueue::getEmptyI(void) {
|
||||
|
||||
return chIQGetEmptyI(&iq);
|
||||
}
|
||||
|
||||
bool InQueue::isEmptyI(void) {
|
||||
|
||||
return (bool)chIQIsEmptyI(&iq);
|
||||
}
|
||||
|
||||
bool InQueue::isFullI(void) {
|
||||
|
||||
return (bool)chIQIsFullI(&iq);
|
||||
}
|
||||
|
||||
void InQueue::resetI(void) {
|
||||
|
||||
chIQResetI(&iq);
|
||||
}
|
||||
|
||||
msg_t InQueue::putI(uint8_t b) {
|
||||
|
||||
return chIQPutI(&iq, b);
|
||||
}
|
||||
|
||||
msg_t InQueue::get() {
|
||||
|
||||
return chIQGet(&iq);
|
||||
}
|
||||
|
||||
msg_t InQueue::getTimeout(systime_t time) {
|
||||
|
||||
return chIQGetTimeout(&iq, time);
|
||||
}
|
||||
|
||||
size_t InQueue::readTimeout(uint8_t *bp, size_t n, systime_t time) {
|
||||
|
||||
return chIQReadTimeout(&iq, bp, n, time);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::OutQueue *
|
||||
*------------------------------------------------------------------------*/
|
||||
OutQueue::OutQueue(uint8_t *bp, size_t size, qnotify_t onfy, void *link) {
|
||||
|
||||
chOQInit(&oq, bp, size, onfy, link);
|
||||
}
|
||||
|
||||
size_t OutQueue::getFullI(void) {
|
||||
|
||||
return chOQGetFullI(&oq);
|
||||
}
|
||||
|
||||
size_t OutQueue::getEmptyI(void) {
|
||||
|
||||
return chOQGetEmptyI(&oq);
|
||||
}
|
||||
|
||||
bool OutQueue::isEmptyI(void) {
|
||||
|
||||
return (bool)chOQIsEmptyI(&oq);
|
||||
}
|
||||
|
||||
bool OutQueue::isFullI(void) {
|
||||
|
||||
return (bool)chOQIsFullI(&oq);
|
||||
}
|
||||
|
||||
void OutQueue::resetI(void) {
|
||||
|
||||
chOQResetI(&oq);
|
||||
}
|
||||
|
||||
msg_t OutQueue::put(uint8_t b) {
|
||||
|
||||
return chOQPut(&oq, b);
|
||||
}
|
||||
|
||||
msg_t OutQueue::putTimeout(uint8_t b, systime_t time) {
|
||||
|
||||
return chOQPutTimeout(&oq, b, time);
|
||||
}
|
||||
|
||||
msg_t OutQueue::getI(void) {
|
||||
|
||||
return chOQGetI(&oq);
|
||||
}
|
||||
|
||||
size_t OutQueue::writeTimeout(const uint8_t *bp, size_t n,
|
||||
systime_t time) {
|
||||
|
||||
return chOQWriteTimeout(&oq, bp, n, time);
|
||||
}
|
||||
#endif /* CH_USE_QUEUES */
|
||||
|
||||
#if CH_USE_MAILBOXES
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::Mailbox *
|
||||
*------------------------------------------------------------------------*/
|
||||
Mailbox::Mailbox(msg_t *buf, cnt_t n) {
|
||||
|
||||
chMBInit(&mb, buf, n);
|
||||
}
|
||||
|
||||
void Mailbox::reset(void) {
|
||||
|
||||
chMBReset(&mb);
|
||||
}
|
||||
|
||||
msg_t Mailbox::post(msg_t msg, systime_t time) {
|
||||
|
||||
return chMBPost(&mb, msg, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::postS(msg_t msg, systime_t time) {
|
||||
|
||||
return chMBPostS(&mb, msg, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::postI(msg_t msg) {
|
||||
|
||||
return chMBPostI(&mb, msg);
|
||||
}
|
||||
|
||||
msg_t Mailbox::postAhead(msg_t msg, systime_t time) {
|
||||
|
||||
return chMBPostAhead(&mb, msg, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::postAheadS(msg_t msg, systime_t time) {
|
||||
|
||||
return chMBPostAheadS(&mb, msg, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::postAheadI(msg_t msg) {
|
||||
|
||||
return chMBPostAheadI(&mb, msg);
|
||||
}
|
||||
|
||||
msg_t Mailbox::fetch(msg_t *msgp, systime_t time) {
|
||||
|
||||
return chMBFetch(&mb, msgp, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::fetchS(msg_t *msgp, systime_t time) {
|
||||
|
||||
return chMBFetchS(&mb, msgp, time);
|
||||
}
|
||||
|
||||
msg_t Mailbox::fetchI(msg_t *msgp) {
|
||||
|
||||
return chMBFetchI(&mb, msgp);
|
||||
}
|
||||
|
||||
cnt_t Mailbox::getFreeCountI(void) {
|
||||
|
||||
return chMBGetFreeCountI(&mb);
|
||||
}
|
||||
|
||||
cnt_t Mailbox::getUsedCountI(void) {
|
||||
|
||||
return chMBGetUsedCountI(&mb);
|
||||
}
|
||||
#endif /* CH_USE_MAILBOXES */
|
||||
|
||||
#if CH_USE_MEMPOOLS
|
||||
/*------------------------------------------------------------------------*
|
||||
* chibios_rt::MemoryPool *
|
||||
*------------------------------------------------------------------------*/
|
||||
MemoryPool::MemoryPool(size_t size, memgetfunc_t provider) {
|
||||
|
||||
chPoolInit(&pool, size, provider);
|
||||
}
|
||||
|
||||
MemoryPool::MemoryPool(size_t size, memgetfunc_t provider, void* p, size_t n) {
|
||||
|
||||
chPoolInit(&pool, size, provider);
|
||||
chPoolLoadArray(&pool, p, n);
|
||||
}
|
||||
|
||||
|
||||
void MemoryPool::loadArray(void *p, size_t n) {
|
||||
|
||||
chPoolLoadArray(&pool, p, n);
|
||||
}
|
||||
|
||||
void *MemoryPool::allocI(void) {
|
||||
|
||||
return chPoolAllocI(&pool);
|
||||
}
|
||||
|
||||
void *MemoryPool::alloc(void) {
|
||||
|
||||
return chPoolAlloc(&pool);
|
||||
}
|
||||
|
||||
void MemoryPool::free(void *objp) {
|
||||
|
||||
chPoolFree(&pool, objp);
|
||||
}
|
||||
|
||||
void MemoryPool::freeI(void *objp) {
|
||||
|
||||
chPoolFreeI(&pool, objp);
|
||||
}
|
||||
#endif /* CH_USE_MEMPOOLS */
|
||||
}
|
||||
|
||||
/** @} */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,4 @@
|
||||
# C++ wrapper files.
|
||||
CHCPPSRC = ${CHIBIOS}/os/various/cpp_wrappers/ch.cpp
|
||||
|
||||
CHCPPINC = ${CHIBIOS}/os/various/cpp_wrappers
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
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 lis302dl.c
|
||||
* @brief LIS302DL MEMS interface module through SPI code.
|
||||
*
|
||||
* @addtogroup lis302dl
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "lis302dl.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static uint8_t txbuf[2];
|
||||
static uint8_t rxbuf[2];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Reads a register value.
|
||||
* @pre The SPI interface must be initialized and the driver started.
|
||||
*
|
||||
* @param[in] spip pointer to the SPI initerface
|
||||
* @param[in] reg register number
|
||||
* @return The register value.
|
||||
*/
|
||||
uint8_t lis302dlReadRegister(SPIDriver *spip, uint8_t reg) {
|
||||
|
||||
spiSelect(spip);
|
||||
txbuf[0] = 0x80 | reg;
|
||||
txbuf[1] = 0xff;
|
||||
spiExchange(spip, 2, txbuf, rxbuf);
|
||||
spiUnselect(spip);
|
||||
return rxbuf[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a value into a register.
|
||||
* @pre The SPI interface must be initialized and the driver started.
|
||||
*
|
||||
* @param[in] spip pointer to the SPI initerface
|
||||
* @param[in] reg register number
|
||||
* @param[in] value the value to be written
|
||||
*/
|
||||
void lis302dlWriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value) {
|
||||
|
||||
switch (reg) {
|
||||
default:
|
||||
/* Reserved register must not be written, according to the datasheet
|
||||
this could permanently damage the device.*/
|
||||
chDbgAssert(FALSE, "lis302dlWriteRegister(), #1", "reserved register");
|
||||
case LIS302DL_WHO_AM_I:
|
||||
case LIS302DL_HP_FILTER_RESET:
|
||||
case LIS302DL_STATUS_REG:
|
||||
case LIS302DL_OUTX:
|
||||
case LIS302DL_OUTY:
|
||||
case LIS302DL_OUTZ:
|
||||
case LIS302DL_FF_WU_SRC1:
|
||||
case LIS302DL_FF_WU_SRC2:
|
||||
case LIS302DL_CLICK_SRC:
|
||||
/* Read only registers cannot be written, the command is ignored.*/
|
||||
return;
|
||||
case LIS302DL_CTRL_REG1:
|
||||
case LIS302DL_CTRL_REG2:
|
||||
case LIS302DL_CTRL_REG3:
|
||||
case LIS302DL_FF_WU_CFG1:
|
||||
case LIS302DL_FF_WU_THS1:
|
||||
case LIS302DL_FF_WU_DURATION1:
|
||||
case LIS302DL_FF_WU_CFG2:
|
||||
case LIS302DL_FF_WU_THS2:
|
||||
case LIS302DL_FF_WU_DURATION2:
|
||||
case LIS302DL_CLICK_CFG:
|
||||
case LIS302DL_CLICK_THSY_X:
|
||||
case LIS302DL_CLICK_THSZ:
|
||||
case LIS302DL_CLICK_TIMELIMIT:
|
||||
case LIS302DL_CLICK_LATENCY:
|
||||
case LIS302DL_CLICK_WINDOW:
|
||||
spiSelect(spip);
|
||||
txbuf[0] = reg;
|
||||
txbuf[1] = value;
|
||||
spiSend(spip, 2, txbuf);
|
||||
spiUnselect(spip);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lis302dl Interface module for LIS302DL MEMS
|
||||
*
|
||||
* @brief Interface module for LIS302DL MEMS.
|
||||
* @details This module implements a generic interface for the LIS302DL
|
||||
* STMicroelectronics MEMS device. The communication is performed
|
||||
* through a standard SPI driver.
|
||||
*
|
||||
* @ingroup accel
|
||||
*/
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
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 lis302dl.h
|
||||
* @brief LIS302DL MEMS interface module through SPI header.
|
||||
*
|
||||
* @addtogroup lis302dl
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LIS302DL_H_
|
||||
#define _LIS302DL_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name LIS302DL register names
|
||||
* @{
|
||||
*/
|
||||
#define LIS302DL_WHO_AM_I 0x0F
|
||||
#define LIS302DL_CTRL_REG1 0x20
|
||||
#define LIS302DL_CTRL_REG2 0x21
|
||||
#define LIS302DL_CTRL_REG3 0x22
|
||||
#define LIS302DL_HP_FILTER_RESET 0x23
|
||||
#define LIS302DL_STATUS_REG 0x27
|
||||
#define LIS302DL_OUTX 0x29
|
||||
#define LIS302DL_OUTY 0x2B
|
||||
#define LIS302DL_OUTZ 0x2D
|
||||
#define LIS302DL_FF_WU_CFG1 0x30
|
||||
#define LIS302DL_FF_WU_SRC1 0x31
|
||||
#define LIS302DL_FF_WU_THS1 0x32
|
||||
#define LIS302DL_FF_WU_DURATION1 0x33
|
||||
#define LIS302DL_FF_WU_CFG2 0x34
|
||||
#define LIS302DL_FF_WU_SRC2 0x35
|
||||
#define LIS302DL_FF_WU_THS2 0x36
|
||||
#define LIS302DL_FF_WU_DURATION2 0x37
|
||||
#define LIS302DL_CLICK_CFG 0x38
|
||||
#define LIS302DL_CLICK_SRC 0x39
|
||||
#define LIS302DL_CLICK_THSY_X 0x3B
|
||||
#define LIS302DL_CLICK_THSZ 0x3C
|
||||
#define LIS302DL_CLICK_TIMELIMIT 0x3D
|
||||
#define LIS302DL_CLICK_LATENCY 0x3E
|
||||
#define LIS302DL_CLICK_WINDOW 0x3F
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
uint8_t lis302dlReadRegister(SPIDriver *spip, uint8_t reg);
|
||||
void lis302dlWriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIS302DL_H_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 evtimer.c
|
||||
* @brief Events Generator Timer code.
|
||||
*
|
||||
* @addtogroup event_timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "evtimer.h"
|
||||
|
||||
static void tmrcb(void *p) {
|
||||
EvTimer *etp = p;
|
||||
|
||||
chSysLockFromIsr();
|
||||
chEvtBroadcastI(&etp->et_es);
|
||||
chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer
|
||||
* @details If the timer was already running then the function has no effect.
|
||||
*
|
||||
* @param etp pointer to an initialized @p EvTimer structure.
|
||||
*/
|
||||
void evtStart(EvTimer *etp) {
|
||||
|
||||
chSysLock();
|
||||
|
||||
if (!chVTIsArmedI(&etp->et_vt))
|
||||
chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp);
|
||||
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
* @details If the timer was already stopped then the function has no effect.
|
||||
*
|
||||
* @param etp pointer to an initialized @p EvTimer structure.
|
||||
*/
|
||||
void evtStop(EvTimer *etp) {
|
||||
|
||||
chVTReset(&etp->et_vt);
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
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 evtimer.h
|
||||
* @brief Events Generator Timer structures and macros.
|
||||
*
|
||||
* @addtogroup event_timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _EVTIMER_H_
|
||||
#define _EVTIMER_H_
|
||||
|
||||
|
||||
/*
|
||||
* Module dependencies check.
|
||||
*/
|
||||
#if !CH_USE_EVENTS
|
||||
#error "Event Timers require CH_USE_EVENTS"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Event timer structure.
|
||||
*/
|
||||
typedef struct {
|
||||
VirtualTimer et_vt;
|
||||
EventSource et_es;
|
||||
systime_t et_interval;
|
||||
} EvTimer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void evtStart(EvTimer *etp);
|
||||
void evtStop(EvTimer *etp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes an @p EvTimer structure.
|
||||
*
|
||||
* @param etp the EvTimer structure to be initialized
|
||||
* @param time the interval in system ticks
|
||||
*/
|
||||
#define evtInit(etp, time) { \
|
||||
chEvtInit(&(etp)->et_es); \
|
||||
(etp)->et_vt.vt_func = NULL; \
|
||||
(etp)->et_interval = (time); \
|
||||
}
|
||||
|
||||
#endif /* _EVTIMER_H_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,7 @@
|
||||
# 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/unicode.c
|
||||
|
||||
FATFSINC = ${CHIBIOS}/ext/fatfs/src
|
@ -0,0 +1,254 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* 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
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
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 */
|
@ -0,0 +1,6 @@
|
||||
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.
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
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__ */
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
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__ */
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
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
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
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__ */
|
@ -0,0 +1,54 @@
|
||||
# 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
|
@ -0,0 +1,303 @@
|
||||
/*
|
||||
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(ÐD1, &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(ÐD1, &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(ÐD1, &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(ÐD1), &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(ÐD1);
|
||||
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;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
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_ */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,6 @@
|
||||
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.
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 memstreams.c
|
||||
* @brief Memory streams code.
|
||||
*
|
||||
* @addtogroup memory_streams
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ch.h"
|
||||
#include "memstreams.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static size_t writes(void *ip, const uint8_t *bp, size_t n) {
|
||||
MemoryStream *msp = ip;
|
||||
|
||||
if (msp->size - msp->eos < n)
|
||||
n = msp->size - msp->eos;
|
||||
memcpy(msp->buffer + msp->eos, bp, n);
|
||||
msp->eos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static size_t reads(void *ip, uint8_t *bp, size_t n) {
|
||||
MemoryStream *msp = ip;
|
||||
|
||||
if (msp->eos - msp->offset < n)
|
||||
n = msp->eos - msp->offset;
|
||||
memcpy(bp, msp->buffer + msp->offset, n);
|
||||
msp->offset += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static msg_t put(void *ip, uint8_t b) {
|
||||
MemoryStream *msp = ip;
|
||||
|
||||
if (msp->size - msp->eos <= 0)
|
||||
return RDY_RESET;
|
||||
*(msp->buffer + msp->eos) = b;
|
||||
msp->eos += 1;
|
||||
return RDY_OK;
|
||||
}
|
||||
|
||||
static msg_t get(void *ip) {
|
||||
uint8_t b;
|
||||
MemoryStream *msp = ip;
|
||||
|
||||
if (msp->eos - msp->offset <= 0)
|
||||
return RDY_RESET;
|
||||
b = *(msp->buffer + msp->offset);
|
||||
msp->offset += 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
static const struct MemStreamVMT vmt = {writes, reads, put, get};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Memory stream object initialization.
|
||||
*
|
||||
* @param[out] msp pointer to the @p MemoryStream object to be initialized
|
||||
* @param[in] buffer pointer to the memory buffer for the memory stream
|
||||
* @param[in] size total size of the memory stream buffer
|
||||
* @param[in] eos initial End Of Stream offset. Normally you need to
|
||||
* put this to zero for RAM buffers or equal to @p size
|
||||
* for ROM streams.
|
||||
*/
|
||||
void msObjectInit(MemoryStream *msp, uint8_t *buffer,
|
||||
size_t size, size_t eos) {
|
||||
|
||||
msp->vmt = &vmt;
|
||||
msp->buffer = buffer;
|
||||
msp->size = size;
|
||||
msp->eos = eos;
|
||||
msp->offset = 0;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
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 memstreams.h
|
||||
* @brief Memory streams structures and macros.
|
||||
|
||||
* @addtogroup memory_streams
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _MEMSTREAMS_H_
|
||||
#define _MEMSTREAMS_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief @p RamStream specific data.
|
||||
*/
|
||||
#define _memory_stream_data \
|
||||
_base_sequential_stream_data \
|
||||
/* Pointer to the stream buffer.*/ \
|
||||
uint8_t *buffer; \
|
||||
/* Size of the stream.*/ \
|
||||
size_t size; \
|
||||
/* Current end of stream.*/ \
|
||||
size_t eos; \
|
||||
/* Current read offset.*/ \
|
||||
size_t offset;
|
||||
|
||||
/**
|
||||
* @brief @p MemStream virtual methods table.
|
||||
*/
|
||||
struct MemStreamVMT {
|
||||
_base_sequential_stream_methods
|
||||
};
|
||||
|
||||
/**
|
||||
* @extends BaseSequentialStream
|
||||
*
|
||||
* @brief Memory stream object.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief Virtual Methods Table.*/
|
||||
const struct MemStreamVMT *vmt;
|
||||
_memory_stream_data
|
||||
} MemoryStream;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void msObjectInit(MemoryStream *msp, uint8_t *buffer,
|
||||
size_t size, size_t eos);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MEMSTREAMS_H_ */
|
||||
|
||||
/** @} */
|
310
Software/portapack-mayhem/firmware/chibios/os/various/shell.c
Normal file
310
Software/portapack-mayhem/firmware/chibios/os/various/shell.c
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
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 shell.c
|
||||
* @brief Simple CLI shell code.
|
||||
*
|
||||
* @addtogroup SHELL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "shell.h"
|
||||
#include "chprintf.h"
|
||||
|
||||
/**
|
||||
* @brief Shell termination event source.
|
||||
*/
|
||||
EventSource shell_terminated;
|
||||
|
||||
static char *_strtok(char *str, const char *delim, char **saveptr) {
|
||||
char *token;
|
||||
if (str)
|
||||
*saveptr = str;
|
||||
token = *saveptr;
|
||||
|
||||
if (!token)
|
||||
return NULL;
|
||||
|
||||
token += strspn(token, delim);
|
||||
*saveptr = strpbrk(token, delim);
|
||||
if (*saveptr)
|
||||
*(*saveptr)++ = '\0';
|
||||
|
||||
return *token ? token : NULL;
|
||||
}
|
||||
|
||||
static void usage(BaseSequentialStream *chp, char *p) {
|
||||
|
||||
chprintf(chp, "Usage: %s\r\n", p);
|
||||
}
|
||||
|
||||
static void list_commands(BaseSequentialStream *chp, const ShellCommand *scp) {
|
||||
|
||||
while (scp->sc_name != NULL) {
|
||||
chprintf(chp, "%s ", scp->sc_name);
|
||||
scp++;
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_info(BaseSequentialStream *chp, int argc, char *argv[]) {
|
||||
|
||||
(void)argv;
|
||||
if (argc > 0) {
|
||||
usage(chp, "info");
|
||||
return;
|
||||
}
|
||||
|
||||
chprintf(chp, "Kernel: %s\r\n", CH_KERNEL_VERSION);
|
||||
#ifdef CH_COMPILER_NAME
|
||||
chprintf(chp, "Compiler: %s\r\n", CH_COMPILER_NAME);
|
||||
#endif
|
||||
chprintf(chp, "Architecture: %s\r\n", CH_ARCHITECTURE_NAME);
|
||||
#ifdef CH_CORE_VARIANT_NAME
|
||||
chprintf(chp, "Core Variant: %s\r\n", CH_CORE_VARIANT_NAME);
|
||||
#endif
|
||||
#ifdef CH_PORT_INFO
|
||||
chprintf(chp, "Port Info: %s\r\n", CH_PORT_INFO);
|
||||
#endif
|
||||
#ifdef PLATFORM_NAME
|
||||
chprintf(chp, "Platform: %s\r\n", PLATFORM_NAME);
|
||||
#endif
|
||||
#ifdef BOARD_NAME
|
||||
chprintf(chp, "Board: %s\r\n", BOARD_NAME);
|
||||
#endif
|
||||
#ifdef __DATE__
|
||||
#ifdef __TIME__
|
||||
chprintf(chp, "Build time: %s%s%s\r\n", __DATE__, " - ", __TIME__);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cmd_systime(BaseSequentialStream *chp, int argc, char *argv[]) {
|
||||
|
||||
(void)argv;
|
||||
if (argc > 0) {
|
||||
usage(chp, "systime");
|
||||
return;
|
||||
}
|
||||
chprintf(chp, "%lu\r\n", (unsigned long)chTimeNow());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Array of the default commands.
|
||||
*/
|
||||
static ShellCommand local_commands[] = {
|
||||
{"info", cmd_info},
|
||||
{"systime", cmd_systime},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static bool_t cmdexec(const ShellCommand *scp, BaseSequentialStream *chp,
|
||||
char *name, int argc, char *argv[]) {
|
||||
|
||||
while (scp->sc_name != NULL) {
|
||||
if (strcasecmp(scp->sc_name, name) == 0) {
|
||||
scp->sc_function(chp, argc, argv);
|
||||
return FALSE;
|
||||
}
|
||||
scp++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shell thread function.
|
||||
*
|
||||
* @param[in] p pointer to a @p BaseSequentialStream object
|
||||
* @return Termination reason.
|
||||
* @retval RDY_OK terminated by command.
|
||||
* @retval RDY_RESET terminated by reset condition on the I/O channel.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static msg_t shell_thread(void *p) {
|
||||
int n;
|
||||
BaseSequentialStream *chp = ((ShellConfig *)p)->sc_channel;
|
||||
const ShellCommand *scp = ((ShellConfig *)p)->sc_commands;
|
||||
char *lp, *cmd, *tokp, line[SHELL_MAX_LINE_LENGTH];
|
||||
char *args[SHELL_MAX_ARGUMENTS + 1];
|
||||
|
||||
chRegSetThreadName("shell");
|
||||
chprintf(chp, "\r\nChibiOS/RT Shell\r\n");
|
||||
while (TRUE) {
|
||||
chprintf(chp, "ch> ");
|
||||
if (shellGetLine(chp, line, sizeof(line))) {
|
||||
chprintf(chp, "\r\nlogout");
|
||||
break;
|
||||
}
|
||||
lp = _strtok(line, " \t", &tokp);
|
||||
cmd = lp;
|
||||
n = 0;
|
||||
while ((lp = _strtok(NULL, " \t", &tokp)) != NULL) {
|
||||
if (n >= SHELL_MAX_ARGUMENTS) {
|
||||
chprintf(chp, "too many arguments\r\n");
|
||||
cmd = NULL;
|
||||
break;
|
||||
}
|
||||
args[n++] = lp;
|
||||
}
|
||||
args[n] = NULL;
|
||||
if (cmd != NULL) {
|
||||
if (strcasecmp(cmd, "exit") == 0) {
|
||||
if (n > 0) {
|
||||
usage(chp, "exit");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (strcasecmp(cmd, "help") == 0) {
|
||||
if (n > 0) {
|
||||
usage(chp, "help");
|
||||
continue;
|
||||
}
|
||||
chprintf(chp, "Commands: help exit ");
|
||||
list_commands(chp, local_commands);
|
||||
if (scp != NULL)
|
||||
list_commands(chp, scp);
|
||||
chprintf(chp, "\r\n");
|
||||
}
|
||||
else if (cmdexec(local_commands, chp, cmd, n, args) &&
|
||||
((scp == NULL) || cmdexec(scp, chp, cmd, n, args))) {
|
||||
chprintf(chp, "%s", cmd);
|
||||
chprintf(chp, " ?\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
shellExit(RDY_OK);
|
||||
/* Never executed, silencing a warning.*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shell manager initialization.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void shellInit(void) {
|
||||
|
||||
chEvtInit(&shell_terminated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminates the shell.
|
||||
* @note Must be invoked from the command handlers.
|
||||
* @note Does not return.
|
||||
*
|
||||
* @param[in] msg shell exit code
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void shellExit(msg_t msg) {
|
||||
|
||||
/* Atomically broadcasting the event source and terminating the thread,
|
||||
there is not a chSysUnlock() because the thread terminates upon return.*/
|
||||
chSysLock();
|
||||
chEvtBroadcastI(&shell_terminated);
|
||||
chThdExitS(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Spawns a new shell.
|
||||
* @pre @p CH_USE_HEAP and @p CH_USE_DYNAMIC must be enabled.
|
||||
*
|
||||
* @param[in] scp pointer to a @p ShellConfig object
|
||||
* @param[in] size size of the shell working area to be allocated
|
||||
* @param[in] prio priority level for the new shell
|
||||
* @return A pointer to the shell thread.
|
||||
* @retval NULL thread creation failed because memory allocation.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#if CH_USE_HEAP && CH_USE_DYNAMIC
|
||||
Thread *shellCreate(const ShellConfig *scp, size_t size, tprio_t prio) {
|
||||
|
||||
return chThdCreateFromHeap(NULL, size, prio, shell_thread, (void *)scp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create statically allocated shell thread.
|
||||
*
|
||||
* @param[in] scp pointer to a @p ShellConfig object
|
||||
* @param[in] wsp pointer to a working area dedicated to the shell thread stack
|
||||
* @param[in] size size of the shell working area
|
||||
* @param[in] prio priority level for the new shell
|
||||
* @return A pointer to the shell thread.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
Thread *shellCreateStatic(const ShellConfig *scp, void *wsp,
|
||||
size_t size, tprio_t prio) {
|
||||
|
||||
return chThdCreateStatic(wsp, size, prio, shell_thread, (void *)scp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a whole line from the input channel.
|
||||
*
|
||||
* @param[in] chp pointer to a @p BaseSequentialStream object
|
||||
* @param[in] line pointer to the line buffer
|
||||
* @param[in] size buffer maximum length
|
||||
* @return The operation status.
|
||||
* @retval TRUE the channel was reset or CTRL-D pressed.
|
||||
* @retval FALSE operation successful.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
bool_t shellGetLine(BaseSequentialStream *chp, char *line, unsigned size) {
|
||||
char *p = line;
|
||||
|
||||
while (TRUE) {
|
||||
char c;
|
||||
|
||||
if (chSequentialStreamRead(chp, (uint8_t *)&c, 1) == 0)
|
||||
return TRUE;
|
||||
if (c == 4) {
|
||||
chprintf(chp, "^D");
|
||||
return TRUE;
|
||||
}
|
||||
if ((c == 8) || (c == 127)) {
|
||||
if (p != line) {
|
||||
chSequentialStreamPut(chp, c);
|
||||
chSequentialStreamPut(chp, 0x20);
|
||||
chSequentialStreamPut(chp, c);
|
||||
p--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '\r') {
|
||||
chprintf(chp, "\r\n");
|
||||
*p = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (c < 0x20)
|
||||
continue;
|
||||
if (p < line + size - 1) {
|
||||
chSequentialStreamPut(chp, c);
|
||||
*p++ = (char)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
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 shell.h
|
||||
* @brief Simple CLI shell header.
|
||||
*
|
||||
* @addtogroup SHELL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SHELL_H_
|
||||
#define _SHELL_H_
|
||||
|
||||
/**
|
||||
* @brief Shell maximum input line length.
|
||||
*/
|
||||
#if !defined(SHELL_MAX_LINE_LENGTH) || defined(__DOXYGEN__)
|
||||
#define SHELL_MAX_LINE_LENGTH 64
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Shell maximum arguments per command.
|
||||
*/
|
||||
#if !defined(SHELL_MAX_ARGUMENTS) || defined(__DOXYGEN__)
|
||||
#define SHELL_MAX_ARGUMENTS 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Command handler function type.
|
||||
*/
|
||||
typedef void (*shellcmd_t)(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Custom command entry type.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *sc_name; /**< @brief Command name. */
|
||||
shellcmd_t sc_function; /**< @brief Command function. */
|
||||
} ShellCommand;
|
||||
|
||||
/**
|
||||
* @brief Shell descriptor type.
|
||||
*/
|
||||
typedef struct {
|
||||
BaseSequentialStream *sc_channel; /**< @brief I/O channel associated
|
||||
to the shell. */
|
||||
const ShellCommand *sc_commands; /**< @brief Shell extra commands
|
||||
table. */
|
||||
} ShellConfig;
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern EventSource shell_terminated;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void shellInit(void);
|
||||
void shellExit(msg_t msg);
|
||||
Thread *shellCreate(const ShellConfig *scp, size_t size, tprio_t prio);
|
||||
Thread *shellCreateStatic(const ShellConfig *scp, void *wsp,
|
||||
size_t size, tprio_t prio);
|
||||
bool_t shellGetLine(BaseSequentialStream *chp, char *line, unsigned size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SHELL_H_ */
|
||||
|
||||
/** @} */
|
177
Software/portapack-mayhem/firmware/chibios/os/various/syscalls.c
Normal file
177
Software/portapack-mayhem/firmware/chibios/os/various/syscalls.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
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) 2009 by Michael Fischer. 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. Neither the name of the author nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
*
|
||||
****************************************************************************
|
||||
* History:
|
||||
*
|
||||
* 28.03.09 mifi First Version, based on the original syscall.c from
|
||||
* newlib version 1.17.0
|
||||
* 17.08.09 gdisirio Modified the file for use under ChibiOS/RT
|
||||
* 15.11.09 gdisirio Added read and write handling
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ch.h"
|
||||
#if defined(STDOUT_SD) || defined(STDIN_SD)
|
||||
#include "hal.h"
|
||||
#endif
|
||||
|
||||
#ifndef __errno_r
|
||||
#include <sys/reent.h>
|
||||
#define __errno_r(reent) reent->_errno
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _read_r(struct _reent *r, int file, char * ptr, int len)
|
||||
{
|
||||
(void)r;
|
||||
#if defined(STDIN_SD)
|
||||
if (!len || (file != 0)) {
|
||||
__errno_r(r) = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
len = sdRead(&STDIN_SD, (uint8_t *)ptr, (size_t)len);
|
||||
return len;
|
||||
#else
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)len;
|
||||
__errno_r(r) = EINVAL;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _lseek_r(struct _reent *r, int file, int ptr, int dir)
|
||||
{
|
||||
(void)r;
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)dir;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _write_r(struct _reent *r, int file, char * ptr, int len)
|
||||
{
|
||||
(void)r;
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
#if defined(STDOUT_SD)
|
||||
if (file != 1) {
|
||||
__errno_r(r) = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
sdWrite(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _close_r(struct _reent *r, int file)
|
||||
{
|
||||
(void)r;
|
||||
(void)file;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
caddr_t _sbrk_r(struct _reent *r, int incr)
|
||||
{
|
||||
#if CH_USE_MEMCORE
|
||||
void *p;
|
||||
|
||||
chDbgCheck(incr > 0, "_sbrk_r");
|
||||
|
||||
p = chCoreAlloc((size_t)incr);
|
||||
if (p == NULL) {
|
||||
__errno_r(r) = ENOMEM;
|
||||
return (caddr_t)-1;
|
||||
}
|
||||
return (caddr_t)p;
|
||||
#else
|
||||
(void)incr;
|
||||
__errno_r(r) = ENOMEM;
|
||||
return (caddr_t)-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _fstat_r(struct _reent *r, int file, struct stat * st)
|
||||
{
|
||||
(void)r;
|
||||
(void)file;
|
||||
|
||||
memset(st, 0, sizeof(*st));
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int _isatty_r(struct _reent *r, int fd)
|
||||
{
|
||||
(void)r;
|
||||
(void)fd;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*** EOF ***/
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup various Various
|
||||
*
|
||||
* @brief Utilities Library.
|
||||
* @details This is a collection of useful library code that is not part of
|
||||
* the base kernel services.
|
||||
* <h2>Notes</h2>
|
||||
* The library code does not follow the same naming convention of the
|
||||
* system APIs in order to make very clear that it is not "core" code.<br>
|
||||
* The main difference is that library code is not formally tested in the
|
||||
* test suite but through usage in the various demo applications.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cpp_library C++ Wrapper
|
||||
*
|
||||
* @brief C++ wrapper module.
|
||||
* @details This module allows to use the ChibiOS/RT functionalities
|
||||
* from C++ as classes and objects rather the traditional "C" APIs.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup memory_streams Memory Streams
|
||||
*
|
||||
* @brief Memory Streams.
|
||||
* @details This module allows to use a memory area (RAM or ROM) using a
|
||||
* @ref data_streams interface.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup event_timer Periodic Events Timer
|
||||
*
|
||||
* @brief Periodic Event Timer.
|
||||
* @details This timer generates an event at regular intervals. The
|
||||
* listening threads can use the event to perform time related
|
||||
* activities. Multiple threads can listen to the same timer.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup SHELL Command Shell
|
||||
*
|
||||
* @brief Small extendible command line shell.
|
||||
* @details This module implements a generic extendible command line interface.
|
||||
* The CLI just requires an I/O channel (@p BaseChannel), more
|
||||
* commands can be added to the shell using the configuration
|
||||
* structure.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup chrtclib RTC time conversion utilities
|
||||
*
|
||||
* @brief RTC time conversion utilities.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup chprintf System formatted print
|
||||
*
|
||||
* @brief System formatted print service.
|
||||
* @details This module implements printf()-like function able to send data
|
||||
* to any module implementing a @p BaseSequentialStream interface.
|
||||
*
|
||||
* @ingroup various
|
||||
*/
|
Reference in New Issue
Block a user