aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/src
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/src')
-rw-r--r--os/hal/src/adc.c7
-rw-r--r--os/hal/src/ext.c167
-rw-r--r--os/hal/src/gpt.c1
-rw-r--r--os/hal/src/hal.c3
-rw-r--r--os/hal/src/i2c.c178
-rw-r--r--os/hal/src/mac.c63
-rw-r--r--os/hal/src/rtc.c120
-rw-r--r--os/hal/src/serial_usb.c91
-rw-r--r--os/hal/src/usb.c107
9 files changed, 439 insertions, 298 deletions
diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c
index c375818a6..08aa830f0 100644
--- a/os/hal/src/adc.c
+++ b/os/hal/src/adc.c
@@ -162,6 +162,8 @@ void adcStartConversion(ADCDriver *adcp,
/**
* @brief Starts an ADC conversion.
* @details Starts an asynchronous conversion operation.
+ * @post The callbacks associated to the conversion group will be invoked
+ * on buffer fill and error events.
* @note The buffer is organized as a matrix of M*N elements where M is the
* channels number configured into the conversion group and N is the
* buffer depth. The samples are sequentially written into the buffer
@@ -185,7 +187,8 @@ void adcStartConversionI(ADCDriver *adcp,
((depth == 1) || ((depth & 1) == 0)),
"adcStartConversionI");
chDbgAssert((adcp->state == ADC_READY) ||
- (adcp->state == ADC_COMPLETE),
+ (adcp->state == ADC_COMPLETE) ||
+ (adcp->state == ADC_ERROR),
"adcStartConversionI(), #1", "not ready");
adcp->samples = samples;
@@ -268,6 +271,8 @@ void adcStopConversionI(ADCDriver *adcp) {
* @retval RDY_RESET The conversion has been stopped using
* @p acdStopConversion() or @p acdStopConversionI(),
* the result buffer may contain incorrect data.
+ * @retval RDY_TIMEOUT The conversion has been stopped because an hardware
+ * error.
*
* @api
*/
diff --git a/os/hal/src/ext.c b/os/hal/src/ext.c
new file mode 100644
index 000000000..1c83cd2e6
--- /dev/null
+++ b/os/hal/src/ext.c
@@ -0,0 +1,167 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ext.c
+ * @brief EXT Driver code.
+ *
+ * @addtogroup EXT
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_EXT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief EXT Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void extInit(void) {
+
+ ext_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p EXTDriver structure.
+ *
+ * @param[out] extp pointer to the @p EXTDriver object
+ *
+ * @init
+ */
+void extObjectInit(EXTDriver *extp) {
+
+ extp->state = EXT_STOP;
+ extp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the EXT peripheral.
+ * @post After activation all EXT channels are in the disabled state,
+ * use @p extChannelEnable() in order to activate them.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ * @param[in] config pointer to the @p EXTConfig object
+ *
+ * @api
+ */
+void extStart(EXTDriver *extp, const EXTConfig *config) {
+
+ chDbgCheck((extp != NULL) && (config != NULL), "extStart");
+
+ chSysLock();
+ chDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE),
+ "extStart(), #1", "invalid state");
+ extp->config = config;
+ ext_lld_start(extp);
+ extp->state = EXT_ACTIVE;
+ chSysUnlock();
+}
+
+/**
+ * @brief Deactivates the EXT peripheral.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ *
+ * @api
+ */
+void extStop(EXTDriver *extp) {
+
+ chDbgCheck(extp != NULL, "extStop");
+
+ chSysLock();
+ chDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE),
+ "extStop(), #1", "invalid state");
+ ext_lld_stop(extp);
+ extp->state = EXT_STOP;
+ chSysUnlock();
+}
+
+/**
+ * @brief Enables an EXT channel.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ * @param[in] channel channel to be enabled
+ *
+ * @api
+ */
+void extChannelEnable(EXTDriver *extp, expchannel_t channel) {
+
+ chDbgCheck((extp != NULL) &&
+ (channel < EXT_MAX_CHANNELS) &&
+ (extp->config->channels[channel].mode != EXT_CH_MODE_DISABLED),
+ "extChannelEnable");
+
+ chSysLock();
+ chDbgAssert(extp->state == EXT_ACTIVE,
+ "extChannelEnable(), #1", "invalid state");
+ extChannelEnableI(extp, channel);
+ chSysUnlock();
+}
+
+/**
+ * @brief Disables an EXT channel.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ * @param[in] channel channel to be disabled
+ *
+ * @api
+ */
+void extChannelDisable(EXTDriver *extp, expchannel_t channel) {
+
+ chDbgCheck((extp != NULL) &&
+ (channel < EXT_MAX_CHANNELS) &&
+ (extp->config->channels[channel].mode != EXT_CH_MODE_DISABLED),
+ "extChannelDisable");
+
+ chSysLock();
+ chDbgAssert(extp->state == EXT_ACTIVE,
+ "extChannelDisable(), #1", "invalid state");
+ extChannelDisableI(extp, channel);
+ chSysUnlock();
+}
+
+#endif /* HAL_USE_EXT */
+
+/** @} */
diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c
index c677f5284..726936ca8 100644
--- a/os/hal/src/gpt.c
+++ b/os/hal/src/gpt.c
@@ -236,6 +236,7 @@ void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) {
gptp->state = GPT_ONESHOT;
gpt_lld_polled_delay(gptp, interval);
+ gptp->state = GPT_READY;
}
#endif /* HAL_USE_GPT */
diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c
index 3c8fb2fe6..d5a8082e9 100644
--- a/os/hal/src/hal.c
+++ b/os/hal/src/hal.c
@@ -71,6 +71,9 @@ void halInit(void) {
#if HAL_USE_CAN || defined(__DOXYGEN__)
canInit();
#endif
+#if HAL_USE_EXT || defined(__DOXYGEN__)
+ extInit();
+#endif
#if HAL_USE_GPT || defined(__DOXYGEN__)
gptInit();
#endif
diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c
index 9ce2cc76f..f7f7c335e 100644
--- a/os/hal/src/i2c.c
+++ b/os/hal/src/i2c.c
@@ -73,15 +73,9 @@ void i2cObjectInit(I2CDriver *i2cp) {
i2cp->id_state = I2C_STOP;
i2cp->id_config = NULL;
- i2cp->rxbuff_p = NULL;
- i2cp->txbuff_p = NULL;
i2cp->rxbuf = NULL;
i2cp->txbuf = NULL;
- i2cp->id_slave_config = NULL;
-
-#if I2C_USE_WAIT
i2cp->id_thread = NULL;
-#endif /* I2C_USE_WAIT */
#if I2C_USE_MUTUAL_EXCLUSION
#if CH_USE_MUTEXES
@@ -111,10 +105,6 @@ void i2cStart(I2CDriver *i2cp, const I2CConfig *config) {
"i2cStart(), #1",
"invalid state");
-#if (!(STM32_I2C_I2C2_USE_POLLING_WAIT) && I2C_SUPPORTS_CALLBACKS)
- gptStart(i2cp->timer, i2cp->timer_cfg);
-#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */
-
chSysLock();
i2cp->id_config = config;
i2c_lld_start(i2cp);
@@ -136,10 +126,6 @@ void i2cStop(I2CDriver *i2cp) {
"i2cStop(), #1",
"invalid state");
-#if (!(STM32_I2C_I2C2_USE_POLLING_WAIT) && I2C_SUPPORTS_CALLBACKS)
- gptStop(i2cp->timer);
-#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */
-
chSysLock();
i2c_lld_stop(i2cp);
i2cp->id_state = I2C_STOP;
@@ -147,145 +133,94 @@ void i2cStop(I2CDriver *i2cp) {
}
/**
- * @brief Sends data via the I2C bus.
- *
+ * @brief Sends data via the I2C bus.
* @details Function designed to realize "read-through-write" transfer
* paradigm. If you want transmit data without any further read,
* than set @b rxbytes field to 0.
*
* @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cscfg pointer to the @p I2C slave config
- * @param[in] slave_addr Slave device address. Bits 0-9 contain slave
- * device address. Bit 15 must be set to 1 if 10-bit
- * addressing mode used. Otherwise keep it cleared.
- * Bits 10-14 unused.
+ * @param[in] slave_addr Slave device address (7 bits) without R/W bit
* @param[in] txbuf pointer to transmit buffer
* @param[in] txbytes number of bytes to be transmitted
* @param[in] rxbuf pointer to receive buffer
* @param[in] rxbytes number of bytes to be received, set it to 0 if
* you want transmit only
+ * @param[in] errors pointer to variable to store error code, zero means
+ * no error.
+ * @param[in] timeout operation timeout
+ *
+ * @return timeout status
+ * @retval RDY_OK if timeout not reached
+ * @retval RDY_TIMEOUT if a timeout occurs
*/
-void i2cMasterTransmit(I2CDriver *i2cp,
- const I2CSlaveConfig *i2cscfg,
- uint16_t slave_addr,
- uint8_t *txbuf,
- size_t txbytes,
- uint8_t *rxbuf,
- size_t rxbytes) {
-
- chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\
- (slave_addr != 0) &&\
- (txbytes > 0) &&\
- (txbuf != NULL),
- "i2cMasterTransmit");
-
- /* init slave config field in driver */
- i2cp->id_slave_config = i2cscfg;
-
- i2c_lld_wait_bus_free(i2cp);
- chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out");
-
+msg_t i2cMasterTransmit(I2CDriver *i2cp,
+ uint8_t slave_addr,
+ uint8_t *txbuf,
+ size_t txbytes,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ i2cflags_t *errors,
+ systime_t timeout) {
+ msg_t rdymsg;
+
+ chDbgCheck((i2cp != NULL) && (slave_addr != 0) &&
+ (txbytes > 0) && (txbuf != NULL) &&
+ ((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL))) &&
+ (timeout > TIME_IMMEDIATE) && (errors != NULL),
+ "i2cMasterTransmit");
+ i2cp->errors = I2CD_NO_ERROR; /* clear error flags from previous run */
chDbgAssert(i2cp->id_state == I2C_READY,
"i2cMasterTransmit(), #1", "not ready");
i2cp->id_state = I2C_ACTIVE_TRANSMIT;
i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes);
-#if I2C_SUPPORTS_CALLBACKS
- _i2c_wait_s(i2cp);
-#else
- i2cp->id_state = I2C_READY;
-#endif /* I2C_SUPPORTS_CALLBACKS */
+ _i2c_wait_s(i2cp, timeout, rdymsg);
+
+ *errors = i2cp->errors;
+
+ return rdymsg;
}
/**
- * @brief Receives data from the I2C bus.
+ * @brief Receives data from the I2C bus.
*
* @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cscfg pointer to the @p I2C slave config
- * @param[in] slave_addr Slave device address. Bits 0-9 contain slave
- * device address. Bit 15 must be set to 1 if 10-bit
- * addressing mode used. Otherwise keep it cleared.
- * Bits 10-14 unused.
+ * @param[in] slave_addr slave device address (7 bits) without R/W bit
* @param[in] rxbytes number of bytes to be received
* @param[in] rxbuf pointer to receive buffer
+ * @param[in] errors pointer to variable to store error code, zero means
+ * no error.
+ * @param[in] timeout operation timeout
+ *
+ * @return timeout status
+ * @retval RDY_OK if timeout not reached
+ * @retval RDY_TIMEOUT if a timeout occurs
*/
-void i2cMasterReceive(I2CDriver *i2cp,
- const I2CSlaveConfig *i2cscfg,
- uint16_t slave_addr,
- uint8_t *rxbuf,
- size_t rxbytes){
-
- chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\
- (slave_addr != 0) &&\
- (rxbytes > 0) && \
- (rxbuf != NULL),
- "i2cMasterReceive");
-
- /* init slave config field in driver */
- i2cp->id_slave_config = i2cscfg;
-
- i2c_lld_wait_bus_free(i2cp);
- chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out");
-
+msg_t i2cMasterReceive(I2CDriver *i2cp,
+ uint8_t slave_addr,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ i2cflags_t *errors,
+ systime_t timeout){
+
+ msg_t rdymsg;
+
+ chDbgCheck((i2cp != NULL) && (slave_addr != 0) &&
+ (rxbytes > 0) && (rxbuf != NULL) &&
+ (timeout > TIME_IMMEDIATE) && (errors != NULL),
+ "i2cMasterReceive");
+ i2cp->errors = I2CD_NO_ERROR; /* clear error flags from previous run */
chDbgAssert(i2cp->id_state == I2C_READY,
"i2cMasterReceive(), #1", "not ready");
i2cp->id_state = I2C_ACTIVE_RECEIVE;
i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes);
-#if I2C_SUPPORTS_CALLBACKS
- _i2c_wait_s(i2cp);
-#else
- i2cp->id_state = I2C_READY;
-#endif /* I2C_SUPPORTS_CALLBACKS */
-}
+ _i2c_wait_s(i2cp, timeout, rdymsg);
+ *errors = i2cp->errors;
-/* FIXME: I do not know what this function must do. And can not test it
-uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) {
- i2cMasterReceive(i2cp, i2cscfg);
- return i2cp->id_slave_config->slave_addr;
+ return rdymsg;
}
-*/
-
-/**
- * @brief Handles communication events/errors.
- * @details Must be called from the I/O interrupt service routine in order to
- * notify I/O conditions as errors, signals change etc.
- *
- * @param[in] i2cp pointer to a @p I2CDriver structure
- * @param[in] mask condition flags to be added to the mask
- *
- * @iclass
- */
-void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) {
-
- chDbgCheck(i2cp != NULL, "i2cAddFlagsI");
-
- i2cp->errors |= mask;
- chEvtBroadcastI(&i2cp->sevent);
-}
-
-/**
- * @brief Returns and clears the errors mask associated to the driver.
- *
- * @param[in] i2cp pointer to a @p I2CDriver structure
- * @return The condition flags modified since last time this
- * function was invoked.
- *
- * @api
- */
-i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp) {
- i2cflags_t mask;
-
- chDbgCheck(i2cp != NULL, "i2cGetAndClearFlags");
-
- chSysLock();
- mask = i2cp->errors;
- i2cp->errors = I2CD_NO_ERROR;
- chSysUnlock();
- return mask;
-}
-
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
@@ -323,7 +258,6 @@ void i2cReleaseBus(I2CDriver *i2cp) {
chDbgCheck(i2cp != NULL, "i2cReleaseBus");
#if CH_USE_MUTEXES
- (void)i2cp;
chMtxUnlock();
#elif CH_USE_SEMAPHORES
chSemSignal(&i2cp->id_semaphore);
diff --git a/os/hal/src/mac.c b/os/hal/src/mac.c
index 0f1c47576..edd15d087 100644
--- a/os/hal/src/mac.c
+++ b/os/hal/src/mac.c
@@ -21,8 +21,6 @@
/**
* @file mac.c
* @brief MAC Driver code.
- * @note This function is implicitly invoked by @p halInit(), there is
- * no need to explicitly initialize the driver.
*
* @addtogroup MAC
* @{
@@ -59,6 +57,8 @@
/**
* @brief MAC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
*
* @init
*/
@@ -76,28 +76,53 @@ void macInit(void) {
*/
void macObjectInit(MACDriver *macp) {
+ macp->state = MAC_STOP;
+ macp->config = NULL;
chSemInit(&macp->tdsem, 0);
chSemInit(&macp->rdsem, 0);
-#if CH_USE_EVENTS
+#if MAC_USE_EVENTS
chEvtInit(&macp->rdevent);
#endif
}
/**
- * @brief MAC address setup.
- * @pre This function must be invoked with the driver in the stopped
- * state. If invoked on an active interface then it is ignored.
+ * @brief Configures and activates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[in] config pointer to the @p MACConfig object
+ *
+ * @api
+ */
+void macStart(MACDriver *macp, const MACConfig *config) {
+
+ chDbgCheck((macp != NULL) && (config != NULL), "macStart");
+
+ chSysLock();
+ chDbgAssert(macp->state == MAC_STOP,
+ "macStart(), #1", "invalid state");
+ macp->config = config;
+ mac_lld_start(macp);
+ macp->state = MAC_ACTIVE;
+ chSysUnlock();
+}
+
+/**
+ * @brief Deactivates the MAC peripheral.
*
* @param[in] macp pointer to the @p MACDriver object
- * @param[in] p pointer to a six bytes buffer containing the MAC
- * address. If this parameter is set to @p NULL then MAC
- * a system default is used.
*
* @api
*/
-void macSetAddress(MACDriver *macp, const uint8_t *p) {
+void macStop(MACDriver *macp) {
+
+ chDbgCheck(macp != NULL, "macStop");
- mac_lld_set_address(macp, p);
+ chSysLock();
+ chDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE),
+ "macStop(), #1", "invalid state");
+ mac_lld_stop(macp);
+ macp->state = MAC_STOP;
+ chSysUnlock();
}
/**
@@ -124,6 +149,10 @@ msg_t macWaitTransmitDescriptor(MACDriver *macp,
systime_t time) {
msg_t msg;
+ chDbgCheck((macp != NULL) && (tdp != NULL), "macWaitTransmitDescriptor");
+ chDbgAssert(macp->state == MAC_ACTIVE, "macWaitTransmitDescriptor(), #1",
+ "not active");
+
while (((msg = max_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) &&
(time > 0)) {
chSysLock();
@@ -149,6 +178,8 @@ msg_t macWaitTransmitDescriptor(MACDriver *macp,
*/
void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) {
+ chDbgCheck((tdp != NULL), "macReleaseTransmitDescriptor");
+
mac_lld_release_transmit_descriptor(tdp);
}
@@ -176,6 +207,10 @@ msg_t macWaitReceiveDescriptor(MACDriver *macp,
systime_t time) {
msg_t msg;
+ chDbgCheck((macp != NULL) && (rdp != NULL), "macWaitReceiveDescriptor");
+ chDbgAssert(macp->state == MAC_ACTIVE, "macWaitReceiveDescriptor(), #1",
+ "not active");
+
while (((msg = max_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) &&
(time > 0)) {
chSysLock();
@@ -202,6 +237,8 @@ msg_t macWaitReceiveDescriptor(MACDriver *macp,
*/
void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) {
+ chDbgCheck((rdp != NULL), "macReleaseReceiveDescriptor");
+
mac_lld_release_receive_descriptor(rdp);
}
@@ -217,6 +254,10 @@ void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) {
*/
bool_t macPollLinkStatus(MACDriver *macp) {
+ chDbgCheck((macp != NULL), "macPollLinkStatus");
+ chDbgAssert(macp->state == MAC_ACTIVE, "macPollLinkStatus(), #1",
+ "not active");
+
return mac_lld_poll_link_status(macp);
}
diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c
index 1341bb2dd..dda5a9c95 100644
--- a/os/hal/src/rtc.c
+++ b/os/hal/src/rtc.c
@@ -20,7 +20,7 @@
/**
* @file rtc.c
- * @brief Real Time Clock Abstraction Layer code.
+ * @brief RTC Driver code.
*
* @addtogroup RTC
* @{
@@ -29,8 +29,6 @@
#include "ch.h"
#include "hal.h"
-#include "rtc_lld.h"
-
#if HAL_USE_RTC || defined(__DOXYGEN__)
/*===========================================================================*/
@@ -52,75 +50,109 @@
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
+
/**
- * @brief Enable access to registers and initialize RTC if BKP doamin
- * was previously reseted.
+ * @brief RTC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
*/
-void rtcInit(void){
+void rtcInit(void) {
+
rtc_lld_init();
}
/**
- * @brief Configure and start interrupt servicing routines.
- * This function do nothing if callbacks disabled.
+ * @brief Set current time.
*
- * @param[in] rtcp - pointer to RTC driver structure.
- * @param[in] rtccfgp - pointer to RTC config structure.
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCTime structure
+ *
+ * @api
*/
-#if RTC_SUPPORTS_CALLBACKS
-void rtcStartI(RTCDriver *rtcp, const RTCConfig *rtccfgp){
- chDbgCheckClassI();
- chDbgCheck(((rtcp != NULL) && (rtccfgp != NULL)), "rtcStart");
- rtc_lld_start(rtcp, rtccfgp);
-}
+void rtcSetTime(RTCDriver *rtcp, const RTCTime *timespec) {
-/**
- * @brief Stop interrupt servicing routines.
- */
-void rtcStopI(void){
- chDbgCheckClassI();
- rtc_lld_stop();
-}
-#endif /* RTC_SUPPORTS_CALLBACKS */
+ chDbgCheck((rtcp != NULL) && (timespec != NULL), "rtcSetTime");
-/**
- * @brief Set current time.
- * @param[in] tv_sec - time value in UNIX notation.
- */
-void rtcSetTime(uint32_t tv_sec){
- rtc_lld_set_time(tv_sec);
+ rtc_lld_set_time(rtcp, timespec);
}
/**
- * @brief Return current time in UNIX notation.
+ * @brief Get current time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timespec pointer to a @p RTCTime structure
+ *
+ * @api
*/
-inline uint32_t rtcGetSec(void){
- return rtc_lld_get_sec();
+void rtcGetTime(RTCDriver *rtcp, RTCTime *timespec) {
+
+ chDbgCheck((rtcp != NULL) && (timespec != NULL), "rtcGetTime");
+
+ rtc_lld_get_time(rtcp, timespec);
}
+#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
/**
- * @brief Return fractional part of current time (milliseconds).
+ * @brief Set alarm time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL
+ *
+ * @api
*/
-inline uint16_t rtcGetMsec(void){
- return rtc_lld_get_msec();
+void rtcSetAlarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec) {
+
+ chDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS), "rtcSetAlarm");
+
+ rtc_lld_set_alarm(rtcp, alarm, alarmspec);
}
/**
- * @brief Set alarm date in UNIX notation.
+ * @brief Get current alarm.
+ * @note If an alarm has not been set then the returned alarm specification
+ * is not meaningful.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @api
*/
-void rtcSetAlarm(uint32_t tv_alarm){
- rtc_lld_set_alarm(tv_alarm);
+void rtcGetAlarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec) {
+
+ chDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS) && (alarmspec != NULL),
+ "rtcGetAlarm");
+
+ rtc_lld_get_alarm(rtcp, alarm, alarmspec);
}
+#endif /* RTC_ALARMS > 0 */
+#if RTC_SUPPORTS_CALLBACKS || defined(__DOXYGEN__)
/**
- * @brief Get current alarm date in UNIX notation.
+ * @brief Enables or disables RTC callbacks.
+ * @details This function enables or disables callbacks, use a @p NULL pointer
+ * in order to disable a callback.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @api
*/
-inline uint32_t rtcGetAlarm(void){
- return rtc_lld_get_alarm();
+void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) {
+
+ chDbgCheck((rtcp != NULL), "rtcSetCallback");
+
+ rtc_lld_set_callback(rtcp, callback);
}
+#endif /* RTC_SUPPORTS_CALLBACKS */
#endif /* HAL_USE_RTC */
/** @} */
-
-
diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c
index 16822502a..ea434b197 100644
--- a/os/hal/src/serial_usb.c
+++ b/os/hal/src/serial_usb.c
@@ -118,21 +118,26 @@ static const struct SerialUSBDriverVMT vmt = {
*/
static void inotify(GenericQueue *qp) {
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
- size_t n;
/* Writes to the input queue can only happen when the queue has been
emptied, then a whole packet is loaded in the queue.*/
- if (chIQIsEmptyI(&sdup->iqueue)) {
-
- n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP,
- sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE);
- if (n != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
+ chIQIsEmptyI(&sdup->iqueue)) {
+ chSysUnlock();
+
+ /* Unlocked to make the potentially long read operation preemptable.*/
+ size_t n = usbReadPacketBuffer(sdup->config->usbp,
+ USB_CDC_DATA_AVAILABLE_EP,
+ sdup->iqueue.q_buffer,
+ SERIAL_USB_BUFFERS_SIZE);
+
+ chSysLock();
+ usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
+ chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
+ sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
+ sdup->iqueue.q_counter = n;
+ while (notempty(&sdup->iqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
}
@@ -141,14 +146,20 @@ static void inotify(GenericQueue *qp) {
*/
static void onotify(GenericQueue *qp) {
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr;
- size_t w, n;
+ size_t n;
/* If there is any data in the output queue then it is sent within a
single packet and the queue is emptied.*/
n = chOQGetFullI(&sdup->oqueue);
- w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
- sdup->oqueue.q_buffer, n);
- if (w != USB_ENDPOINT_BUSY) {
+ if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) {
+ chSysUnlock();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
+ sdup->oqueue.q_buffer, n);
+
+ chSysLock();
+ usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
@@ -285,21 +296,27 @@ bool_t sduRequestsHook(USBDriver *usbp) {
*/
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
SerialUSBDriver *sdup = usbp->param;
- size_t n, w;
+ size_t n;
chSysLockFromIsr();
/* If there is any data in the output queue then it is sent within a
single packet and the queue is emptied.*/
n = chOQGetFullI(&sdup->oqueue);
if (n > 0) {
- w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n);
- if (w != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
- sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
- sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
- while (notempty(&sdup->oqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ chSysUnlockFromIsr();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n);
+
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, ep);
+ chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
+ sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
+ sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
+ while (notempty(&sdup->oqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
chSysUnlockFromIsr();
}
@@ -319,17 +336,23 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
/* Writes to the input queue can only happen when the queue has been
emptied, then a whole packet is loaded in the queue.*/
if (chIQIsEmptyI(&sdup->iqueue)) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so a packet is in the buffer for sure.*/
size_t n;
- n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer,
- SERIAL_USB_BUFFERS_SIZE);
- if (n != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ chSysUnlockFromIsr();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer,
+ SERIAL_USB_BUFFERS_SIZE);
+
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, ep);
+ chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
+ sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
+ sdup->iqueue.q_counter = n;
+ while (notempty(&sdup->iqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
chSysUnlockFromIsr();
}
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c
index 44a772ab1..30919580c 100644
--- a/os/hal/src/usb.c
+++ b/os/hal/src/usb.c
@@ -309,7 +309,7 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI");
chDbgAssert(usbp->state == USB_ACTIVE,
"usbEnableEndpointI(), #1", "invalid state");
- chDbgAssert(usbp->epc[ep] != NULL,
+ chDbgAssert(usbp->epc[ep] == NULL,
"usbEnableEndpointI(), #2", "already initialized");
/* Logically enabling the endpoint in the USBDriver structure.*/
@@ -352,126 +352,54 @@ void usbDisableEndpointsI(USBDriver *usbp) {
}
/**
- * @brief Reads a packet from the dedicated packet buffer.
- * @pre In order to use this function he endpoint must have been
- * initialized in packet mode.
- * @post The endpoint is ready to accept another packet.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the packet data
- * @param[in] n maximum number of bytes to copy. This value must
- * not exceed the maximum packet size for this endpoint.
- * @return The received packet size regardless the specified
- * @p n parameter.
- * @retval USB_ENDPOINT_BUSY Endpoint busy receiving.
- * @retval 0 Zero size packet received.
- *
- * @iclass
- */
-size_t usbReadPacketI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
-
- chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbReadPacketI");
-
- if (usbGetReceiveStatusI(usbp, ep))
- return USB_ENDPOINT_BUSY;
-
- usbp->receiving |= (1 << ep);
- return usb_lld_read_packet(usbp, ep, buf, n);;
-}
-
-/**
- * @brief Writes a packet to the dedicated packet buffer.
- * @pre In order to use this function he endpoint must have been
- * initialized in packet mode.
- * @post The endpoint is ready to transmit the packet.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the packet data
- * @param[in] n maximum number of bytes to copy. This value must
- * not exceed the maximum packet size for this endpoint.
- * @return The operation status.
- * @retval USB_ENDPOINT_BUSY Endpoint busy transmitting.
- * @retval 0 Operation complete.
- *
- * @iclass
- */
-size_t usbWritePacketI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
-
- chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbWritePacketI");
-
- if (usbGetTransmitStatusI(usbp, ep))
- return USB_ENDPOINT_BUSY;
-
- usbp->transmitting |= (1 << ep);
- usb_lld_write_packet(usbp, ep, buf, n);
- return 0;
-}
-
-/**
* @brief Starts a receive transaction on an OUT endpoint.
- * @pre In order to use this function he endpoint must have been
- * initialized in transaction mode.
* @post The endpoint callback is invoked when the transfer has been
* completed.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the received data
- * @param[in] n maximum number of bytes to copy
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
*
* @iclass
*/
-bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartReceiveI");
+ chDbgCheck(usbp != NULL, "usbStartReceiveI");
if (usbGetReceiveStatusI(usbp, ep))
return TRUE;
usbp->receiving |= (1 << ep);
- usb_lld_start_out(usbp, ep, buf, n);
+ usb_lld_start_out(usbp, ep);
return FALSE;
}
/**
* @brief Starts a transmit transaction on an IN endpoint.
- * @pre In order to use this function he endpoint must have been
- * initialized in transaction mode.
* @post The endpoint callback is invoked when the transfer has been
* completed.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the data to be transmitted
- * @param[in] n maximum number of bytes to copy
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
*
* @iclass
*/
-bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartTransmitI");
+ chDbgCheck(usbp != NULL, "usbStartTransmitI");
if (usbGetTransmitStatusI(usbp, ep))
return TRUE;
usbp->transmitting |= (1 << ep);
- usb_lld_start_in(usbp, ep, buf, n);
+ usb_lld_start_in(usbp, ep);
return FALSE;
}
@@ -597,13 +525,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n > 0) {
/* Starts the transmit phase.*/
usbp->ep0state = USB_EP0_TX;
- usb_lld_start_in(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_prepare_transmit(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_start_in(usbp, 0);
}
else {
/* No transmission phase, directly receiving the zero sized status
packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_start_out(usbp, 0, NULL, 0);
+ usb_lld_prepare_receive(usbp, 0, NULL, 0);
+ usb_lld_start_out(usbp, 0);
}
}
else {
@@ -611,13 +541,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n > 0) {
/* Starts the receive phase.*/
usbp->ep0state = USB_EP0_RX;
- usb_lld_start_out(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_prepare_receive(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_start_out(usbp, 0);
}
else {
/* No receive phase, directly sending the zero sized status
packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
}
}
}
@@ -644,13 +576,15 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
transmitted.*/
if ((usbp->ep0n < max) &&
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
return;
}
/* Transmit phase over, receiving the zero sized status packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_start_out(usbp, 0, NULL, 0);
+ usb_lld_prepare_receive(usbp, 0, NULL, 0);
+ usb_lld_start_out(usbp, 0);
return;
case USB_EP0_SENDING_STS:
/* Status packet sent, invoking the callback if defined.*/
@@ -687,7 +621,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
case USB_EP0_RX:
/* Receive phase over, sending the zero sized status packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
return;
case USB_EP0_WAITING_STS:
/* Status packet received, it must be zero sized, invoking the callback