diff options
Diffstat (limited to 'os/hal/src')
| -rw-r--r-- | os/hal/src/adc.c | 7 | ||||
| -rw-r--r-- | os/hal/src/ext.c | 167 | ||||
| -rw-r--r-- | os/hal/src/gpt.c | 1 | ||||
| -rw-r--r-- | os/hal/src/hal.c | 3 | ||||
| -rw-r--r-- | os/hal/src/i2c.c | 178 | ||||
| -rw-r--r-- | os/hal/src/mac.c | 63 | ||||
| -rw-r--r-- | os/hal/src/rtc.c | 120 | ||||
| -rw-r--r-- | os/hal/src/serial_usb.c | 91 | ||||
| -rw-r--r-- | os/hal/src/usb.c | 107 | 
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
  | 
